@roeehrl/tinode-sdk 0.25.1-sqlite.10 → 0.25.1-sqlite.12
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/package.json +1 -1
- package/src/comm-error.js +3 -2
- package/src/large-file.native.js +86 -79
- package/src/tinode.js +3 -1
- package/umd/tinode.dev.js +6 -26
- package/umd/tinode.dev.js.map +1 -1
- package/umd/tinode.prod.js +1 -1
- package/umd/tinode.prod.js.map +1 -1
- package/version.js +1 -1
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@roeehrl/tinode-sdk",
|
|
3
3
|
"description": "Tinode SDK fork with Storage interface for SQLite persistence in React Native",
|
|
4
|
-
"version": "0.25.1-sqlite.
|
|
4
|
+
"version": "0.25.1-sqlite.12",
|
|
5
5
|
"types": "./types/index.d.ts",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"format": "js-beautify -r src/*.js",
|
package/src/comm-error.js
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @file Throwable error with numeric error code.
|
|
2
|
+
* @file Throwable error with numeric error code and optional params.
|
|
3
3
|
*
|
|
4
4
|
* @copyright 2015-2023 Tinode LLC.
|
|
5
5
|
*/
|
|
6
6
|
'use strict';
|
|
7
7
|
|
|
8
8
|
export default class CommError extends Error {
|
|
9
|
-
constructor(message, code) {
|
|
9
|
+
constructor(message, code, params) {
|
|
10
10
|
super(`${message} (${code})`);
|
|
11
11
|
this.name = 'CommError';
|
|
12
12
|
this.code = code;
|
|
13
|
+
this.params = params;
|
|
13
14
|
}
|
|
14
15
|
}
|
package/src/large-file.native.js
CHANGED
|
@@ -112,21 +112,35 @@ export default class LargeFileHelperNative {
|
|
|
112
112
|
const url = this._buildUploadUrl(baseUrl);
|
|
113
113
|
const headers = this._buildHeaders();
|
|
114
114
|
|
|
115
|
+
// Log upload details
|
|
116
|
+
this._tinode.logger("Starting upload to:", url);
|
|
117
|
+
this._tinode.logger("Upload file:", {
|
|
118
|
+
uri,
|
|
119
|
+
filename,
|
|
120
|
+
mimetype,
|
|
121
|
+
size
|
|
122
|
+
});
|
|
123
|
+
|
|
115
124
|
// Create AbortController for cancellation
|
|
116
125
|
const abortController = new AbortController();
|
|
117
126
|
this._abortControllers.push(abortController);
|
|
118
127
|
|
|
119
|
-
|
|
128
|
+
// Use fetch instead of XHR - React Native XHR has issues with FormData uploads
|
|
129
|
+
// where the response body is not accessible. Fetch works correctly.
|
|
130
|
+
// Note: We lose upload progress tracking with fetch, but the upload works.
|
|
131
|
+
return (async () => {
|
|
120
132
|
try {
|
|
121
133
|
// Build FormData with file URI (React Native specific)
|
|
122
134
|
const formData = new FormData();
|
|
123
135
|
|
|
124
136
|
// React Native FormData accepts objects with uri, type, and name
|
|
125
|
-
|
|
137
|
+
const fileObj = {
|
|
126
138
|
uri: uri,
|
|
127
139
|
type: mimetype,
|
|
128
140
|
name: filename,
|
|
129
|
-
}
|
|
141
|
+
};
|
|
142
|
+
instance._tinode.logger("FormData file object:", fileObj);
|
|
143
|
+
formData.append('file', fileObj);
|
|
130
144
|
|
|
131
145
|
formData.append('id', this._tinode.getNextUniqueId());
|
|
132
146
|
|
|
@@ -134,103 +148,96 @@ export default class LargeFileHelperNative {
|
|
|
134
148
|
formData.append('topic', avatarFor);
|
|
135
149
|
}
|
|
136
150
|
|
|
137
|
-
//
|
|
138
|
-
|
|
139
|
-
|
|
151
|
+
// Signal progress start (we can't track actual progress with fetch)
|
|
152
|
+
if (onProgress) {
|
|
153
|
+
onProgress(0.1); // Indicate upload started
|
|
154
|
+
}
|
|
155
|
+
if (instance.onProgress) {
|
|
156
|
+
instance.onProgress(0.1);
|
|
157
|
+
}
|
|
140
158
|
|
|
141
|
-
|
|
159
|
+
instance._tinode.logger("Sending fetch request...");
|
|
142
160
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
161
|
+
const response = await fetch(url, {
|
|
162
|
+
method: 'POST',
|
|
163
|
+
headers: headers,
|
|
164
|
+
body: formData,
|
|
165
|
+
signal: abortController.signal,
|
|
146
166
|
});
|
|
147
167
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
168
|
+
instance._tinode.logger("Fetch response:", {
|
|
169
|
+
status: response.status,
|
|
170
|
+
statusText: response.statusText,
|
|
171
|
+
ok: response.ok,
|
|
151
172
|
});
|
|
152
173
|
|
|
153
|
-
//
|
|
154
|
-
if (onProgress
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
174
|
+
// Signal progress near completion
|
|
175
|
+
if (onProgress) {
|
|
176
|
+
onProgress(0.9);
|
|
177
|
+
}
|
|
178
|
+
if (instance.onProgress) {
|
|
179
|
+
instance.onProgress(0.9);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
const responseText = await response.text();
|
|
183
|
+
instance._tinode.logger("Response text:", responseText.substring(0, 200));
|
|
184
|
+
|
|
185
|
+
let pkt;
|
|
186
|
+
try {
|
|
187
|
+
pkt = JSON.parse(responseText);
|
|
188
|
+
} catch (err) {
|
|
189
|
+
instance._tinode.logger("ERROR: Failed to parse server response:", responseText);
|
|
190
|
+
pkt = {
|
|
191
|
+
ctrl: {
|
|
192
|
+
code: response.status,
|
|
193
|
+
text: response.statusText || 'Unknown error'
|
|
173
194
|
}
|
|
174
195
|
};
|
|
175
196
|
}
|
|
176
197
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
ctrl: {
|
|
185
|
-
code: this.status,
|
|
186
|
-
text: this.statusText
|
|
187
|
-
}
|
|
188
|
-
};
|
|
189
|
-
}
|
|
198
|
+
// Signal completion
|
|
199
|
+
if (onProgress) {
|
|
200
|
+
onProgress(1);
|
|
201
|
+
}
|
|
202
|
+
if (instance.onProgress) {
|
|
203
|
+
instance.onProgress(1);
|
|
204
|
+
}
|
|
190
205
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
}
|
|
197
|
-
} else if (this.status >= 400) {
|
|
198
|
-
const error = new CommError(pkt.ctrl.text, pkt.ctrl.code);
|
|
199
|
-
reject(error);
|
|
200
|
-
if (onFailure) {
|
|
201
|
-
onFailure(pkt.ctrl);
|
|
202
|
-
}
|
|
203
|
-
} else {
|
|
204
|
-
instance._tinode.logger("ERROR: Unexpected server response status", this.status, this.response);
|
|
205
|
-
reject(new Error(`Unexpected status: ${this.status}`));
|
|
206
|
+
if (response.ok && pkt.ctrl && pkt.ctrl.params && pkt.ctrl.params.url) {
|
|
207
|
+
const uploadUrl = pkt.ctrl.params.url;
|
|
208
|
+
instance._tinode.logger("Upload success, URL:", uploadUrl);
|
|
209
|
+
if (onSuccess) {
|
|
210
|
+
onSuccess(pkt.ctrl);
|
|
206
211
|
}
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
const
|
|
211
|
-
|
|
212
|
+
return uploadUrl;
|
|
213
|
+
} else if (response.status >= 400) {
|
|
214
|
+
const errorCode = pkt.ctrl?.code || response.status;
|
|
215
|
+
const errorText = pkt.ctrl?.text || 'Upload failed';
|
|
216
|
+
instance._tinode.logger("Upload error:", errorCode, errorText);
|
|
217
|
+
const error = new CommError(errorText, errorCode);
|
|
212
218
|
if (onFailure) {
|
|
213
|
-
onFailure(
|
|
219
|
+
onFailure(pkt.ctrl);
|
|
214
220
|
}
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
221
|
+
throw error;
|
|
222
|
+
} else {
|
|
223
|
+
instance._tinode.logger("ERROR: Unexpected response - status:", response.status, "response:", responseText);
|
|
224
|
+
throw new Error(`Unexpected status: ${response.status}, response: ${responseText ? responseText.substring(0, 100) : 'empty'}`);
|
|
225
|
+
}
|
|
226
|
+
} catch (err) {
|
|
227
|
+
if (err.name === 'AbortError') {
|
|
228
|
+
instance._tinode.logger("Upload aborted");
|
|
220
229
|
if (onFailure) {
|
|
221
230
|
onFailure(null);
|
|
222
231
|
}
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
} catch (err) {
|
|
228
|
-
reject(err);
|
|
232
|
+
throw new Error("Upload cancelled by user");
|
|
233
|
+
}
|
|
234
|
+
instance._tinode.logger("Upload error:", err.message);
|
|
229
235
|
if (onFailure) {
|
|
230
236
|
onFailure(null);
|
|
231
237
|
}
|
|
238
|
+
throw err;
|
|
232
239
|
}
|
|
233
|
-
});
|
|
240
|
+
})();
|
|
234
241
|
}
|
|
235
242
|
|
|
236
243
|
/**
|
package/src/tinode.js
CHANGED
|
@@ -495,6 +495,7 @@ export class Tinode {
|
|
|
495
495
|
|
|
496
496
|
// Resolve or reject a pending promise.
|
|
497
497
|
// Unresolved promises are stored in _pendingPromises.
|
|
498
|
+
// onOK is the full ctrl object, which contains params for error responses.
|
|
498
499
|
#execPromise(id, code, onOK, errorText) {
|
|
499
500
|
const callbacks = this._pendingPromises[id];
|
|
500
501
|
if (callbacks) {
|
|
@@ -504,7 +505,8 @@ export class Tinode {
|
|
|
504
505
|
callbacks.resolve(onOK);
|
|
505
506
|
}
|
|
506
507
|
} else if (callbacks.reject) {
|
|
507
|
-
|
|
508
|
+
// Pass params from ctrl response to CommError for richer error handling
|
|
509
|
+
callbacks.reject(new CommError(errorText, code, onOK?.params));
|
|
508
510
|
}
|
|
509
511
|
}
|
|
510
512
|
}
|
package/umd/tinode.dev.js
CHANGED
|
@@ -360,10 +360,11 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
360
360
|
|
|
361
361
|
|
|
362
362
|
class CommError extends Error {
|
|
363
|
-
constructor(message, code) {
|
|
363
|
+
constructor(message, code, params) {
|
|
364
364
|
super(`${message} (${code})`);
|
|
365
365
|
this.name = 'CommError';
|
|
366
366
|
this.code = code;
|
|
367
|
+
this.params = params;
|
|
367
368
|
}
|
|
368
369
|
}
|
|
369
370
|
|
|
@@ -852,15 +853,9 @@ class DB {
|
|
|
852
853
|
});
|
|
853
854
|
}
|
|
854
855
|
initDatabase() {
|
|
855
|
-
console.log('[DB] initDatabase CALLED, shouldDelegate:', this.#shouldDelegate(), 'delegateStorage:', !!this.#delegateStorage);
|
|
856
856
|
if (this.#shouldDelegate()) {
|
|
857
|
-
|
|
858
|
-
return this.#delegateStorage.initDatabase().then(result => {
|
|
859
|
-
console.log('[DB] initDatabase: SQLiteStorage initialized successfully');
|
|
860
|
-
return result;
|
|
861
|
-
});
|
|
857
|
+
return this.#delegateStorage.initDatabase();
|
|
862
858
|
}
|
|
863
|
-
console.log('[DB] initDatabase using IndexedDB');
|
|
864
859
|
return new Promise((resolve, reject) => {
|
|
865
860
|
const req = IDBProvider.open(DB_NAME, DB_VERSION);
|
|
866
861
|
req.onsuccess = event => {
|
|
@@ -955,10 +950,8 @@ class DB {
|
|
|
955
950
|
}
|
|
956
951
|
updTopic(topic) {
|
|
957
952
|
if (topic?._new) {
|
|
958
|
-
console.log('[DB] updTopic DEFERRED - topic not yet confirmed by server:', topic.name);
|
|
959
953
|
return Promise.resolve();
|
|
960
954
|
}
|
|
961
|
-
console.log('[DB] updTopic CALLED:', topic?.name, 'shouldDelegate:', this.#shouldDelegate());
|
|
962
955
|
if (this.#shouldDelegate()) {
|
|
963
956
|
return this.#delegateStorage.updTopic(topic);
|
|
964
957
|
}
|
|
@@ -1031,15 +1024,9 @@ class DB {
|
|
|
1031
1024
|
});
|
|
1032
1025
|
}
|
|
1033
1026
|
mapTopics(callback, context) {
|
|
1034
|
-
console.log('[DB] mapTopics CALLED, shouldDelegate:', this.#shouldDelegate());
|
|
1035
1027
|
if (this.#shouldDelegate()) {
|
|
1036
|
-
|
|
1037
|
-
return this.#delegateStorage.mapTopics(callback, context).then(result => {
|
|
1038
|
-
console.log('[DB] mapTopics: SQLiteStorage returned', result ? result.length : 0, 'topics');
|
|
1039
|
-
return result;
|
|
1040
|
-
});
|
|
1028
|
+
return this.#delegateStorage.mapTopics(callback, context);
|
|
1041
1029
|
}
|
|
1042
|
-
console.log('[DB] mapTopics using IndexedDB');
|
|
1043
1030
|
return this.#mapObjects('topic', callback, context);
|
|
1044
1031
|
}
|
|
1045
1032
|
deserializeTopic(topic, src) {
|
|
@@ -1246,12 +1233,9 @@ class DB {
|
|
|
1246
1233
|
});
|
|
1247
1234
|
}
|
|
1248
1235
|
readMessages(topicName, query, callback, context) {
|
|
1249
|
-
console.log('[DB] readMessages CALLED:', topicName, 'shouldDelegate:', this.#shouldDelegate(), 'delegateStorage:', !!this.#delegateStorage);
|
|
1250
1236
|
if (this.#shouldDelegate()) {
|
|
1251
|
-
console.log('[DB] readMessages DELEGATING to SQLiteStorage');
|
|
1252
1237
|
return this.#delegateStorage.readMessages(topicName, query, callback, context);
|
|
1253
1238
|
}
|
|
1254
|
-
console.log('[DB] readMessages NOT delegating, using IndexedDB');
|
|
1255
1239
|
query = query || {};
|
|
1256
1240
|
if (!this.isReady()) {
|
|
1257
1241
|
return this.disabled ? Promise.resolve([]) : Promise.reject(new Error("not initialized"));
|
|
@@ -5267,13 +5251,10 @@ class Topic {
|
|
|
5267
5251
|
return this._queuedSeqId++;
|
|
5268
5252
|
}
|
|
5269
5253
|
_loadMessages(db, query) {
|
|
5270
|
-
console.log('[Topic] _loadMessages CALLED:', this.name, 'query:', JSON.stringify(query), 'db:', !!db);
|
|
5271
5254
|
query = query || {};
|
|
5272
5255
|
query.limit = query.limit || _config_js__WEBPACK_IMPORTED_MODULE_3__.DEFAULT_MESSAGES_PAGE;
|
|
5273
5256
|
let count = 0;
|
|
5274
|
-
console.log('[Topic] _loadMessages: calling db.readMessages');
|
|
5275
5257
|
return db.readMessages(this.name, query).then(msgs => {
|
|
5276
|
-
console.log('[Topic] _loadMessages: db.readMessages returned', msgs ? msgs.length : 0, 'messages');
|
|
5277
5258
|
msgs.forEach(data => {
|
|
5278
5259
|
if (data.seq > this._maxSeq) {
|
|
5279
5260
|
this._maxSeq = data.seq;
|
|
@@ -5285,7 +5266,6 @@ class Topic {
|
|
|
5285
5266
|
this._maybeUpdateMessageVersionsCache(data);
|
|
5286
5267
|
});
|
|
5287
5268
|
count = msgs.length;
|
|
5288
|
-
console.log('[Topic] _loadMessages: processed', count, 'messages, _maxSeq:', this._maxSeq, '_minSeq:', this._minSeq);
|
|
5289
5269
|
}).then(_ => db.readDelLog(this.name, query)).then(dellog => {
|
|
5290
5270
|
return dellog.forEach(rec => {
|
|
5291
5271
|
this._messages.put({
|
|
@@ -5565,7 +5545,7 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
5565
5545
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
5566
5546
|
/* harmony export */ PACKAGE_VERSION: function() { return /* binding */ PACKAGE_VERSION; }
|
|
5567
5547
|
/* harmony export */ });
|
|
5568
|
-
const PACKAGE_VERSION = "0.25.1-sqlite.
|
|
5548
|
+
const PACKAGE_VERSION = "0.25.1-sqlite.12";
|
|
5569
5549
|
|
|
5570
5550
|
/***/ })
|
|
5571
5551
|
|
|
@@ -6027,7 +6007,7 @@ class Tinode {
|
|
|
6027
6007
|
callbacks.resolve(onOK);
|
|
6028
6008
|
}
|
|
6029
6009
|
} else if (callbacks.reject) {
|
|
6030
|
-
callbacks.reject(new _comm_error_js__WEBPACK_IMPORTED_MODULE_2__["default"](errorText, code));
|
|
6010
|
+
callbacks.reject(new _comm_error_js__WEBPACK_IMPORTED_MODULE_2__["default"](errorText, code, onOK?.params));
|
|
6031
6011
|
}
|
|
6032
6012
|
}
|
|
6033
6013
|
}
|