rn-file-toolkit 1.0.8 → 1.0.10

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.
@@ -24,6 +24,12 @@ export interface Spec extends TurboModule {
24
24
  openFile(filePath: string, mimeType: string): Promise<Object>;
25
25
  unzip(sourcePath: string, destDir: string): Promise<Object>;
26
26
  zip(sourcePath: string, destPath: string): Promise<Object>;
27
+ df(): Promise<Object>;
28
+ appendFile(filePath: string, data: string, encoding: string): Promise<Object>;
29
+ hash(filePath: string, algorithm: string): Promise<Object>;
30
+ getCookies(domain: string): Promise<Object>;
31
+ clearCookies(domain: string): Promise<Object>;
32
+ saveToMediaStore(options: Object): Promise<Object>;
27
33
  }
28
34
 
29
35
  export default TurboModuleRegistry.getEnforcing<Spec>('FileToolkit');
package/src/index.tsx CHANGED
@@ -136,6 +136,56 @@ export interface FsStat {
136
136
  isDir: boolean;
137
137
  }
138
138
 
139
+ export interface DiskSpaceResult {
140
+ success: boolean;
141
+ freeBytes?: number;
142
+ totalBytes?: number;
143
+ error?: string;
144
+ }
145
+
146
+ export type HashAlgorithm = 'md5' | 'sha1' | 'sha256';
147
+
148
+ export interface HashResult {
149
+ success: boolean;
150
+ hash?: string;
151
+ error?: string;
152
+ }
153
+
154
+ export interface Cookie {
155
+ name: string;
156
+ value: string;
157
+ domain: string;
158
+ path: string;
159
+ expiresDate?: number;
160
+ isSecure?: boolean;
161
+ isHTTPOnly?: boolean;
162
+ }
163
+
164
+ export interface CookiesResult {
165
+ success: boolean;
166
+ cookies?: Cookie[];
167
+ error?: string;
168
+ }
169
+
170
+ export interface MediaStoreOptions {
171
+ filePath: string;
172
+ mediaType?: 'image' | 'video' | 'audio' | 'download';
173
+ album?: string;
174
+ }
175
+
176
+ export interface MediaStoreResult {
177
+ success: boolean;
178
+ uri?: string;
179
+ error?: string;
180
+ }
181
+
182
+ export interface SessionApi {
183
+ add: (sessionId: string, filePath: string) => void;
184
+ get: (sessionId: string) => string[];
185
+ clear: (sessionId: string) => Promise<ActionResult>;
186
+ clearAll: () => Promise<ActionResult>;
187
+ }
188
+
139
189
  export interface FsApi {
140
190
  exists: (filePath: string) => Promise<boolean>;
141
191
  stat: (filePath: string) => Promise<FsStat>;
@@ -145,11 +195,18 @@ export interface FsApi {
145
195
  data: string,
146
196
  encoding?: FsEncoding
147
197
  ) => Promise<void>;
198
+ appendFile: (
199
+ filePath: string,
200
+ data: string,
201
+ encoding?: FsEncoding
202
+ ) => Promise<void>;
148
203
  copyFile: (fromPath: string, toPath: string) => Promise<void>;
149
204
  moveFile: (fromPath: string, toPath: string) => Promise<void>;
150
205
  deleteFile: (filePath: string) => Promise<void>;
151
206
  mkdir: (dirPath: string) => Promise<void>;
152
207
  ls: (dirPath: string) => Promise<string[]>;
208
+ df: () => Promise<DiskSpaceResult>;
209
+ hash: (filePath: string, algorithm?: HashAlgorithm) => Promise<HashResult>;
153
210
  }
154
211
 
155
212
  export interface QueueOptions {
@@ -226,8 +283,8 @@ const _globalQueue = new DownloadQueue();
226
283
 
227
284
  function _generateId(): string {
228
285
  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
229
- const r = (Math.random() * 16) | 0;
230
- const v = c === 'x' ? r : (r & 0x3) | 0x8;
286
+ const r = Math.floor(Math.random() * 16);
287
+ const v = c === 'x' ? r : (r % 4) + 8;
231
288
  return v.toString(16);
232
289
  });
233
290
  }
@@ -313,13 +370,24 @@ async function _executeDownload(
313
370
  };
314
371
 
315
372
  try {
316
- const result = await (FileToolkitModule as any).download({
373
+ // Strip JS-only fields functions cannot be serialized across the native bridge
374
+ const nativeOpts: any = {
317
375
  ...options,
318
376
  downloadId,
319
377
  background: options.background ?? false,
320
378
  headers: options.headers ?? {},
321
379
  destination: options.destination ?? 'downloads',
322
- });
380
+ };
381
+ delete nativeOpts.onProgress;
382
+ delete nativeOpts.queue;
383
+ delete nativeOpts.priority;
384
+ if (nativeOpts.retry) {
385
+ nativeOpts.retry = {
386
+ attempts: nativeOpts.retry.attempts,
387
+ delay: nativeOpts.retry.delay,
388
+ };
389
+ }
390
+ const result = await (FileToolkitModule as any).download(nativeOpts);
323
391
  cleanup();
324
392
  return result as DownloadResult;
325
393
  } catch (error: any) {
@@ -342,13 +410,16 @@ export async function upload(options: UploadOptions): Promise<UploadResult> {
342
410
  });
343
411
  }
