react-native-mosquito-transport 0.0.26 → 0.0.28
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 +1 -0
- package/TODO +1 -0
- package/android/src/main/java/com/mosquitodb/MosquitodbModule.java +55 -5
- package/android/src/main/java/com/mosquitodb/utils/FileUploader.java +101 -0
- package/android/src/main/java/com/mosquitodb/utils/UploadCallback.java +7 -0
- package/ios/Mosquitodb.swift +1 -2
- package/package.json +1 -1
- package/src/index.d.ts +1 -1
- package/src/products/database/accessor.js +1 -1
- package/src/products/database/bson.js +1 -1
- package/src/products/database/index.js +1 -1
- package/src/products/database/validator.js +1 -1
- package/src/products/storage/index.js +18 -15
package/README.md
CHANGED
package/TODO
CHANGED
|
@@ -1,16 +1,25 @@
|
|
|
1
1
|
package com.mosquitodb;
|
|
2
2
|
|
|
3
|
+
import android.util.ArrayMap;
|
|
4
|
+
|
|
3
5
|
import androidx.annotation.NonNull;
|
|
6
|
+
import androidx.annotation.Nullable;
|
|
4
7
|
|
|
5
|
-
import com.facebook.react.bridge.Promise;
|
|
6
8
|
import com.facebook.react.bridge.ReactApplicationContext;
|
|
7
9
|
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
|
8
10
|
import com.facebook.react.bridge.ReactMethod;
|
|
11
|
+
import com.facebook.react.bridge.ReadableMap;
|
|
12
|
+
import com.facebook.react.bridge.WritableMap;
|
|
13
|
+
import com.facebook.react.bridge.WritableNativeMap;
|
|
9
14
|
import com.facebook.react.module.annotations.ReactModule;
|
|
15
|
+
import com.facebook.react.modules.core.DeviceEventManagerModule;
|
|
16
|
+
import com.mosquitodb.utils.FileUploader;
|
|
17
|
+
import com.mosquitodb.utils.UploadCallback;
|
|
10
18
|
|
|
11
19
|
@ReactModule(name = MosquitodbModule.NAME)
|
|
12
20
|
public class MosquitodbModule extends ReactContextBaseJavaModule {
|
|
13
21
|
public static final String NAME = "Mosquitodb";
|
|
22
|
+
private final ArrayMap<String, FileUploader> uploaderMap = new ArrayMap<>();
|
|
14
23
|
|
|
15
24
|
public MosquitodbModule(ReactApplicationContext reactContext) {
|
|
16
25
|
super(reactContext);
|
|
@@ -22,11 +31,52 @@ public class MosquitodbModule extends ReactContextBaseJavaModule {
|
|
|
22
31
|
return NAME;
|
|
23
32
|
}
|
|
24
33
|
|
|
34
|
+
@ReactMethod
|
|
35
|
+
public void uploadFile(ReadableMap readable) {
|
|
36
|
+
String processId = readable.getString("processID");
|
|
37
|
+
FileUploader uploader = new FileUploader();
|
|
38
|
+
|
|
39
|
+
uploader.uploadFile(readable, new UploadCallback() {
|
|
40
|
+
@Override
|
|
41
|
+
public void onProgress(long sentBytes, long totalBytes) {
|
|
42
|
+
WritableMap progress = new WritableNativeMap();
|
|
43
|
+
progress.putInt("sentBytes", (int) sentBytes);
|
|
44
|
+
progress.putInt("totalBytes", (int) totalBytes);
|
|
45
|
+
progress.putString("processID", processId);
|
|
46
|
+
sendEvent("mt-uploading-progress", progress);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
@Override
|
|
50
|
+
public void onComplete(int responseCode, String responseBody) {
|
|
51
|
+
WritableMap statusData = new WritableNativeMap();
|
|
52
|
+
statusData.putString("processID", processId);
|
|
53
|
+
statusData.putString("result", responseBody);
|
|
54
|
+
sendEvent("mt-uploading-status", statusData);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
@Override
|
|
58
|
+
public void onError(Exception e) {
|
|
59
|
+
WritableMap statusData = new WritableNativeMap();
|
|
60
|
+
statusData.putString("processID", processId);
|
|
61
|
+
statusData.putString("error", "internal_error");
|
|
62
|
+
statusData.putString("errorDes", e.getLocalizedMessage());
|
|
63
|
+
sendEvent("mt-uploading-status", statusData);
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
uploaderMap.put(processId, uploader);
|
|
67
|
+
}
|
|
25
68
|
|
|
26
|
-
// Example method
|
|
27
|
-
// See https://reactnative.dev/docs/native-modules-android
|
|
28
69
|
@ReactMethod
|
|
29
|
-
public void
|
|
30
|
-
|
|
70
|
+
public void cancelUpload(String processID) {
|
|
71
|
+
FileUploader uploader = uploaderMap.get(processID);
|
|
72
|
+
if (uploader != null) {
|
|
73
|
+
uploader.cancelUpload();
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
private void sendEvent(String eventName, @Nullable WritableMap params) {
|
|
78
|
+
getReactApplicationContext()
|
|
79
|
+
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
|
|
80
|
+
.emit(eventName, params);
|
|
31
81
|
}
|
|
32
82
|
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
package com.mosquitodb.utils;
|
|
2
|
+
|
|
3
|
+
import java.io.*;
|
|
4
|
+
import java.net.*;
|
|
5
|
+
import java.util.Objects;
|
|
6
|
+
|
|
7
|
+
import android.net.Uri;
|
|
8
|
+
|
|
9
|
+
import com.facebook.react.bridge.ReadableMap;
|
|
10
|
+
import com.facebook.react.bridge.ReadableMapKeySetIterator;
|
|
11
|
+
|
|
12
|
+
public class FileUploader {
|
|
13
|
+
|
|
14
|
+
private volatile boolean isCancelled = false;
|
|
15
|
+
|
|
16
|
+
public void cancelUpload() {
|
|
17
|
+
isCancelled = true;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
public void uploadFile(ReadableMap config, UploadCallback callback) {
|
|
21
|
+
new Thread(() -> {
|
|
22
|
+
try {
|
|
23
|
+
Uri fileUri = Uri.parse(config.getString("file"));
|
|
24
|
+
File file = new File(Objects.requireNonNull(fileUri.getPath()));
|
|
25
|
+
|
|
26
|
+
if (!file.exists()) {
|
|
27
|
+
throw new FileNotFoundException("File not found: " + file.getAbsolutePath());
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
long totalBytes = file.length();
|
|
31
|
+
HttpURLConnection connection = (HttpURLConnection) new URL(config.getString("url")).openConnection();
|
|
32
|
+
connection.setDoOutput(true);
|
|
33
|
+
connection.setRequestMethod("POST");
|
|
34
|
+
|
|
35
|
+
ReadableMap extraHeaders = config.getMap("extraHeaders");
|
|
36
|
+
ReadableMapKeySetIterator iterator = Objects.requireNonNull(extraHeaders).keySetIterator();
|
|
37
|
+
while (iterator.hasNextKey()) {
|
|
38
|
+
String key = iterator.nextKey();
|
|
39
|
+
connection.setRequestProperty(key, extraHeaders.getString(key));
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
connection.setRequestProperty("Content-Type", "buffer/upload");
|
|
43
|
+
connection.setRequestProperty("hash-upload", config.getString("createHash"));
|
|
44
|
+
connection.setRequestProperty("Mosquito-Destination", config.getString("destination"));
|
|
45
|
+
if (config.hasKey("authToken")) {
|
|
46
|
+
connection.setRequestProperty("Mosquito-Token", config.getString("authToken"));
|
|
47
|
+
}
|
|
48
|
+
connection.setFixedLengthStreamingMode((int) totalBytes);
|
|
49
|
+
|
|
50
|
+
OutputStream out = connection.getOutputStream();
|
|
51
|
+
FileInputStream in = new FileInputStream(file);
|
|
52
|
+
|
|
53
|
+
byte[] buffer = new byte[8192];
|
|
54
|
+
long sentBytes = 0;
|
|
55
|
+
int bytesRead;
|
|
56
|
+
|
|
57
|
+
while ((bytesRead = in.read(buffer)) != -1) {
|
|
58
|
+
if (isCancelled) {
|
|
59
|
+
in.close();
|
|
60
|
+
out.close();
|
|
61
|
+
connection.disconnect();
|
|
62
|
+
callback.onError(new IOException("Upload cancelled"));
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
out.write(buffer, 0, bytesRead);
|
|
67
|
+
sentBytes += bytesRead;
|
|
68
|
+
callback.onProgress(sentBytes, totalBytes);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
out.flush();
|
|
72
|
+
in.close();
|
|
73
|
+
out.close();
|
|
74
|
+
|
|
75
|
+
int responseCode = connection.getResponseCode();
|
|
76
|
+
InputStream responseStream = (responseCode >= 200 && responseCode < 400)
|
|
77
|
+
? connection.getInputStream()
|
|
78
|
+
: connection.getErrorStream();
|
|
79
|
+
String responseBody = readStream(responseStream);
|
|
80
|
+
|
|
81
|
+
callback.onComplete(responseCode, responseBody);
|
|
82
|
+
connection.disconnect();
|
|
83
|
+
} catch (Exception e) {
|
|
84
|
+
callback.onError(e);
|
|
85
|
+
}
|
|
86
|
+
}).start();
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
private String readStream(InputStream stream) throws IOException {
|
|
90
|
+
if (stream == null) return "";
|
|
91
|
+
|
|
92
|
+
BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
|
|
93
|
+
StringBuilder result = new StringBuilder();
|
|
94
|
+
String line;
|
|
95
|
+
while ((line = reader.readLine()) != null) {
|
|
96
|
+
result.append(line).append("\n");
|
|
97
|
+
}
|
|
98
|
+
reader.close();
|
|
99
|
+
return result.toString().trim();
|
|
100
|
+
}
|
|
101
|
+
}
|
package/ios/Mosquitodb.swift
CHANGED
|
@@ -100,7 +100,6 @@ class MosquitodbUploadTask: NSObject, URLSessionDataDelegate {
|
|
|
100
100
|
request.setValue(value, forHTTPHeaderField: key)
|
|
101
101
|
}
|
|
102
102
|
}
|
|
103
|
-
request.setValue("application/json", forHTTPHeaderField: "Accept")
|
|
104
103
|
if options["authToken"] != nil {
|
|
105
104
|
request.setValue(options["authToken"] as? String, forHTTPHeaderField: "Mosquito-Token")
|
|
106
105
|
}
|
|
@@ -137,7 +136,7 @@ class MosquitodbUploadTask: NSObject, URLSessionDataDelegate {
|
|
|
137
136
|
|
|
138
137
|
trigger!([
|
|
139
138
|
"mt-uploading-progress", [
|
|
140
|
-
"
|
|
139
|
+
"sentBytes": Float(totalBytesSent),
|
|
141
140
|
"totalBytes": Float(totalBytesExpectedToSend),
|
|
142
141
|
"processID": mainProcessID
|
|
143
142
|
]
|
package/package.json
CHANGED
package/src/index.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ import setLodash from 'lodash/set';
|
|
|
7
7
|
import unsetLodash from 'lodash/unset';
|
|
8
8
|
import { DatabaseRecordsListener } from "../../helpers/listeners";
|
|
9
9
|
import cloneDeep from "lodash/cloneDeep";
|
|
10
|
-
import { BSONRegExp, ObjectId, Timestamp } from "bson";
|
|
10
|
+
import { BSONRegExp, ObjectId, Timestamp } from "bson/lib/bson.rn.cjs";
|
|
11
11
|
import { niceGuard, Validator } from "guard-object";
|
|
12
12
|
import { TIMESTAMP } from "../..";
|
|
13
13
|
import { docSize, incrementDatabaseSize } from "./counter";
|
|
@@ -8,7 +8,7 @@ import { addPendingWrites, generateRecordID, getCountQuery, getRecord, insertCou
|
|
|
8
8
|
import { validateCollectionName, validateFilter, validateFindConfig, validateFindObject, validateListenFindConfig } from "./validator";
|
|
9
9
|
import { awaitRefreshToken, listenToken } from "../auth/accessor";
|
|
10
10
|
import { DELIVERY, RETRIEVAL } from "../../helpers/values";
|
|
11
|
-
import { ObjectId } from "bson";
|
|
11
|
+
import { ObjectId } from "bson/lib/bson.rn.cjs";
|
|
12
12
|
import { guardObject, Validator } from "guard-object";
|
|
13
13
|
import { simplifyCaughtError } from "simplify-error";
|
|
14
14
|
import cloneDeep from "lodash/cloneDeep";
|
|
@@ -2,7 +2,7 @@ import { guardArray, GuardError, guardObject, GuardSignal, niceGuard, Validator
|
|
|
2
2
|
import { sameInstance } from "../../helpers/peripherals";
|
|
3
3
|
import { RETRIEVAL } from "../../helpers/values";
|
|
4
4
|
import getLodash from 'lodash/get';
|
|
5
|
-
import { Binary, BSONRegExp, BSONSymbol, Code, DBRef, Decimal128, Double, Int32, Long, MaxKey, MinKey, ObjectId, Timestamp, UUID } from 'bson';
|
|
5
|
+
import { Binary, BSONRegExp, BSONSymbol, Code, DBRef, Decimal128, Double, Int32, Long, MaxKey, MinKey, ObjectId, Timestamp, UUID } from 'bson/lib/bson.rn.cjs';
|
|
6
6
|
import { bboxPolygon, booleanIntersects, booleanWithin, circle, distance, polygon } from "@turf/turf";
|
|
7
7
|
|
|
8
8
|
const DirectionList = [1, -1, 'asc', 'desc', 'ascending', 'descending'];
|
|
@@ -118,8 +118,14 @@ export class MTStorage {
|
|
|
118
118
|
const { createHash, awaitServer } = options || {};
|
|
119
119
|
let hasFinished, hasCancelled;
|
|
120
120
|
|
|
121
|
+
const thisComplete = (...args) => {
|
|
122
|
+
if (hasFinished) return;
|
|
123
|
+
hasFinished = true;
|
|
124
|
+
onComplete?.(...args);
|
|
125
|
+
}
|
|
126
|
+
|
|
121
127
|
if (typeof file !== 'string' || !file.trim()) {
|
|
122
|
-
|
|
128
|
+
thisComplete?.({ error: 'file_path_invalid', message: 'file must be a non-empty string in uploadFile()' });
|
|
123
129
|
return () => { };
|
|
124
130
|
}
|
|
125
131
|
destination = destination?.trim?.();
|
|
@@ -127,12 +133,11 @@ export class MTStorage {
|
|
|
127
133
|
try {
|
|
128
134
|
validateDestination(destination);
|
|
129
135
|
} catch (error) {
|
|
130
|
-
|
|
136
|
+
thisComplete?.({ error: 'destination_invalid', message: error });
|
|
131
137
|
return () => { };
|
|
132
138
|
}
|
|
133
139
|
|
|
134
|
-
const isAsset =
|
|
135
|
-
|
|
140
|
+
const isAsset = file.startsWith('ph://') || file.startsWith('content://');
|
|
136
141
|
file = isAsset ? file.trim() : prefixStoragePath(file.trim());
|
|
137
142
|
|
|
138
143
|
const { projectUrl, uglify, extraHeaders } = this.builder;
|
|
@@ -143,30 +148,28 @@ export class MTStorage {
|
|
|
143
148
|
await awaitRefreshToken(projectUrl);
|
|
144
149
|
|
|
145
150
|
if (hasCancelled) return;
|
|
146
|
-
const progressListener = emitter.addListener('mt-uploading-progress', ({ processID: ref,
|
|
151
|
+
const progressListener = emitter.addListener('mt-uploading-progress', ({ processID: ref, sentBytes, totalBytes }) => {
|
|
147
152
|
if (processID !== ref || hasFinished || hasCancelled) return;
|
|
148
|
-
onProgress?.({
|
|
153
|
+
onProgress?.({ sentBytes, totalBytes });
|
|
149
154
|
});
|
|
150
155
|
const resultListener = emitter.addListener('mt-uploading-status', ({ processID: ref, error, errorDes, result }) => {
|
|
151
|
-
if (processID !== ref
|
|
156
|
+
if (processID !== ref) return;
|
|
152
157
|
if (result)
|
|
153
158
|
try {
|
|
154
159
|
result = JSON.parse(result);
|
|
155
|
-
} catch (
|
|
160
|
+
} catch (_) { }
|
|
156
161
|
|
|
157
162
|
const downloadUrl = result?.downloadUrl || undefined;
|
|
158
|
-
|
|
159
|
-
if (!hasFinished && !hasCancelled)
|
|
160
|
-
onComplete?.(downloadUrl ? undefined : (result?.simpleError || { error, message: errorDes }), downloadUrl);
|
|
163
|
+
thisComplete?.(downloadUrl ? undefined : (result?.simpleError || { error, message: errorDes }), downloadUrl);
|
|
161
164
|
resultListener.remove();
|
|
162
165
|
progressListener.remove();
|
|
163
|
-
hasFinished = true;
|
|
164
166
|
});
|
|
167
|
+
const authToken = Scoped.AuthJWTToken[projectUrl];
|
|
165
168
|
|
|
166
169
|
RNMTModule.uploadFile({
|
|
167
170
|
url: EngineApi._uploadFile(projectUrl, uglify),
|
|
168
171
|
file: isAsset ? file : file.substring('file://'.length),
|
|
169
|
-
authToken:
|
|
172
|
+
...authToken ? { authToken } : {},
|
|
170
173
|
createHash: createHash ? 'yes' : 'no',
|
|
171
174
|
destination,
|
|
172
175
|
processID,
|
|
@@ -180,8 +183,8 @@ export class MTStorage {
|
|
|
180
183
|
if (hasFinished || hasCancelled) return;
|
|
181
184
|
hasCancelled = true;
|
|
182
185
|
setTimeout(() => {
|
|
183
|
-
|
|
184
|
-
},
|
|
186
|
+
thisComplete?.({ error: 'upload_aborted', message: 'The upload process was aborted' });
|
|
187
|
+
}, 0);
|
|
185
188
|
RNMTModule.cancelUpload(processID);
|
|
186
189
|
}
|
|
187
190
|
}
|