@ammarahmed/react-native-upload 6.16.0

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/dist/index.js ADDED
@@ -0,0 +1,390 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ var __generator = (this && this.__generator) || function (thisArg, body) {
11
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
12
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
13
+ function verb(n) { return function (v) { return step([n, v]); }; }
14
+ function step(op) {
15
+ if (f) throw new TypeError("Generator is already executing.");
16
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
17
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
18
+ if (y = 0, t) op = [op[0] & 2, t.value];
19
+ switch (op[0]) {
20
+ case 0: case 1: t = op; break;
21
+ case 4: _.label++; return { value: op[1], done: false };
22
+ case 5: _.label++; y = op[1]; op = [0]; continue;
23
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
24
+ default:
25
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
26
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
27
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
28
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
29
+ if (t[2]) _.ops.pop();
30
+ _.trys.pop(); continue;
31
+ }
32
+ op = body.call(thisArg, _);
33
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
34
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
35
+ }
36
+ };
37
+ /**
38
+ * Handles HTTP background file uploads from an iOS or Android device.
39
+ */
40
+ import { NativeModules, DeviceEventEmitter, Platform, } from 'react-native';
41
+ var NativeModule = NativeModules.VydiaRNFileUploader || NativeModules.RNFileUploader;
42
+ var eventPrefix = 'RNFileUploader-';
43
+ // for IOS, register event listeners or else they don't fire on DeviceEventEmitter
44
+ if (NativeModules.VydiaRNFileUploader) {
45
+ NativeModule.addListener(eventPrefix + 'progress');
46
+ NativeModule.addListener(eventPrefix + 'error');
47
+ NativeModule.addListener(eventPrefix + 'cancelled');
48
+ NativeModule.addListener(eventPrefix + 'completed');
49
+ }
50
+ export var UploadState = {
51
+ Cancelled: 'cancelled',
52
+ Completed: 'completed',
53
+ Pending: 'pending',
54
+ Running: 'running',
55
+ Error: 'error',
56
+ };
57
+ // Global registry to track active uploads and prevent duplicates
58
+ var UploadRegistry = /** @class */ (function () {
59
+ function UploadRegistry() {
60
+ }
61
+ UploadRegistry.register = function (upload) {
62
+ var id = upload.getId();
63
+ if (id) {
64
+ this.uploads.set(id, upload);
65
+ }
66
+ };
67
+ UploadRegistry.unregister = function (upload) {
68
+ var id = upload.getId();
69
+ if (id) {
70
+ this.uploads.delete(id);
71
+ }
72
+ };
73
+ UploadRegistry.getById = function (id) {
74
+ return this.uploads.get(id);
75
+ };
76
+ UploadRegistry.has = function (id) {
77
+ return this.uploads.has(id);
78
+ };
79
+ UploadRegistry.clear = function () {
80
+ this.uploads.clear();
81
+ };
82
+ UploadRegistry.uploads = new Map();
83
+ return UploadRegistry;
84
+ }());
85
+ var Upload = /** @class */ (function () {
86
+ function Upload(config) {
87
+ this.uploadId = null;
88
+ this.subscriptions = [];
89
+ this.status = UploadState.Pending;
90
+ this.startPromise = null;
91
+ this.resolveStart = null;
92
+ this.rejectStart = null;
93
+ this.changeCallback = null;
94
+ this.config = config;
95
+ }
96
+ /**
97
+ * Create a new upload instance or return existing one for the same path
98
+ */
99
+ Upload.create = function (config) {
100
+ // Check if there's an existing upload for this upload id
101
+ var existingUpload = config.customUploadId
102
+ ? UploadRegistry.getById(config.customUploadId)
103
+ : null;
104
+ if (existingUpload && existingUpload.isRunning()) {
105
+ console.warn("Upload already in progress for path: ".concat(config.path, ". Returning existing upload."));
106
+ return existingUpload;
107
+ }
108
+ var upload = new Upload(config);
109
+ return upload;
110
+ };
111
+ /**
112
+ * Resume an existing upload by ID (useful after app restart)
113
+ */
114
+ Upload.resume = function (uploadId) {
115
+ return __awaiter(this, void 0, void 0, function () {
116
+ var existingUpload, nativeUploads, uploadInfo, upload;
117
+ return __generator(this, function (_a) {
118
+ switch (_a.label) {
119
+ case 0:
120
+ existingUpload = UploadRegistry.getById(uploadId);
121
+ if (existingUpload) {
122
+ return [2 /*return*/, existingUpload];
123
+ }
124
+ return [4 /*yield*/, getAllUploads()];
125
+ case 1:
126
+ nativeUploads = _a.sent();
127
+ uploadInfo = nativeUploads.find(function (u) { return u.id === uploadId; });
128
+ if (!uploadInfo) {
129
+ return [2 /*return*/, null];
130
+ }
131
+ upload = new Upload({ url: '', path: '' });
132
+ upload.uploadId = uploadId;
133
+ upload.status = upload.mapNativeStateToStatus(uploadInfo.state);
134
+ // Register and setup listeners
135
+ UploadRegistry.register(upload);
136
+ upload.setupEventListeners();
137
+ return [2 /*return*/, upload];
138
+ }
139
+ });
140
+ });
141
+ };
142
+ /**
143
+ * Get all currently tracked uploads
144
+ */
145
+ Upload.getAll = function () {
146
+ var uploads = [];
147
+ UploadRegistry.uploads.forEach(function (upload) { return uploads.push(upload); });
148
+ return uploads;
149
+ };
150
+ /**
151
+ * Set a callback to be called whenever the upload state changes
152
+ */
153
+ Upload.prototype.onChange = function (callback) {
154
+ this.changeCallback = callback;
155
+ return this;
156
+ };
157
+ /**
158
+ * Start the upload - resolves when upload completes, is cancelled, or errors
159
+ */
160
+ Upload.prototype.start = function () {
161
+ return __awaiter(this, void 0, void 0, function () {
162
+ var nativeUploads, existingUpload, _a, error_1;
163
+ var _this = this;
164
+ return __generator(this, function (_b) {
165
+ switch (_b.label) {
166
+ case 0:
167
+ if (this.uploadId) {
168
+ throw new Error('Upload already started');
169
+ }
170
+ if (this.startPromise) {
171
+ return [2 /*return*/, this.startPromise];
172
+ }
173
+ if (!this.config.path) return [3 /*break*/, 2];
174
+ return [4 /*yield*/, getAllUploads()];
175
+ case 1:
176
+ nativeUploads = _b.sent();
177
+ existingUpload = nativeUploads.find(function (u) { return u.state === 'running' || u.state === 'pending'; });
178
+ if (existingUpload && !this.config.customUploadId) {
179
+ console.warn("Found existing upload in native side. Resuming upload: ".concat(existingUpload.id));
180
+ this.uploadId = existingUpload.id;
181
+ this.status = this.mapNativeStateToStatus(existingUpload.state);
182
+ UploadRegistry.register(this);
183
+ }
184
+ _b.label = 2;
185
+ case 2:
186
+ this.startPromise = new Promise(function (resolve, reject) {
187
+ _this.resolveStart = resolve;
188
+ _this.rejectStart = reject;
189
+ });
190
+ // Register event listeners
191
+ this.setupEventListeners();
192
+ if (!!this.uploadId) return [3 /*break*/, 6];
193
+ _b.label = 3;
194
+ case 3:
195
+ _b.trys.push([3, 5, , 6]);
196
+ _a = this;
197
+ return [4 /*yield*/, NativeModule.startUpload(this.config)];
198
+ case 4:
199
+ _a.uploadId = _b.sent();
200
+ this.updateStatus(UploadState.Running);
201
+ UploadRegistry.register(this);
202
+ return [3 /*break*/, 6];
203
+ case 5:
204
+ error_1 = _b.sent();
205
+ this.cleanup();
206
+ if (this.rejectStart) {
207
+ this.rejectStart(error_1);
208
+ }
209
+ throw error_1;
210
+ case 6: return [2 /*return*/, this.startPromise];
211
+ }
212
+ });
213
+ });
214
+ };
215
+ Upload.prototype.setupEventListeners = function () {
216
+ var _this = this;
217
+ // Progress listener
218
+ var progressSubscription = DeviceEventEmitter.addListener(eventPrefix + 'progress', function (data) {
219
+ if (_this.uploadId && data.id === _this.uploadId) {
220
+ _this.notifyChange({
221
+ status: UploadState.Running,
222
+ progress: data.progress,
223
+ });
224
+ }
225
+ });
226
+ this.subscriptions.push(progressSubscription);
227
+ // Completed listener
228
+ var completedSubscription = DeviceEventEmitter.addListener(eventPrefix + 'completed', function (data) {
229
+ if (_this.uploadId && data.id === _this.uploadId) {
230
+ _this.updateStatus(UploadState.Completed, undefined, data.responseCode, data.responseBody);
231
+ if (_this.resolveStart) {
232
+ _this.resolveStart({
233
+ status: 'completed',
234
+ responseCode: data.responseCode,
235
+ responseBody: data.responseBody,
236
+ });
237
+ }
238
+ _this.cleanup();
239
+ }
240
+ });
241
+ this.subscriptions.push(completedSubscription);
242
+ // Error listener
243
+ var errorSubscription = DeviceEventEmitter.addListener(eventPrefix + 'error', function (data) {
244
+ if (_this.uploadId && data.id === _this.uploadId) {
245
+ _this.updateStatus(UploadState.Error, data.error);
246
+ if (_this.resolveStart) {
247
+ _this.resolveStart({ status: 'error', error: data.error });
248
+ }
249
+ _this.cleanup();
250
+ }
251
+ });
252
+ this.subscriptions.push(errorSubscription);
253
+ // Cancelled listener
254
+ var cancelledSubscription = DeviceEventEmitter.addListener(eventPrefix + 'cancelled', function (data) {
255
+ if (_this.uploadId && data.id === _this.uploadId) {
256
+ _this.updateStatus(UploadState.Cancelled, data.error);
257
+ if (_this.resolveStart) {
258
+ _this.resolveStart({ status: 'cancelled', error: data.error });
259
+ }
260
+ _this.cleanup();
261
+ }
262
+ });
263
+ this.subscriptions.push(cancelledSubscription);
264
+ };
265
+ Upload.prototype.updateStatus = function (status, error, responseCode, responseBody) {
266
+ this.status = status;
267
+ this.notifyChange({ status: status, error: error, responseCode: responseCode, responseBody: responseBody });
268
+ };
269
+ Upload.prototype.notifyChange = function (event) {
270
+ if (this.changeCallback) {
271
+ this.changeCallback(event);
272
+ }
273
+ };
274
+ Upload.prototype.mapNativeStateToStatus = function (state) {
275
+ switch (state) {
276
+ case 'running':
277
+ return UploadState.Running;
278
+ case 'pending':
279
+ return UploadState.Pending;
280
+ case 'cancelled':
281
+ return UploadState.Cancelled;
282
+ case 'completed':
283
+ return UploadState.Completed;
284
+ default:
285
+ return UploadState.Pending;
286
+ }
287
+ };
288
+ /**
289
+ * Cancel the upload
290
+ */
291
+ Upload.prototype.cancel = function () {
292
+ return __awaiter(this, void 0, void 0, function () {
293
+ var result, error_2;
294
+ return __generator(this, function (_a) {
295
+ switch (_a.label) {
296
+ case 0:
297
+ if (!this.uploadId) {
298
+ throw new Error('Upload not started');
299
+ }
300
+ _a.label = 1;
301
+ case 1:
302
+ _a.trys.push([1, 3, , 4]);
303
+ return [4 /*yield*/, NativeModule.cancelUpload(this.uploadId)];
304
+ case 2:
305
+ result = _a.sent();
306
+ // Don't cleanup here - let the cancelled event handle it
307
+ return [2 /*return*/, result];
308
+ case 3:
309
+ error_2 = _a.sent();
310
+ this.cleanup();
311
+ throw error_2;
312
+ case 4: return [2 /*return*/];
313
+ }
314
+ });
315
+ });
316
+ };
317
+ /**
318
+ * Get the current upload status
319
+ */
320
+ Upload.prototype.getStatus = function () {
321
+ return this.status;
322
+ };
323
+ /**
324
+ * Get the upload ID
325
+ */
326
+ Upload.prototype.getId = function () {
327
+ return this.uploadId;
328
+ };
329
+ /**
330
+ * Get the file path
331
+ */
332
+ Upload.prototype.getPath = function () {
333
+ return this.config.path;
334
+ };
335
+ /**
336
+ * Check if upload is in progress
337
+ */
338
+ Upload.prototype.isRunning = function () {
339
+ return this.status === UploadState.Running;
340
+ };
341
+ /**
342
+ * Clean up listeners
343
+ */
344
+ Upload.prototype.cleanup = function () {
345
+ this.subscriptions.forEach(function (sub) { return sub.remove(); });
346
+ this.subscriptions = [];
347
+ this.resolveStart = null;
348
+ this.rejectStart = null;
349
+ UploadRegistry.unregister(this);
350
+ };
351
+ return Upload;
352
+ }());
353
+ // Legacy API exports for backward compatibility
354
+ export var getFileInfo = function (path) {
355
+ return NativeModule.getFileInfo(path).then(function (data) {
356
+ if (data.size) {
357
+ data.size = +data.size;
358
+ }
359
+ return data;
360
+ });
361
+ };
362
+ export var startUpload = function (options) {
363
+ return NativeModule.startUpload(options);
364
+ };
365
+ export var cancelUpload = function (cancelUploadId) {
366
+ if (typeof cancelUploadId !== 'string') {
367
+ return Promise.reject(new Error('Upload ID must be a string'));
368
+ }
369
+ return NativeModule.cancelUpload(cancelUploadId);
370
+ };
371
+ export var addListener = function (eventType, uploadId, listener) {
372
+ return DeviceEventEmitter.addListener(eventPrefix + eventType, function (data) {
373
+ if (!uploadId || !data || !('id' in data) || data.id === uploadId) {
374
+ listener(data);
375
+ }
376
+ });
377
+ };
378
+ export var canSuspendIfBackground = function () {
379
+ if (Platform.OS === 'ios') {
380
+ NativeModule.canSuspendIfBackground();
381
+ }
382
+ };
383
+ export var shouldLimitNetwork = function (limit) {
384
+ NativeModule.shouldLimitNetwork(limit);
385
+ };
386
+ export var getAllUploads = function () {
387
+ return NativeModule.getAllUploads();
388
+ };
389
+ export { Upload };
390
+ export default Upload;
@@ -0,0 +1,8 @@
1
+ #import <Foundation/Foundation.h>
2
+ #import <MobileCoreServices/MobileCoreServices.h>
3
+ #import <React/RCTEventEmitter.h>
4
+ #import <React/RCTBridgeModule.h>
5
+
6
+ @interface RNFileUploader : RCTEventEmitter <RCTBridgeModule, NSURLSessionTaskDelegate>
7
+ + (void)setCompletionHandlerWithIdentifier: (NSString *)identifier completionHandler: (void (^)())completionHandler;
8
+ @end