344
412
  try {
345
- const res = await (FileToolkitModule as any).upload({
413
+ // Strip onProgress callback functions cannot be serialized across the native bridge
414
+ const nativeUploadOpts: any = {
346
415
  ...options,
347
416
  uploadId,
348
417
  fieldName: options.fieldName ?? 'file',
349
418
  headers: options.headers ?? {},
350
419
  parameters: options.parameters ?? {},
351
- });
420
+ };
421
+ delete nativeUploadOpts.onProgress;
422
+ const res = await (FileToolkitModule as any).upload(nativeUploadOpts);
352
423
  sub?.remove();
353
424
  return { ...res, uploadId } as UploadResult;
354
425
  } catch (err: any) {
@@ -468,11 +539,125 @@ export async function ls(path: string): Promise<string[]> {
468
539
  return res.entries || [];
469
540
  }
470
541
 
542
+ export async function df(): Promise<DiskSpaceResult> {
543
+ try {
544
+ return await (FileToolkitModule as any).df();
545
+ } catch (err: any) {
546
+ return { success: false, error: err.message || 'DF_ERROR' };
547
+ }
548
+ }
549
+
550
+ export async function appendFile(
551
+ path: string,
552
+ data: string,
553
+ enc: FsEncoding = 'utf8'
554
+ ): Promise<void> {
555
+ const res = await (FileToolkitModule as any).appendFile(path, data, enc);
556
+ _ensure(res, 'APPEND_ERROR');
557
+ }
558
+
559
+ export async function hash(
560
+ path: string,
561
+ algorithm: HashAlgorithm = 'md5'
562
+ ): Promise<HashResult> {
563
+ try {
564
+ return await (FileToolkitModule as any).hash(path, algorithm);
565
+ } catch (err: any) {
566
+ return { success: false, error: err.message || 'HASH_ERROR' };
567
+ }
568
+ }
569
+
570
+ export async function getCookies(domain: string): Promise<CookiesResult> {
571
+ try {
572
+ return await (FileToolkitModule as any).getCookies(domain);
573
+ } catch (err: any) {
574
+ return { success: false, error: err.message || 'GET_COOKIES_ERROR' };
575
+ }
576
+ }
577
+
578
+ export async function clearCookies(domain: string = ''): Promise<ActionResult> {
579
+ try {
580
+ return await (FileToolkitModule as any).clearCookies(domain);
581
+ } catch (err: any) {
582
+ return { success: false, error: err.message || 'CLEAR_COOKIES_ERROR' };
583
+ }
584
+ }
585
+
586
+ export async function saveToMediaStore(
587
+ opts: MediaStoreOptions
588
+ ): Promise<MediaStoreResult> {
589
+ try {
590
+ return await (FileToolkitModule as any).saveToMediaStore({
591
+ filePath: opts.filePath,
592
+ mediaType: opts.mediaType ?? 'download',
593
+ album: opts.album,
594
+ });
595
+ } catch (err: any) {
596
+ return { success: false, error: err.message || 'MEDIA_STORE_ERROR' };
597
+ }
598
+ }
599
+
600
+ // ─── Session Management (JS-only) ──────────────────────────────────────────
601
+
602
+ const _sessionRegistry = new Map<string, Set<string>>();
603
+
604
+ function _sessionAdd(sessionId: string, filePath: string): void {
605
+ let set = _sessionRegistry.get(sessionId);
606
+ if (!set) {
607
+ set = new Set();
608
+ _sessionRegistry.set(sessionId, set);
609
+ }
610
+ set.add(filePath);
611
+ }
612
+
613
+ function _sessionGet(sessionId: string): string[] {
614
+ const set = _sessionRegistry.get(sessionId);
615
+ return set ? Array.from(set) : [];
616
+ }
617
+
618
+ async function _sessionClear(sessionId: string): Promise<ActionResult> {
619
+ const set = _sessionRegistry.get(sessionId);
620
+ if (!set) return { success: true };
621
+ const errors: string[] = [];
622
+ for (const filePath of set) {
623
+ const res = await deleteFile(filePath);
624
+ if (!res.success && res.error) errors.push(res.error);
625
+ }
626
+ _sessionRegistry.delete(sessionId);
627
+ return errors.length > 0
628
+ ? { success: false, error: errors.join('; ') }
629
+ : { success: true };
630
+ }
631
+
632
+ async function _sessionClearAll(): Promise<ActionResult> {
633
+ const errors: string[] = [];
634
+ for (const [sessionId] of _sessionRegistry) {
635
+ const res = await _sessionClear(sessionId);
636
+ if (!res.success && res.error) errors.push(res.error);
637
+ }
638
+ return errors.length > 0
639
+ ? { success: false, error: errors.join('; ') }
640
+ : { success: true };
641
+ }
642
+
643
+ export const session: SessionApi = {
644
+ add: _sessionAdd,
645
+ get: _sessionGet,
646
+ clear: _sessionClear,
647
+ clearAll: _sessionClearAll,
648
+ };
649
+
650
+ export const cookies = {
651
+ get: getCookies,
652
+ clear: clearCookies,
653
+ };
654
+
471
655
  export const fs: FsApi = {
472
656
  exists,
473
657
  stat,
474
658
  readFile,
475
659
  writeFile,
660
+ appendFile,
476
661
  copyFile,
477
662
  moveFile,
478
663
  deleteFile: async (p) => {
@@ -480,6 +665,8 @@ export const fs: FsApi = {
480
665
  },
481
666
  mkdir,
482
667
  ls,
668
+ df,
669
+ hash,
483
670
  };
484
671
 
485
672
  export function onDownloadComplete(cb: any) {
@@ -676,11 +863,19 @@ export default {
676
863
  stat,
677
864
  readFile,
678
865
  writeFile,
866
+ appendFile,
679
867
  copyFile,
680
868
  moveFile,
681
869
  mkdir,
682
870
  ls,
871
+ df,
872
+ hash,
873
+ getCookies,
874
+ clearCookies,
875
+ saveToMediaStore,
683
876
  fs,
877
+ cookies,
878
+ session,
684
879
  useDownload,
685
880
  unzip,
686
881
  zip,