@capacitor-community/sqlite 4.1.1 → 4.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/README.md +19 -4
- package/android/src/main/java/com/getcapacitor/community/database/sqlite/CapacitorSQLite.java +10 -0
- package/android/src/main/java/com/getcapacitor/community/database/sqlite/CapacitorSQLitePlugin.java +59 -6
- package/android/src/main/java/com/getcapacitor/community/database/sqlite/SQLite/UtilsDownloadFromHTTP.java +116 -0
- package/android/src/main/java/com/getcapacitor/community/database/sqlite/SQLite/UtilsFile.java +89 -12
- package/electron/dist/plugin.js +71 -17
- package/electron/dist/plugin.js.map +1 -1
- package/ios/Plugin/CapacitorSQLite.swift +36 -6
- package/ios/Plugin/CapacitorSQLitePlugin.swift +49 -24
- package/ios/Plugin/Utils/UtilsDownloadFromHTTP.swift +122 -0
- package/ios/Plugin/Utils/UtilsFile.swift +40 -19
- package/ios/Plugin/Utils/UtilsMigrate.swift +1 -1
- package/ios/Plugin/Utils/UtilsUpgrade.swift +1 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
<a href="https://www.npmjs.com/package/@capacitor-community/sqlite"><img src="https://img.shields.io/npm/dw/@capacitor-community/sqlite?style=flat-square" /></a>
|
|
17
17
|
<a href="https://www.npmjs.com/package/@capacitor-community/sqlite"><img src="https://img.shields.io/npm/v/@capacitor-community/sqlite?style=flat-square" /></a>
|
|
18
18
|
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
|
|
19
|
-
<a href="#contributors-"><img src="https://img.shields.io/badge/all%20contributors-
|
|
19
|
+
<a href="#contributors-"><img src="https://img.shields.io/badge/all%20contributors-22-orange?style=flat-square" /></a>
|
|
20
20
|
<!-- ALL-CONTRIBUTORS-BADGE:END -->
|
|
21
21
|
</p>
|
|
22
22
|
|
|
@@ -27,8 +27,21 @@
|
|
|
27
27
|
| Quéau Jean Pierre | [jepiqueau](https://github.com/jepiqueau) | |
|
|
28
28
|
|
|
29
29
|
To install:
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
npm install --save @capacitor-community/sqlite
|
|
33
|
+
npx cap sync
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
yarn install --save @capacitor-community/sqlite
|
|
38
|
+
npx cap sync
|
|
39
|
+
```
|
|
40
|
+
|
|
30
41
|
```
|
|
31
|
-
|
|
42
|
+
pnpm install --save @capacitor-community/sqlite
|
|
43
|
+
pnpm install --save @jeep-sqlite
|
|
44
|
+
pnpm install --save sql.js
|
|
32
45
|
npx cap sync
|
|
33
46
|
```
|
|
34
47
|
|
|
@@ -78,6 +91,7 @@ See [#301](https://github.com/capacitor-community/sqlite/issues/301) and [SO que
|
|
|
78
91
|
cd electron
|
|
79
92
|
npm install --save sqlite3
|
|
80
93
|
npm install --save jszip
|
|
94
|
+
npm install --save node-fetch
|
|
81
95
|
npm install --save-dev @types/sqlite3
|
|
82
96
|
```
|
|
83
97
|
|
|
@@ -137,7 +151,7 @@ npm install --save-dev @types/sqlite3
|
|
|
137
151
|
| closeNCConnection | ✅ | ✅ | ❌ | ❌ |
|
|
138
152
|
| isNCDatabase | ✅ | ✅ | ❌ | ❌ |
|
|
139
153
|
| transaction | ✅ | ✅ | ✅ | ✅ |
|
|
140
|
-
| getFromHTTPRequest |
|
|
154
|
+
| getFromHTTPRequest | ✅ | ✅ | ✅ | ✅ | since 4.2.0
|
|
141
155
|
|
|
142
156
|
|
|
143
157
|
## Documentation & APIs
|
|
@@ -210,7 +224,7 @@ npm install --save-dev @types/sqlite3
|
|
|
210
224
|
|
|
211
225
|
The iOS and Android codes are using `SQLCipher` allowing for database encryption.
|
|
212
226
|
The iOS codes is using `ZIPFoundation` for unzipping assets files
|
|
213
|
-
The Electron code is using `sqlite3
|
|
227
|
+
The Electron code is using `sqlite3` and `node-fetch` from 4.2.0.
|
|
214
228
|
The Web code is using the Stencil component `jeep-sqlite` based on `sql.js`, `localforage`. and `jszip`
|
|
215
229
|
|
|
216
230
|
## Contributors ✨
|
|
@@ -242,6 +256,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
|
|
|
242
256
|
<a href="https://github.com/antoniovlx" title="antoniovlx"><img src="https://github.com/antoniovlx.png?size=100" width="50" height="50" /></a>
|
|
243
257
|
<a href="https://github.com/HarelM" title="HarelM"><img src="https://github.com/HarelM.png?size=100" width="50" height="50" /></a>
|
|
244
258
|
<a href="https://github.com/rdlabo" title="rdlabo"><img src="https://github.com/rdlabo.png?size=100" width="50" height="50" /></a>
|
|
259
|
+
<a href="https://github.com/axkristiansen" title="rdlabo"><img src="https://github.com/axkristiansen.png?size=100" width="50" height="50" /></a>
|
|
245
260
|
</p>
|
|
246
261
|
|
|
247
262
|
<!-- markdownlint-enable -->
|
package/android/src/main/java/com/getcapacitor/community/database/sqlite/CapacitorSQLite.java
CHANGED
|
@@ -17,6 +17,7 @@ import com.getcapacitor.community.database.sqlite.SQLite.ImportExportJson.JsonSQ
|
|
|
17
17
|
import com.getcapacitor.community.database.sqlite.SQLite.ImportExportJson.UtilsJson;
|
|
18
18
|
import com.getcapacitor.community.database.sqlite.SQLite.SqliteConfig;
|
|
19
19
|
import com.getcapacitor.community.database.sqlite.SQLite.UtilsBiometric;
|
|
20
|
+
import com.getcapacitor.community.database.sqlite.SQLite.UtilsDownloadFromHTTP;
|
|
20
21
|
import com.getcapacitor.community.database.sqlite.SQLite.UtilsFile;
|
|
21
22
|
import com.getcapacitor.community.database.sqlite.SQLite.UtilsMigrate;
|
|
22
23
|
import com.getcapacitor.community.database.sqlite.SQLite.UtilsNCDatabase;
|
|
@@ -46,6 +47,7 @@ public class CapacitorSQLite {
|
|
|
46
47
|
private final UtilsJson uJson = new UtilsJson();
|
|
47
48
|
private final UtilsMigrate uMigrate = new UtilsMigrate();
|
|
48
49
|
private final UtilsNCDatabase uNCDatabase = new UtilsNCDatabase();
|
|
50
|
+
private final UtilsDownloadFromHTTP uHTTP = new UtilsDownloadFromHTTP();
|
|
49
51
|
private UtilsSecret uSecret;
|
|
50
52
|
private SharedPreferences sharedPreferences = null;
|
|
51
53
|
private MasterKey masterKeyAlias;
|
|
@@ -537,6 +539,14 @@ public class CapacitorSQLite {
|
|
|
537
539
|
}
|
|
538
540
|
}
|
|
539
541
|
|
|
542
|
+
public void getFromHTTPRequest(String url) throws Exception {
|
|
543
|
+
try {
|
|
544
|
+
uHTTP.download(context, url);
|
|
545
|
+
} catch (Exception e) {
|
|
546
|
+
throw new Exception(e.getMessage());
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
|
|
540
550
|
public Boolean checkConnectionsConsistency(JSArray dbNames, JSArray openModes) throws Exception {
|
|
541
551
|
Set<String> keys = new HashSet<String>(Collections.list(dbDict.keys()));
|
|
542
552
|
String msg = "All Native Connections released";
|
package/android/src/main/java/com/getcapacitor/community/database/sqlite/CapacitorSQLitePlugin.java
CHANGED
|
@@ -12,12 +12,10 @@ import com.getcapacitor.annotation.CapacitorPlugin;
|
|
|
12
12
|
import com.getcapacitor.community.database.sqlite.SQLite.Database;
|
|
13
13
|
import com.getcapacitor.community.database.sqlite.SQLite.ImportExportJson.JsonSQLite;
|
|
14
14
|
import com.getcapacitor.community.database.sqlite.SQLite.SqliteConfig;
|
|
15
|
-
|
|
16
15
|
import java.util.Collections;
|
|
17
16
|
import java.util.Dictionary;
|
|
18
17
|
import java.util.Hashtable;
|
|
19
18
|
import java.util.List;
|
|
20
|
-
|
|
21
19
|
import org.json.JSONArray;
|
|
22
20
|
import org.json.JSONException;
|
|
23
21
|
import org.json.JSONObject;
|
|
@@ -1225,9 +1223,9 @@ public class CapacitorSQLitePlugin extends Plugin {
|
|
|
1225
1223
|
try {
|
|
1226
1224
|
Dictionary<Integer, JSONObject> upgDict = implementation.addUpgradeStatement(upgrade);
|
|
1227
1225
|
|
|
1228
|
-
if (versionUpgrades.get(dbName) != null){
|
|
1226
|
+
if (versionUpgrades.get(dbName) != null) {
|
|
1229
1227
|
List<Integer> keys = Collections.list(upgDict.keys());
|
|
1230
|
-
|
|
1228
|
+
for (Integer versionKey : keys) {
|
|
1231
1229
|
JSONObject upgObj = upgDict.get(versionKey);
|
|
1232
1230
|
|
|
1233
1231
|
versionUpgrades.get(dbName).put(versionKey, upgObj);
|
|
@@ -1362,7 +1360,7 @@ public class CapacitorSQLitePlugin extends Plugin {
|
|
|
1362
1360
|
JSObject retObj = new JSObject();
|
|
1363
1361
|
JsonSQLite retJson = new JsonSQLite();
|
|
1364
1362
|
if (!call.getData().has("database")) {
|
|
1365
|
-
String msg = "
|
|
1363
|
+
String msg = "DeleteExportedRows: Must provide a database name";
|
|
1366
1364
|
rHandler.retResult(call, null, msg);
|
|
1367
1365
|
return;
|
|
1368
1366
|
}
|
|
@@ -1418,7 +1416,62 @@ public class CapacitorSQLitePlugin extends Plugin {
|
|
|
1418
1416
|
*/
|
|
1419
1417
|
@PluginMethod
|
|
1420
1418
|
public void getFromHTTPRequest(PluginCall call) {
|
|
1421
|
-
call.
|
|
1419
|
+
if (!call.getData().has("url")) {
|
|
1420
|
+
String msg = "GetFromHTTPRequest: Must provide a database url";
|
|
1421
|
+
rHandler.retResult(call, null, msg);
|
|
1422
|
+
return;
|
|
1423
|
+
}
|
|
1424
|
+
String url = call.getString("url");
|
|
1425
|
+
if (implementation != null) {
|
|
1426
|
+
Runnable setHTTPRunnable = new Runnable() {
|
|
1427
|
+
@Override
|
|
1428
|
+
public void run() {
|
|
1429
|
+
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND);
|
|
1430
|
+
try {
|
|
1431
|
+
implementation.getFromHTTPRequest(url);
|
|
1432
|
+
getActivity()
|
|
1433
|
+
.runOnUiThread(
|
|
1434
|
+
new Runnable() {
|
|
1435
|
+
@Override
|
|
1436
|
+
public void run() {
|
|
1437
|
+
rHandler.retResult(call, null, null);
|
|
1438
|
+
return;
|
|
1439
|
+
}
|
|
1440
|
+
}
|
|
1441
|
+
);
|
|
1442
|
+
} catch (Exception e) {
|
|
1443
|
+
getActivity()
|
|
1444
|
+
.runOnUiThread(
|
|
1445
|
+
new Runnable() {
|
|
1446
|
+
@Override
|
|
1447
|
+
public void run() {
|
|
1448
|
+
String msg = "GetFromHTTPRequest: " + e.getMessage();
|
|
1449
|
+
rHandler.retResult(call, null, msg);
|
|
1450
|
+
return;
|
|
1451
|
+
}
|
|
1452
|
+
}
|
|
1453
|
+
);
|
|
1454
|
+
}
|
|
1455
|
+
}
|
|
1456
|
+
};
|
|
1457
|
+
Thread myHttpThread = new Thread(setHTTPRunnable);
|
|
1458
|
+
myHttpThread.start();
|
|
1459
|
+
while (myHttpThread.isAlive());
|
|
1460
|
+
System.out.println("Thread Exiting!");
|
|
1461
|
+
/* try {
|
|
1462
|
+
implementation.getFromHTTPRequest(url);
|
|
1463
|
+
rHandler.retResult(call, null, null);
|
|
1464
|
+
return;
|
|
1465
|
+
} catch (Exception e) {
|
|
1466
|
+
String msg = "GetFromHTTPRequest: " + e.getMessage();
|
|
1467
|
+
rHandler.retResult(call, null, msg);
|
|
1468
|
+
return;
|
|
1469
|
+
}
|
|
1470
|
+
*/
|
|
1471
|
+
} else {
|
|
1472
|
+
rHandler.retResult(call, null, loadMessage);
|
|
1473
|
+
return;
|
|
1474
|
+
}
|
|
1422
1475
|
}
|
|
1423
1476
|
|
|
1424
1477
|
private void AddObserversToNotificationCenter() {
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
package com.getcapacitor.community.database.sqlite.SQLite;
|
|
2
|
+
|
|
3
|
+
import android.content.Context;
|
|
4
|
+
import android.content.res.AssetManager;
|
|
5
|
+
import java.io.File;
|
|
6
|
+
import java.io.FileOutputStream;
|
|
7
|
+
import java.io.IOException;
|
|
8
|
+
import java.io.InputStream;
|
|
9
|
+
import java.net.HttpURLConnection;
|
|
10
|
+
import java.net.URL;
|
|
11
|
+
|
|
12
|
+
public class UtilsDownloadFromHTTP {
|
|
13
|
+
|
|
14
|
+
private static final String TAG = UtilsDownloadFromHTTP.class.getName();
|
|
15
|
+
private static final int BUFFER_SIZE = 4096;
|
|
16
|
+
private final UtilsFile _uFile = new UtilsFile();
|
|
17
|
+
|
|
18
|
+
public void download(Context context, String fileUrl) throws Exception {
|
|
19
|
+
AssetManager assetManager = context.getAssets();
|
|
20
|
+
String fileName = fileUrl.substring(fileUrl.lastIndexOf('/') + 1);
|
|
21
|
+
String dbName = fileName;
|
|
22
|
+
Boolean isZip = false;
|
|
23
|
+
if (!fileName.contains("SQLite.db")) {
|
|
24
|
+
if (_uFile.getFileExtension((fileName)).equals("db")) {
|
|
25
|
+
dbName = fileName.substring(0, fileName.length() - 3) + "SQLite.db";
|
|
26
|
+
}
|
|
27
|
+
if (_uFile.isLast(fileName, ".zip")) {
|
|
28
|
+
isZip = true;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
File cacheDir = context.getCacheDir();
|
|
32
|
+
String cachePath = cacheDir.getAbsolutePath();
|
|
33
|
+
String tmpFilePath = cachePath + File.separator + dbName;
|
|
34
|
+
String databasePath = _uFile.getDatabaseDirectoryPath(context);
|
|
35
|
+
File databaseDir = new File(databasePath);
|
|
36
|
+
try {
|
|
37
|
+
// delete file if exists in cache
|
|
38
|
+
Boolean isExists = _uFile.isPathExists(tmpFilePath);
|
|
39
|
+
if (isExists) {
|
|
40
|
+
_uFile.deleteFile(cachePath, dbName);
|
|
41
|
+
}
|
|
42
|
+
downloadFileToCache(fileUrl, cachePath);
|
|
43
|
+
if (isZip) {
|
|
44
|
+
_uFile.unzipCopyDatabase(cachePath, null, tmpFilePath, true);
|
|
45
|
+
// delete zip file from cache
|
|
46
|
+
_uFile.deleteFile(cachePath, dbName);
|
|
47
|
+
}
|
|
48
|
+
// move files to database folder
|
|
49
|
+
_uFile.moveAllDBs(cacheDir, databaseDir);
|
|
50
|
+
} catch (Exception e) {
|
|
51
|
+
throw new Exception(e.getMessage());
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
public static void downloadFileToCache(String fileURL, String cacheDir) throws Exception {
|
|
56
|
+
HttpURLConnection httpConn = null;
|
|
57
|
+
try {
|
|
58
|
+
URL url = new URL(fileURL);
|
|
59
|
+
httpConn = (HttpURLConnection) url.openConnection();
|
|
60
|
+
int responseCode = httpConn.getResponseCode();
|
|
61
|
+
if (responseCode == HttpURLConnection.HTTP_OK) {
|
|
62
|
+
String fileName = "";
|
|
63
|
+
String disposition = httpConn.getHeaderField("Content-Disposition");
|
|
64
|
+
// String contentType = httpConn.getContentType();
|
|
65
|
+
int contentLength = httpConn.getContentLength();
|
|
66
|
+
|
|
67
|
+
if (disposition != null) {
|
|
68
|
+
// extracts file name from header field
|
|
69
|
+
int index = disposition.indexOf("filename=");
|
|
70
|
+
if (index > 0) {
|
|
71
|
+
fileName = disposition.substring(index + 10, disposition.length() - 1);
|
|
72
|
+
}
|
|
73
|
+
} else {
|
|
74
|
+
// extracts file name from URL
|
|
75
|
+
fileName = fileURL.substring(fileURL.lastIndexOf("/") + 1);
|
|
76
|
+
}
|
|
77
|
+
String dbName = fileName;
|
|
78
|
+
if (!fileName.contains("SQLite.db")) {
|
|
79
|
+
if (fileName.substring(fileName.length() - 3).equals(".db")) {
|
|
80
|
+
dbName = fileName.substring(0, fileName.length() - 3) + "SQLite.db";
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// System.out.println("Content-Type = " + contentType);
|
|
85
|
+
// System.out.println("Content-Disposition = " + disposition);
|
|
86
|
+
// System.out.println("Content-Length = " + contentLength);
|
|
87
|
+
// System.out.println("fileName = " + fileName);
|
|
88
|
+
// opens input stream from the HTTP connection
|
|
89
|
+
InputStream inputStream = httpConn.getInputStream();
|
|
90
|
+
// create temporary file path
|
|
91
|
+
String tmpFilePath = cacheDir + File.separator + dbName;
|
|
92
|
+
// opens an output stream to save into file
|
|
93
|
+
FileOutputStream outputStream = new FileOutputStream(tmpFilePath);
|
|
94
|
+
int bytesRead = -1;
|
|
95
|
+
byte[] buffer = new byte[BUFFER_SIZE];
|
|
96
|
+
while ((bytesRead = inputStream.read(buffer)) != -1) {
|
|
97
|
+
outputStream.write(buffer, 0, bytesRead);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
outputStream.close();
|
|
101
|
+
inputStream.close();
|
|
102
|
+
|
|
103
|
+
System.out.println("File " + fileName + " downloaded (" + contentLength + ")");
|
|
104
|
+
} else {
|
|
105
|
+
String msg = "No file to download. Server replied HTTP code: " + responseCode;
|
|
106
|
+
throw new IOException(msg);
|
|
107
|
+
}
|
|
108
|
+
} catch (IOException e) {
|
|
109
|
+
throw new Exception(e);
|
|
110
|
+
} finally {
|
|
111
|
+
if (httpConn != null) {
|
|
112
|
+
httpConn.disconnect();
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
package/android/src/main/java/com/getcapacitor/community/database/sqlite/SQLite/UtilsFile.java
CHANGED
|
@@ -2,7 +2,9 @@ package com.getcapacitor.community.database.sqlite.SQLite;
|
|
|
2
2
|
|
|
3
3
|
import android.content.Context;
|
|
4
4
|
import android.content.res.AssetManager;
|
|
5
|
+
import android.os.Build;
|
|
5
6
|
import android.util.Log;
|
|
7
|
+
import androidx.annotation.RequiresApi;
|
|
6
8
|
import java.io.File;
|
|
7
9
|
import java.io.FileInputStream;
|
|
8
10
|
import java.io.FileOutputStream;
|
|
@@ -10,8 +12,16 @@ import java.io.IOException;
|
|
|
10
12
|
import java.io.InputStream;
|
|
11
13
|
import java.io.OutputStream;
|
|
12
14
|
import java.nio.channels.FileChannel;
|
|
15
|
+
import java.nio.file.DirectoryStream;
|
|
16
|
+
import java.nio.file.Files;
|
|
17
|
+
import java.nio.file.Path;
|
|
18
|
+
import java.nio.file.Paths;
|
|
13
19
|
import java.util.ArrayList;
|
|
20
|
+
import java.util.HashSet;
|
|
14
21
|
import java.util.List;
|
|
22
|
+
import java.util.Set;
|
|
23
|
+
import java.util.stream.Collectors;
|
|
24
|
+
import java.util.stream.Stream;
|
|
15
25
|
import java.util.zip.ZipEntry;
|
|
16
26
|
import java.util.zip.ZipInputStream;
|
|
17
27
|
|
|
@@ -33,6 +43,10 @@ public class UtilsFile {
|
|
|
33
43
|
}
|
|
34
44
|
}
|
|
35
45
|
|
|
46
|
+
public String getDatabaseDirectoryPath(Context context) {
|
|
47
|
+
return context != null && context.getDatabasePath("x") != null ? context.getDatabasePath("x").getParent() : "";
|
|
48
|
+
}
|
|
49
|
+
|
|
36
50
|
public String[] getListOfFiles(Context context) {
|
|
37
51
|
String[] files = context.databaseList();
|
|
38
52
|
List<String> dbs = new ArrayList<>();
|
|
@@ -64,6 +78,10 @@ public class UtilsFile {
|
|
|
64
78
|
return file.delete();
|
|
65
79
|
}
|
|
66
80
|
|
|
81
|
+
public Boolean deleteFile(File file) {
|
|
82
|
+
return file.delete();
|
|
83
|
+
}
|
|
84
|
+
|
|
67
85
|
public void copyFromAssetsToDatabase(Context context, Boolean overwrite) throws Exception {
|
|
68
86
|
AssetManager assetManager = context.getAssets();
|
|
69
87
|
String assetsDatabasePath = "public/assets/databases";
|
|
@@ -99,7 +117,8 @@ public class UtilsFile {
|
|
|
99
117
|
if (isLast(fileName, ".zip")) {
|
|
100
118
|
// unzip file and extract databases
|
|
101
119
|
String zipPathName = assetsDatabasePath + "/" + fileName;
|
|
102
|
-
|
|
120
|
+
String databasePath = getDatabaseDirectoryPath(context);
|
|
121
|
+
unzipCopyDatabase(databasePath, assetManager, zipPathName, overwrite);
|
|
103
122
|
}
|
|
104
123
|
}
|
|
105
124
|
return;
|
|
@@ -109,26 +128,33 @@ public class UtilsFile {
|
|
|
109
128
|
}
|
|
110
129
|
}
|
|
111
130
|
|
|
112
|
-
public void unzipCopyDatabase(
|
|
113
|
-
|
|
114
|
-
|
|
131
|
+
public void unzipCopyDatabase(String databasePath, AssetManager asm, String zipPath, Boolean overwrite) throws IOException {
|
|
132
|
+
InputStream is = null;
|
|
133
|
+
FileInputStream isF = null;
|
|
134
|
+
ZipInputStream zis;
|
|
115
135
|
byte[] buffer = new byte[1024];
|
|
116
|
-
try {
|
|
117
|
-
is = asm.open(zipPath);
|
|
118
|
-
ZipInputStream zis = new ZipInputStream(is);
|
|
119
136
|
|
|
137
|
+
try {
|
|
138
|
+
if (asm != null) {
|
|
139
|
+
is = asm.open(zipPath);
|
|
140
|
+
zis = new ZipInputStream(is);
|
|
141
|
+
} else {
|
|
142
|
+
File zipFile = new File(zipPath);
|
|
143
|
+
isF = new FileInputStream(zipFile);
|
|
144
|
+
zis = new ZipInputStream(isF);
|
|
145
|
+
}
|
|
120
146
|
ZipEntry ze = zis.getNextEntry();
|
|
121
147
|
while (ze != null) {
|
|
122
148
|
String fileName = ze.getName();
|
|
123
149
|
if (isLast(fileName, ".db")) {
|
|
124
150
|
String toFileName = addSQLiteSuffix(fileName);
|
|
125
|
-
|
|
151
|
+
String dbPath = databasePath + File.separator + toFileName;
|
|
152
|
+
boolean isExist = isPathExists(dbPath);
|
|
126
153
|
if (!isExist || overwrite) {
|
|
127
154
|
if (overwrite && isExist) {
|
|
128
|
-
|
|
155
|
+
deleteFile(databasePath, toFileName);
|
|
129
156
|
}
|
|
130
|
-
|
|
131
|
-
File newFile = new File(toPathName);
|
|
157
|
+
File newFile = new File(dbPath);
|
|
132
158
|
System.out.println("Unzipping to " + newFile.getAbsolutePath());
|
|
133
159
|
FileOutputStream fos = new FileOutputStream(newFile);
|
|
134
160
|
int len;
|
|
@@ -145,7 +171,11 @@ public class UtilsFile {
|
|
|
145
171
|
//close last ZipEntry
|
|
146
172
|
zis.closeEntry();
|
|
147
173
|
zis.close();
|
|
148
|
-
is
|
|
174
|
+
if (asm != null && is != null) {
|
|
175
|
+
is.close();
|
|
176
|
+
} else if (isF != null) {
|
|
177
|
+
isF.close();
|
|
178
|
+
}
|
|
149
179
|
} catch (IOException e) {
|
|
150
180
|
throw new IOException("in unzipCopyDatabase " + e.getLocalizedMessage());
|
|
151
181
|
}
|
|
@@ -294,6 +324,53 @@ public class UtilsFile {
|
|
|
294
324
|
}
|
|
295
325
|
}
|
|
296
326
|
|
|
327
|
+
public void moveAllDBs(File fromDir, File toDir) throws Exception {
|
|
328
|
+
// get the file List from fromDir
|
|
329
|
+
List<String> fileList;
|
|
330
|
+
String fromDirPath = fromDir.getAbsolutePath();
|
|
331
|
+
String toDirPath = toDir.getAbsolutePath();
|
|
332
|
+
|
|
333
|
+
try {
|
|
334
|
+
fileList = listDatabases(fromDir);
|
|
335
|
+
for (String fileName : fileList) {
|
|
336
|
+
// Check if the file exists in toDir
|
|
337
|
+
File toFile = new File(toDirPath, fileName);
|
|
338
|
+
Boolean isPath = isPathExists(toFile.getAbsolutePath());
|
|
339
|
+
if (isPath) {
|
|
340
|
+
deleteFile(toFile);
|
|
341
|
+
}
|
|
342
|
+
File fromFile = new File(fromDirPath, fileName);
|
|
343
|
+
|
|
344
|
+
Boolean success = fromFile.renameTo(toFile);
|
|
345
|
+
if (!success) {
|
|
346
|
+
throw new Exception("moveAllDBs: move file " + fileName + " failed");
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
} catch (Exception e) {
|
|
350
|
+
throw new Exception(e.getMessage());
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
public List<String> listDatabases(File fileDir) throws Exception {
|
|
355
|
+
List<String> fileList = new ArrayList<>();
|
|
356
|
+
if (!fileDir.exists()) {
|
|
357
|
+
throw new Exception("File " + fileDir.getAbsolutePath() + " does not exist");
|
|
358
|
+
}
|
|
359
|
+
if (!fileDir.isDirectory()) {
|
|
360
|
+
throw new Exception("File " + fileDir.getAbsolutePath() + " is not a directory");
|
|
361
|
+
}
|
|
362
|
+
File[] fList = fileDir.listFiles();
|
|
363
|
+
for (File file : fList) {
|
|
364
|
+
if (file.isFile()) {
|
|
365
|
+
String fileName = file.getName();
|
|
366
|
+
if (getFileExtension((fileName)).equals("db")) {
|
|
367
|
+
fileList.add(fileName);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
return fileList;
|
|
372
|
+
}
|
|
373
|
+
|
|
297
374
|
private static void copyFileFromFile(File sourceFile, File destFile) throws IOException {
|
|
298
375
|
if (!destFile.getParentFile().exists()) destFile.getParentFile().mkdirs();
|
|
299
376
|
|
package/electron/dist/plugin.js
CHANGED
|
@@ -3,12 +3,13 @@
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
5
|
var require$$0 = require('sqlite3');
|
|
6
|
-
var require$$0$1 = require('
|
|
7
|
-
var require$$1 = require('
|
|
8
|
-
var require$$2 = require('
|
|
9
|
-
var require$$3 = require('
|
|
10
|
-
var require$$4 = require('
|
|
11
|
-
var require$$5 = require('
|
|
6
|
+
var require$$0$1 = require('node:fs/promises');
|
|
7
|
+
var require$$1 = require('path');
|
|
8
|
+
var require$$2 = require('fs');
|
|
9
|
+
var require$$3 = require('node-fetch');
|
|
10
|
+
var require$$4 = require('os');
|
|
11
|
+
var require$$5 = require('jszip');
|
|
12
|
+
var require$$6 = require('electron');
|
|
12
13
|
|
|
13
14
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
14
15
|
|
|
@@ -19,6 +20,7 @@ var require$$2__default = /*#__PURE__*/_interopDefaultLegacy(require$$2);
|
|
|
19
20
|
var require$$3__default = /*#__PURE__*/_interopDefaultLegacy(require$$3);
|
|
20
21
|
var require$$4__default = /*#__PURE__*/_interopDefaultLegacy(require$$4);
|
|
21
22
|
var require$$5__default = /*#__PURE__*/_interopDefaultLegacy(require$$5);
|
|
23
|
+
var require$$6__default = /*#__PURE__*/_interopDefaultLegacy(require$$6);
|
|
22
24
|
|
|
23
25
|
var src = {};
|
|
24
26
|
|
|
@@ -2673,6 +2675,7 @@ var utilsFile = {};
|
|
|
2673
2675
|
|
|
2674
2676
|
Object.defineProperty(utilsFile, "__esModule", { value: true });
|
|
2675
2677
|
utilsFile.UtilsFile = void 0;
|
|
2678
|
+
const promises_1 = require$$0__default$1["default"];
|
|
2676
2679
|
class UtilsFile {
|
|
2677
2680
|
constructor() {
|
|
2678
2681
|
this.pathDB = 'Databases';
|
|
@@ -2685,12 +2688,12 @@ class UtilsFile {
|
|
|
2685
2688
|
this.AppName = '';
|
|
2686
2689
|
this.HomeDir = '';
|
|
2687
2690
|
this.sep = '/';
|
|
2688
|
-
this.Path = require$$
|
|
2689
|
-
this.NodeFs = require$$
|
|
2690
|
-
this.NodeFetch = require$$
|
|
2691
|
-
this.Os = require$$
|
|
2692
|
-
this.JSZip = require$$
|
|
2693
|
-
this.Electron = require$$
|
|
2691
|
+
this.Path = require$$1__default["default"];
|
|
2692
|
+
this.NodeFs = require$$2__default["default"];
|
|
2693
|
+
this.NodeFetch = require$$3__default["default"];
|
|
2694
|
+
this.Os = require$$4__default["default"];
|
|
2695
|
+
this.JSZip = require$$5__default["default"];
|
|
2696
|
+
this.Electron = require$$6__default["default"];
|
|
2694
2697
|
this.HomeDir = this.Os.homedir();
|
|
2695
2698
|
const dir = __dirname;
|
|
2696
2699
|
const idx = dir.indexOf('\\');
|
|
@@ -2996,6 +2999,7 @@ class UtilsFile {
|
|
|
2996
2999
|
const isPath = this.isPathExists(filePath);
|
|
2997
3000
|
if (isPath) {
|
|
2998
3001
|
try {
|
|
3002
|
+
await this.waitForFilePathLock(filePath);
|
|
2999
3003
|
this.NodeFs.unlinkSync(filePath);
|
|
3000
3004
|
return Promise.resolve();
|
|
3001
3005
|
}
|
|
@@ -3011,6 +3015,52 @@ class UtilsFile {
|
|
|
3011
3015
|
return Promise.reject('DeleteFilePath: delete filePath' + 'failed');
|
|
3012
3016
|
}
|
|
3013
3017
|
}
|
|
3018
|
+
async waitForFilePathLock(filePath, timeoutMS = 4000) {
|
|
3019
|
+
let timeIsOver = false;
|
|
3020
|
+
setTimeout(() => {
|
|
3021
|
+
timeIsOver = true;
|
|
3022
|
+
}, timeoutMS);
|
|
3023
|
+
return new Promise((resolve, reject) => {
|
|
3024
|
+
const check = async () => {
|
|
3025
|
+
if (timeIsOver) {
|
|
3026
|
+
reject(new Error(`WaitForFilePathLock: The resource is still locked / busy after ${timeoutMS} milliseconds.`));
|
|
3027
|
+
return;
|
|
3028
|
+
}
|
|
3029
|
+
// check if path exists
|
|
3030
|
+
const isPath = this.isPathExists(filePath);
|
|
3031
|
+
// The file path does not exist. A non existant path cannot be locked.
|
|
3032
|
+
if (!isPath) {
|
|
3033
|
+
resolve();
|
|
3034
|
+
return;
|
|
3035
|
+
}
|
|
3036
|
+
try {
|
|
3037
|
+
const stream = await promises_1.open(filePath, 'r+');
|
|
3038
|
+
// We need to close the stream afterwards, because otherwise, we're locking the file
|
|
3039
|
+
await stream.close();
|
|
3040
|
+
resolve();
|
|
3041
|
+
}
|
|
3042
|
+
catch (err) {
|
|
3043
|
+
if (err.code === 'EBUSY') {
|
|
3044
|
+
// The resource is busy. Retry in 100ms
|
|
3045
|
+
setTimeout(() => {
|
|
3046
|
+
check();
|
|
3047
|
+
}, 100);
|
|
3048
|
+
return;
|
|
3049
|
+
}
|
|
3050
|
+
else if (err.code === 'ENOENT') {
|
|
3051
|
+
// The file does not exist (anymore). So it cannot be locked.
|
|
3052
|
+
resolve();
|
|
3053
|
+
return;
|
|
3054
|
+
}
|
|
3055
|
+
else {
|
|
3056
|
+
// Something else went wrong.
|
|
3057
|
+
reject(new Error(`WaitForFilePathLock: Error while checking the file: ${err}`));
|
|
3058
|
+
}
|
|
3059
|
+
}
|
|
3060
|
+
};
|
|
3061
|
+
check();
|
|
3062
|
+
});
|
|
3063
|
+
}
|
|
3014
3064
|
/**
|
|
3015
3065
|
* RenameFileName
|
|
3016
3066
|
* @param fileName
|
|
@@ -3350,11 +3400,15 @@ class Database {
|
|
|
3350
3400
|
*/
|
|
3351
3401
|
async close() {
|
|
3352
3402
|
this.ensureDatabaseIsOpen();
|
|
3353
|
-
|
|
3354
|
-
|
|
3355
|
-
|
|
3356
|
-
|
|
3357
|
-
|
|
3403
|
+
return new Promise((resolve, reject) => {
|
|
3404
|
+
this.database.close((err) => {
|
|
3405
|
+
if (err) {
|
|
3406
|
+
reject(new Error(`Close failed: ${this.dbName} ${err}`));
|
|
3407
|
+
return;
|
|
3408
|
+
}
|
|
3409
|
+
this._isDbOpen = false;
|
|
3410
|
+
resolve();
|
|
3411
|
+
});
|
|
3358
3412
|
});
|
|
3359
3413
|
}
|
|
3360
3414
|
/**
|