@powersync/op-sqlite 0.0.0-dev-20241014170110 → 0.0.0-dev-20250121082529
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 +62 -1
- package/android/build.gradle +1 -1
- package/android/src/main/java/com/powersync/opsqlite/PowerSyncOpSqlitePackage.kt +4 -8
- package/ios/PowerSyncOpSqlite.mm +0 -5
- package/lib/commonjs/db/OPSQLiteConnection.js +47 -21
- package/lib/commonjs/db/OPSQLiteConnection.js.map +1 -1
- package/lib/commonjs/db/OPSqliteAdapter.js +87 -52
- package/lib/commonjs/db/OPSqliteAdapter.js.map +1 -1
- package/lib/commonjs/db/SqliteOptions.js +3 -1
- package/lib/commonjs/db/SqliteOptions.js.map +1 -1
- package/lib/commonjs/index.js +0 -16
- package/lib/commonjs/index.js.map +1 -1
- package/lib/module/db/OPSQLiteConnection.js +47 -21
- package/lib/module/db/OPSQLiteConnection.js.map +1 -1
- package/lib/module/db/OPSqliteAdapter.js +89 -54
- package/lib/module/db/OPSqliteAdapter.js.map +1 -1
- package/lib/module/db/SqliteOptions.js +3 -1
- package/lib/module/db/SqliteOptions.js.map +1 -1
- package/lib/module/index.js +0 -15
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/commonjs/src/db/OPSQLiteConnection.d.ts +11 -1
- package/lib/typescript/commonjs/src/db/OPSQLiteConnection.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/db/OPSqliteAdapter.d.ts +11 -3
- package/lib/typescript/commonjs/src/db/OPSqliteAdapter.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/db/SqliteOptions.d.ts +13 -0
- package/lib/typescript/commonjs/src/db/SqliteOptions.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/index.d.ts +0 -1
- package/lib/typescript/commonjs/src/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/tsconfig.build.tsbuildinfo +1 -1
- package/lib/typescript/module/src/db/OPSQLiteConnection.d.ts +11 -1
- package/lib/typescript/module/src/db/OPSQLiteConnection.d.ts.map +1 -1
- package/lib/typescript/module/src/db/OPSqliteAdapter.d.ts +11 -3
- package/lib/typescript/module/src/db/OPSqliteAdapter.d.ts.map +1 -1
- package/lib/typescript/module/src/db/SqliteOptions.d.ts +13 -0
- package/lib/typescript/module/src/db/SqliteOptions.d.ts.map +1 -1
- package/lib/typescript/module/src/index.d.ts +0 -1
- package/lib/typescript/module/src/index.d.ts.map +1 -1
- package/lib/typescript/module/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +7 -7
- package/powersync-op-sqlite.podspec +2 -2
- package/src/db/OPSQLiteConnection.ts +73 -24
- package/src/db/OPSqliteAdapter.ts +109 -69
- package/src/db/SqliteOptions.ts +19 -2
- package/src/index.ts +4 -30
- package/android/src/main/java/com/powersync/opsqlite/PowerSyncOpSqliteModule.kt +0 -25
- package/android/src/newarch/PowerSyncOpSqliteSpec.kt +0 -7
- package/android/src/oldarch/PowerSyncOpSqliteSpec.kt +0 -11
- package/lib/commonjs/NativePowerSyncOpSqlite.js +0 -9
- package/lib/commonjs/NativePowerSyncOpSqlite.js.map +0 -1
- package/lib/module/NativePowerSyncOpSqlite.js +0 -5
- package/lib/module/NativePowerSyncOpSqlite.js.map +0 -1
- package/lib/typescript/commonjs/src/NativePowerSyncOpSqlite.d.ts +0 -7
- package/lib/typescript/commonjs/src/NativePowerSyncOpSqlite.d.ts.map +0 -1
- package/lib/typescript/module/src/NativePowerSyncOpSqlite.d.ts +0 -7
- package/lib/typescript/module/src/NativePowerSyncOpSqlite.d.ts.map +0 -1
- package/src/NativePowerSyncOpSqlite.ts +0 -8
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@powersync/op-sqlite",
|
|
3
|
-
"version": "0.0.0-dev-
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.0.0-dev-20250121082529",
|
|
4
|
+
"description": "PowerSync - sync Postgres or MongoDB with SQLite in your React Native app for offline-first and real-time data",
|
|
5
5
|
"source": "./src/index.ts",
|
|
6
6
|
"main": "./lib/commonjs/index.js",
|
|
7
7
|
"module": "./lib/module/index.js",
|
|
@@ -58,17 +58,17 @@
|
|
|
58
58
|
"access": "public"
|
|
59
59
|
},
|
|
60
60
|
"peerDependencies": {
|
|
61
|
-
"@op-engineering/op-sqlite": "^
|
|
62
|
-
"@powersync/common": "^1.
|
|
61
|
+
"@op-engineering/op-sqlite": "^11.2.13",
|
|
62
|
+
"@powersync/common": "^1.22.2",
|
|
63
63
|
"react": "*",
|
|
64
64
|
"react-native": "*"
|
|
65
65
|
},
|
|
66
66
|
"dependencies": {
|
|
67
67
|
"async-lock": "^1.4.0",
|
|
68
|
-
"@powersync/common": "1.
|
|
68
|
+
"@powersync/common": "1.22.2"
|
|
69
69
|
},
|
|
70
70
|
"devDependencies": {
|
|
71
|
-
"@op-engineering/op-sqlite": "^
|
|
71
|
+
"@op-engineering/op-sqlite": "^11.2.13",
|
|
72
72
|
"@react-native/eslint-config": "^0.73.1",
|
|
73
73
|
"@types/async-lock": "^1.4.0",
|
|
74
74
|
"@types/react": "^18.2.44",
|
|
@@ -131,6 +131,6 @@
|
|
|
131
131
|
"build:prod": "bob build",
|
|
132
132
|
"typecheck": "tsc",
|
|
133
133
|
"lint": "eslint \"**/*.{js,ts,tsx}\"",
|
|
134
|
-
"clean": "del-cli android/build example/android/build example/android/app/build example/ios/build lib"
|
|
134
|
+
"clean": "del-cli android/build example/android/build example/android/app/build example/ios/build lib node_modules"
|
|
135
135
|
}
|
|
136
136
|
}
|
|
@@ -11,13 +11,13 @@ Pod::Spec.new do |s|
|
|
|
11
11
|
s.authors = package["author"]
|
|
12
12
|
|
|
13
13
|
s.platforms = { :ios => min_ios_version_supported }
|
|
14
|
-
s.source = { :git => "https://github.com/
|
|
14
|
+
s.source = { :git => "https://github.com/powersync-ja/powersync-js.git", :tag => "#{s.version}" }
|
|
15
15
|
|
|
16
16
|
s.source_files = "ios/**/*.{h,m,mm,cpp}"
|
|
17
17
|
|
|
18
18
|
s.dependency "React-callinvoker"
|
|
19
19
|
s.dependency "React"
|
|
20
|
-
s.dependency "powersync-sqlite-core", "~> 0.3.
|
|
20
|
+
s.dependency "powersync-sqlite-core", "~> 0.3.8"
|
|
21
21
|
if defined?(install_modules_dependencies())
|
|
22
22
|
install_modules_dependencies(s)
|
|
23
23
|
else
|
|
@@ -1,40 +1,85 @@
|
|
|
1
|
-
import { DB, SQLBatchTuple } from '@op-engineering/op-sqlite';
|
|
2
|
-
import {
|
|
1
|
+
import { DB, SQLBatchTuple, UpdateHookOperation } from '@op-engineering/op-sqlite';
|
|
2
|
+
import {
|
|
3
|
+
BaseObserver,
|
|
4
|
+
BatchedUpdateNotification,
|
|
5
|
+
DBAdapterListener,
|
|
6
|
+
QueryResult,
|
|
7
|
+
RowUpdateType,
|
|
8
|
+
UpdateNotification
|
|
9
|
+
} from '@powersync/common';
|
|
3
10
|
|
|
4
11
|
export type OPSQLiteConnectionOptions = {
|
|
5
12
|
baseDB: DB;
|
|
6
13
|
};
|
|
7
14
|
|
|
15
|
+
export type OPSQLiteUpdateNotification = {
|
|
16
|
+
table: string;
|
|
17
|
+
operation: UpdateHookOperation;
|
|
18
|
+
row?: any;
|
|
19
|
+
rowId: number;
|
|
20
|
+
};
|
|
21
|
+
|
|
8
22
|
export class OPSQLiteConnection extends BaseObserver<DBAdapterListener> {
|
|
9
23
|
protected DB: DB;
|
|
24
|
+
private updateBuffer: UpdateNotification[];
|
|
25
|
+
|
|
10
26
|
constructor(protected options: OPSQLiteConnectionOptions) {
|
|
11
27
|
super();
|
|
12
28
|
this.DB = options.baseDB;
|
|
29
|
+
this.updateBuffer = [];
|
|
30
|
+
|
|
31
|
+
this.DB.rollbackHook(() => {
|
|
32
|
+
this.updateBuffer = [];
|
|
33
|
+
});
|
|
13
34
|
|
|
14
|
-
// link table update commands
|
|
15
35
|
this.DB.updateHook((update) => {
|
|
16
|
-
this.
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
36
|
+
this.addTableUpdate(update);
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
addTableUpdate(update: OPSQLiteUpdateNotification) {
|
|
41
|
+
let opType: RowUpdateType;
|
|
42
|
+
switch (update.operation) {
|
|
43
|
+
case 'INSERT':
|
|
44
|
+
opType = RowUpdateType.SQLITE_INSERT;
|
|
45
|
+
break;
|
|
46
|
+
case 'DELETE':
|
|
47
|
+
opType = RowUpdateType.SQLITE_DELETE;
|
|
48
|
+
break;
|
|
49
|
+
case 'UPDATE':
|
|
50
|
+
opType = RowUpdateType.SQLITE_UPDATE;
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
this.updateBuffer.push({
|
|
55
|
+
table: update.table,
|
|
56
|
+
opType,
|
|
57
|
+
rowId: update.rowId
|
|
35
58
|
});
|
|
36
59
|
}
|
|
37
60
|
|
|
61
|
+
flushUpdates() {
|
|
62
|
+
if (!this.updateBuffer.length) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const groupedUpdates = this.updateBuffer.reduce((grouping: Record<string, UpdateNotification[]>, update) => {
|
|
67
|
+
const { table } = update;
|
|
68
|
+
const updateGroup = grouping[table] || (grouping[table] = []);
|
|
69
|
+
updateGroup.push(update);
|
|
70
|
+
return grouping;
|
|
71
|
+
}, {});
|
|
72
|
+
|
|
73
|
+
const batchedUpdate: BatchedUpdateNotification = {
|
|
74
|
+
groupedUpdates,
|
|
75
|
+
rawUpdates: this.updateBuffer,
|
|
76
|
+
tables: Object.keys(groupedUpdates)
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
this.updateBuffer = [];
|
|
80
|
+
this.iterateListeners((l) => l.tablesUpdated?.(batchedUpdate));
|
|
81
|
+
}
|
|
82
|
+
|
|
38
83
|
close() {
|
|
39
84
|
return this.DB.close();
|
|
40
85
|
}
|
|
@@ -64,12 +109,12 @@ export class OPSQLiteConnection extends BaseObserver<DBAdapterListener> {
|
|
|
64
109
|
|
|
65
110
|
async getAll<T>(sql: string, parameters?: any[]): Promise<T[]> {
|
|
66
111
|
const result = await this.DB.execute(sql, parameters);
|
|
67
|
-
return result.rows ?? [];
|
|
112
|
+
return (result.rows ?? []) as T[];
|
|
68
113
|
}
|
|
69
114
|
|
|
70
115
|
async getOptional<T>(sql: string, parameters?: any[]): Promise<T | null> {
|
|
71
116
|
const result = await this.DB.execute(sql, parameters);
|
|
72
|
-
return result.rows?.[0] ?? null;
|
|
117
|
+
return (result.rows?.[0] as T) ?? null;
|
|
73
118
|
}
|
|
74
119
|
|
|
75
120
|
async get<T>(sql: string, parameters?: any[]): Promise<T> {
|
|
@@ -79,4 +124,8 @@ export class OPSQLiteConnection extends BaseObserver<DBAdapterListener> {
|
|
|
79
124
|
}
|
|
80
125
|
return result as T;
|
|
81
126
|
}
|
|
127
|
+
|
|
128
|
+
async refreshSchema() {
|
|
129
|
+
await this.get("PRAGMA table_info('sqlite_master')");
|
|
130
|
+
}
|
|
82
131
|
}
|
|
@@ -4,14 +4,19 @@ import {
|
|
|
4
4
|
DBAdapterListener,
|
|
5
5
|
DBLockOptions,
|
|
6
6
|
QueryResult,
|
|
7
|
-
SQLOpenOptions,
|
|
8
7
|
Transaction
|
|
9
8
|
} from '@powersync/common';
|
|
10
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
ANDROID_DATABASE_PATH,
|
|
11
|
+
getDylibPath,
|
|
12
|
+
IOS_LIBRARY_PATH,
|
|
13
|
+
open,
|
|
14
|
+
type DB
|
|
15
|
+
} from '@op-engineering/op-sqlite';
|
|
11
16
|
import Lock from 'async-lock';
|
|
12
17
|
import { OPSQLiteConnection } from './OPSQLiteConnection';
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
18
|
+
import { Platform } from 'react-native';
|
|
19
|
+
import { SqliteOptions } from './SqliteOptions';
|
|
15
20
|
|
|
16
21
|
/**
|
|
17
22
|
* Adapter for React Native Quick SQLite
|
|
@@ -35,10 +40,12 @@ export class OPSQLiteDBAdapter extends BaseObserver<DBAdapterListener> implement
|
|
|
35
40
|
|
|
36
41
|
protected initialized: Promise<void>;
|
|
37
42
|
|
|
38
|
-
protected readConnections: OPSQLiteConnection
|
|
43
|
+
protected readConnections: Array<{ busy: boolean; connection: OPSQLiteConnection }> | null;
|
|
39
44
|
|
|
40
45
|
protected writeConnection: OPSQLiteConnection | null;
|
|
41
46
|
|
|
47
|
+
private readQueue: Array<() => void> = [];
|
|
48
|
+
|
|
42
49
|
constructor(protected options: OPSQLiteAdapterOptions) {
|
|
43
50
|
super();
|
|
44
51
|
this.name = this.options.name;
|
|
@@ -50,15 +57,10 @@ export class OPSQLiteDBAdapter extends BaseObserver<DBAdapterListener> implement
|
|
|
50
57
|
}
|
|
51
58
|
|
|
52
59
|
protected async init() {
|
|
53
|
-
const { lockTimeoutMs, journalMode, journalSizeLimit, synchronous } = this.options.sqliteOptions;
|
|
54
|
-
// const { dbFilename, dbLocation } = this.options;
|
|
60
|
+
const { lockTimeoutMs, journalMode, journalSizeLimit, synchronous, encryptionKey } = this.options.sqliteOptions;
|
|
55
61
|
const dbFilename = this.options.name;
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
const DB: DB = open({
|
|
59
|
-
name: dbFilename,
|
|
60
|
-
location: location
|
|
61
|
-
});
|
|
62
|
+
|
|
63
|
+
this.writeConnection = await this.openConnection(dbFilename);
|
|
62
64
|
|
|
63
65
|
const statements: string[] = [
|
|
64
66
|
`PRAGMA busy_timeout = ${lockTimeoutMs}`,
|
|
@@ -70,7 +72,7 @@ export class OPSQLiteDBAdapter extends BaseObserver<DBAdapterListener> implement
|
|
|
70
72
|
for (const statement of statements) {
|
|
71
73
|
for (let tries = 0; tries < 30; tries++) {
|
|
72
74
|
try {
|
|
73
|
-
await
|
|
75
|
+
await this.writeConnection!.execute(statement);
|
|
74
76
|
break;
|
|
75
77
|
} catch (e: any) {
|
|
76
78
|
if (e instanceof Error && e.message.includes('database is locked') && tries < 29) {
|
|
@@ -82,37 +84,26 @@ export class OPSQLiteDBAdapter extends BaseObserver<DBAdapterListener> implement
|
|
|
82
84
|
}
|
|
83
85
|
}
|
|
84
86
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
87
|
+
// Changes should only occur in the write connection
|
|
88
|
+
this.writeConnection!.registerListener({
|
|
89
|
+
tablesUpdated: (notification) => this.iterateListeners((cb) => cb.tablesUpdated?.(notification))
|
|
90
|
+
});
|
|
88
91
|
|
|
89
92
|
this.readConnections = [];
|
|
90
93
|
for (let i = 0; i < READ_CONNECTIONS; i++) {
|
|
91
|
-
|
|
92
|
-
let dbName = './'.repeat(i + 1) + dbFilename;
|
|
93
|
-
const conn = await this.openConnection(location, dbName);
|
|
94
|
+
const conn = await this.openConnection(dbFilename);
|
|
94
95
|
await conn.execute('PRAGMA query_only = true');
|
|
95
|
-
this.readConnections.push(conn);
|
|
96
|
+
this.readConnections.push({ busy: false, connection: conn });
|
|
96
97
|
}
|
|
97
|
-
|
|
98
|
-
this.writeConnection = new OPSQLiteConnection({
|
|
99
|
-
baseDB: DB
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
// Changes should only occur in the write connection
|
|
103
|
-
this.writeConnection!.registerListener({
|
|
104
|
-
tablesUpdated: (notification) => this.iterateListeners((cb) => cb.tablesUpdated?.(notification))
|
|
105
|
-
});
|
|
106
98
|
}
|
|
107
99
|
|
|
108
|
-
protected async openConnection(
|
|
109
|
-
const
|
|
110
|
-
|
|
111
|
-
location: dbLocation
|
|
112
|
-
});
|
|
100
|
+
protected async openConnection(filenameOverride?: string): Promise<OPSQLiteConnection> {
|
|
101
|
+
const dbFilename = filenameOverride ?? this.options.name;
|
|
102
|
+
const DB: DB = this.openDatabase(dbFilename, this.options.sqliteOptions.encryptionKey);
|
|
113
103
|
|
|
114
|
-
//Load
|
|
115
|
-
this.
|
|
104
|
+
//Load extensions for all connections
|
|
105
|
+
this.loadAdditionalExtensions(DB);
|
|
106
|
+
this.loadPowerSyncExtension(DB);
|
|
116
107
|
|
|
117
108
|
await DB.execute('SELECT powersync_init()');
|
|
118
109
|
|
|
@@ -129,10 +120,35 @@ export class OPSQLiteDBAdapter extends BaseObserver<DBAdapterListener> implement
|
|
|
129
120
|
}
|
|
130
121
|
}
|
|
131
122
|
|
|
132
|
-
private
|
|
123
|
+
private openDatabase(dbFilename: string, encryptionKey?: string): DB {
|
|
124
|
+
//This is needed because an undefined/null dbLocation will cause the open function to fail
|
|
125
|
+
const location = this.getDbLocation(this.options.dbLocation);
|
|
126
|
+
//Simarlily if the encryption key is undefined/null when using SQLCipher it will cause the open function to fail
|
|
127
|
+
if (encryptionKey) {
|
|
128
|
+
return open({
|
|
129
|
+
name: dbFilename,
|
|
130
|
+
location: location,
|
|
131
|
+
encryptionKey: encryptionKey
|
|
132
|
+
});
|
|
133
|
+
} else {
|
|
134
|
+
return open({
|
|
135
|
+
name: dbFilename,
|
|
136
|
+
location: location
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
private loadAdditionalExtensions(DB: DB) {
|
|
142
|
+
if (this.options.sqliteOptions.extensions.length > 0) {
|
|
143
|
+
for (const extension of this.options.sqliteOptions.extensions) {
|
|
144
|
+
DB.loadExtension(extension.path, extension.entryPoint);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
private async loadPowerSyncExtension(DB: DB) {
|
|
133
150
|
if (Platform.OS === 'ios') {
|
|
134
|
-
const
|
|
135
|
-
const libPath = `${bundlePath}/Frameworks/powersync-sqlite-core.framework/powersync-sqlite-core`;
|
|
151
|
+
const libPath = getDylibPath('co.powersync.sqlitecore', 'powersync-sqlite-core');
|
|
136
152
|
DB.loadExtension(libPath, 'sqlite3_powersync_init');
|
|
137
153
|
} else {
|
|
138
154
|
DB.loadExtension('libpowersync', 'sqlite3_powersync_init');
|
|
@@ -142,36 +158,46 @@ export class OPSQLiteDBAdapter extends BaseObserver<DBAdapterListener> implement
|
|
|
142
158
|
close() {
|
|
143
159
|
this.initialized.then(() => {
|
|
144
160
|
this.writeConnection!.close();
|
|
145
|
-
this.readConnections!.forEach((c) => c.close());
|
|
161
|
+
this.readConnections!.forEach((c) => c.connection.close());
|
|
146
162
|
});
|
|
147
163
|
}
|
|
148
164
|
|
|
149
165
|
async readLock<T>(fn: (tx: OPSQLiteConnection) => Promise<T>, options?: DBLockOptions): Promise<T> {
|
|
150
166
|
await this.initialized;
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
167
|
+
return new Promise(async (resolve, reject) => {
|
|
168
|
+
const execute = async () => {
|
|
169
|
+
// Find an available connection that is not busy
|
|
170
|
+
const availableConnection = this.readConnections!.find((conn) => !conn.busy);
|
|
171
|
+
|
|
172
|
+
// If we have an available connection, use it
|
|
173
|
+
if (availableConnection) {
|
|
174
|
+
availableConnection.busy = true;
|
|
175
|
+
try {
|
|
176
|
+
resolve(await fn(availableConnection.connection));
|
|
177
|
+
} catch (error) {
|
|
178
|
+
reject(error);
|
|
179
|
+
} finally {
|
|
180
|
+
availableConnection.busy = false;
|
|
181
|
+
// After query execution, process any queued tasks
|
|
182
|
+
this.processQueue();
|
|
183
|
+
}
|
|
184
|
+
} else {
|
|
185
|
+
// If no available connections, add to the queue
|
|
186
|
+
this.readQueue.push(execute);
|
|
187
|
+
}
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
execute();
|
|
160
191
|
});
|
|
192
|
+
}
|
|
161
193
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
resolve(await fn(sortedConnections[0].connection));
|
|
168
|
-
},
|
|
169
|
-
{ timeout: options?.timeoutMs }
|
|
170
|
-
);
|
|
171
|
-
} catch (ex) {
|
|
172
|
-
reject(ex);
|
|
194
|
+
private async processQueue(): Promise<void> {
|
|
195
|
+
if (this.readQueue.length > 0) {
|
|
196
|
+
const next = this.readQueue.shift();
|
|
197
|
+
if (next) {
|
|
198
|
+
next();
|
|
173
199
|
}
|
|
174
|
-
}
|
|
200
|
+
}
|
|
175
201
|
}
|
|
176
202
|
|
|
177
203
|
async writeLock<T>(fn: (tx: OPSQLiteConnection) => Promise<T>, options?: DBLockOptions): Promise<T> {
|
|
@@ -179,13 +205,18 @@ export class OPSQLiteDBAdapter extends BaseObserver<DBAdapterListener> implement
|
|
|
179
205
|
|
|
180
206
|
return new Promise(async (resolve, reject) => {
|
|
181
207
|
try {
|
|
182
|
-
await this.locks
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
208
|
+
await this.locks
|
|
209
|
+
.acquire(
|
|
210
|
+
LockType.WRITE,
|
|
211
|
+
async () => {
|
|
212
|
+
resolve(await fn(this.writeConnection!));
|
|
213
|
+
},
|
|
214
|
+
{ timeout: options?.timeoutMs }
|
|
215
|
+
)
|
|
216
|
+
.then(() => {
|
|
217
|
+
// flush updates once a write lock has been released
|
|
218
|
+
this.writeConnection!.flushUpdates();
|
|
219
|
+
});
|
|
189
220
|
} catch (ex) {
|
|
190
221
|
reject(ex);
|
|
191
222
|
}
|
|
@@ -256,4 +287,13 @@ export class OPSQLiteDBAdapter extends BaseObserver<DBAdapterListener> implement
|
|
|
256
287
|
throw ex;
|
|
257
288
|
}
|
|
258
289
|
}
|
|
290
|
+
|
|
291
|
+
async refreshSchema(): Promise<void> {
|
|
292
|
+
await this.initialized;
|
|
293
|
+
await this.writeConnection!.refreshSchema();
|
|
294
|
+
|
|
295
|
+
for (let readConnection of this.readConnections) {
|
|
296
|
+
await readConnection.connection.refreshSchema();
|
|
297
|
+
}
|
|
298
|
+
}
|
|
259
299
|
}
|
package/src/db/SqliteOptions.ts
CHANGED
|
@@ -23,6 +23,21 @@ export interface SqliteOptions {
|
|
|
23
23
|
* Set to null or zero to fail immediately when the database is locked.
|
|
24
24
|
*/
|
|
25
25
|
lockTimeoutMs?: number;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Encryption key for the database.
|
|
29
|
+
* If set, the database will be encrypted using SQLCipher.
|
|
30
|
+
*/
|
|
31
|
+
encryptionKey?: string;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Load extensions using the path and entryPoint.
|
|
35
|
+
* More info can be found here https://op-engineering.github.io/op-sqlite/docs/api#loading-extensions.
|
|
36
|
+
*/
|
|
37
|
+
extensions?: Array<{
|
|
38
|
+
path: string;
|
|
39
|
+
entryPoint?: string;
|
|
40
|
+
}>;
|
|
26
41
|
}
|
|
27
42
|
|
|
28
43
|
// SQLite journal mode. Set on the primary connection.
|
|
@@ -36,14 +51,14 @@ enum SqliteJournalMode {
|
|
|
36
51
|
truncate = 'TRUNCATE',
|
|
37
52
|
persist = 'PERSIST',
|
|
38
53
|
memory = 'MEMORY',
|
|
39
|
-
off = 'OFF'
|
|
54
|
+
off = 'OFF'
|
|
40
55
|
}
|
|
41
56
|
|
|
42
57
|
// SQLite file commit mode.
|
|
43
58
|
enum SqliteSynchronous {
|
|
44
59
|
normal = 'NORMAL',
|
|
45
60
|
full = 'FULL',
|
|
46
|
-
off = 'OFF'
|
|
61
|
+
off = 'OFF'
|
|
47
62
|
}
|
|
48
63
|
|
|
49
64
|
export const DEFAULT_SQLITE_OPTIONS: Required<SqliteOptions> = {
|
|
@@ -51,4 +66,6 @@ export const DEFAULT_SQLITE_OPTIONS: Required<SqliteOptions> = {
|
|
|
51
66
|
synchronous: SqliteSynchronous.normal,
|
|
52
67
|
journalSizeLimit: 6 * 1024 * 1024,
|
|
53
68
|
lockTimeoutMs: 30000,
|
|
69
|
+
encryptionKey: null,
|
|
70
|
+
extensions: []
|
|
54
71
|
};
|
package/src/index.ts
CHANGED
|
@@ -1,30 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
Platform.select({ ios: "- You have run 'pod install'\n", default: '' }) +
|
|
6
|
-
'- You rebuilt the app after installing the package\n' +
|
|
7
|
-
'- You are not using Expo Go\n';
|
|
8
|
-
|
|
9
|
-
const isTurboModuleEnabled = global.__turboModuleProxy != null;
|
|
10
|
-
|
|
11
|
-
const PowerSyncOpSqliteModule = isTurboModuleEnabled
|
|
12
|
-
? require('./NativePowerSyncOpSqlite').default
|
|
13
|
-
: NativeModules.PowerSyncOpSqlite;
|
|
14
|
-
|
|
15
|
-
const PowerSyncOpSqlite = PowerSyncOpSqliteModule
|
|
16
|
-
? PowerSyncOpSqliteModule
|
|
17
|
-
: new Proxy(
|
|
18
|
-
{},
|
|
19
|
-
{
|
|
20
|
-
get() {
|
|
21
|
-
throw new Error(LINKING_ERROR);
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
);
|
|
25
|
-
|
|
26
|
-
export function getBundlePath(): string {
|
|
27
|
-
return PowerSyncOpSqlite.getBundlePath();
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export { OPSqliteOpenFactory, OPSQLiteOpenFactoryOptions } from './db/OPSqliteDBOpenFactory';
|
|
1
|
+
export {
|
|
2
|
+
OPSqliteOpenFactory,
|
|
3
|
+
OPSQLiteOpenFactoryOptions
|
|
4
|
+
} from './db/OPSqliteDBOpenFactory';
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
package com.powersync.opsqlite
|
|
2
|
-
|
|
3
|
-
import com.facebook.react.bridge.ReactApplicationContext
|
|
4
|
-
import com.facebook.react.bridge.ReactMethod
|
|
5
|
-
import com.facebook.react.bridge.Promise
|
|
6
|
-
|
|
7
|
-
class PowerSyncOpSqliteModule internal constructor(context: ReactApplicationContext) :
|
|
8
|
-
PowerSyncOpSqliteSpec(context) {
|
|
9
|
-
|
|
10
|
-
@ReactMethod
|
|
11
|
-
override fun getBundlePath(): String {
|
|
12
|
-
//This method should only be used for iOS platforms
|
|
13
|
-
//Ensure you wrap its usage with a (Platform.OS === 'ios') check
|
|
14
|
-
//Returns an empty string for android
|
|
15
|
-
return ""
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
override fun getName(): String {
|
|
19
|
-
return NAME
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
companion object {
|
|
23
|
-
const val NAME = "PowerSyncOpSqlite"
|
|
24
|
-
}
|
|
25
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
package com.powersync.opsqlite
|
|
2
|
-
|
|
3
|
-
import com.facebook.react.bridge.ReactApplicationContext
|
|
4
|
-
import com.facebook.react.bridge.ReactContextBaseJavaModule
|
|
5
|
-
import com.facebook.react.bridge.Promise
|
|
6
|
-
|
|
7
|
-
abstract class PowerSyncOpSqliteSpec internal constructor(context: ReactApplicationContext) :
|
|
8
|
-
ReactContextBaseJavaModule(context) {
|
|
9
|
-
|
|
10
|
-
abstract fun getBundlePath(): String
|
|
11
|
-
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.default = void 0;
|
|
7
|
-
var _reactNative = require("react-native");
|
|
8
|
-
var _default = exports.default = _reactNative.TurboModuleRegistry.getEnforcing('PowerSyncOpSqlite');
|
|
9
|
-
//# sourceMappingURL=NativePowerSyncOpSqlite.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":["_reactNative","require","_default","exports","default","TurboModuleRegistry","getEnforcing"],"sourceRoot":"../../src","sources":["NativePowerSyncOpSqlite.ts"],"mappings":";;;;;;AACA,IAAAA,YAAA,GAAAC,OAAA;AAAmD,IAAAC,QAAA,GAAAC,OAAA,CAAAC,OAAA,GAMpCC,gCAAmB,CAACC,YAAY,CAAO,mBAAmB,CAAC","ignoreList":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":["TurboModuleRegistry","getEnforcing"],"sourceRoot":"../../src","sources":["NativePowerSyncOpSqlite.ts"],"mappings":";;AACA,SAASA,mBAAmB,QAAQ,cAAc;AAMlD,eAAeA,mBAAmB,CAACC,YAAY,CAAO,mBAAmB,CAAC","ignoreList":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"NativePowerSyncOpSqlite.d.ts","sourceRoot":"","sources":["../../../../src/NativePowerSyncOpSqlite.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAGhD,MAAM,WAAW,IAAK,SAAQ,WAAW;IACvC,aAAa,IAAI,MAAM,CAAC;CACzB;;AAED,wBAA2E"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"NativePowerSyncOpSqlite.d.ts","sourceRoot":"","sources":["../../../../src/NativePowerSyncOpSqlite.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAGhD,MAAM,WAAW,IAAK,SAAQ,WAAW;IACvC,aAAa,IAAI,MAAM,CAAC;CACzB;;AAED,wBAA2E"}
|