@uploadista/react-native-bare 0.0.8 → 0.0.9

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.
@@ -17,4 +17,4 @@ declare class NativeFileSystemProvider implements FileSystemProvider {
17
17
  }
18
18
  //#endregion
19
19
  export { NativeFileSystemProvider };
20
- //# sourceMappingURL=index.d.ts.map
20
+ //# sourceMappingURL=index.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/services/native-file-system-provider.ts"],"sourcesContent":[],"mappings":";;;;;;AAeA;;AACuD,cAD1C,wBAAA,YAAoC,kBACM,CAAA;EAAR,YAAA,CAAA,OAAA,CAAA,EAAhB,aAAgB,CAAA,EAAA,OAAA,CAAQ,cAAR,CAAA;EA2CnB,SAAA,CAAA,OAAA,CAAA,EAAA,aAAA,CAAA,EAAgB,OAAhB,CAAwB,cAAxB,CAAA;EAAwB,SAAA,CAAA,OAAA,CAAA,EA+DxB,aA/DwB,CAAA,EA+DR,OA/DQ,CA+DA,cA/DA,CAAA;EAAR,UAAA,CAAA,OAAA,CAAA,EA4Hf,aA5He,CAAA,EA4HC,OA5HD,CA4HS,cA5HT,CAAA;EA+DhB,QAAA,CAAA,GAAA,EAAA,MAAA,CAAA,EA4HG,OA5HH,CA4HW,WA5HX,CAAA;EAAwB,cAAA,CAAA,QAAA,EAAA,MAAA,CAAA,EA+IV,OA/IU,CAAA,MAAA,CAAA;EAAR,WAAA,CAAA,GAAA,EAAA,MAAA,CAAA,EAoJV,OApJU,CAoJF,QApJE,CAAA"}
package/dist/index.mjs ADDED
@@ -0,0 +1,2 @@
1
+ import*as e from"@react-native-documents/picker";import*as t from"react-native-image-picker";import n from"rn-fetch-blob";var r=class{async pickDocument(t){try{let n=await e.pick({type:t?.allowedTypes||[e.types.allFiles],...t?.allowMultiple&&{isMultiple:!0}}),r=Array.isArray(n)?n[0]:n;return r?{status:`success`,data:{uri:r.uri,name:r.name||`document`,size:r.size||0,mimeType:r.type||void 0,localPath:r.uri||void 0}}:{status:`cancelled`}}catch(e){return e instanceof Error&&(e.message.includes(`cancelled`)||e.message.includes(`Cancelled`))?{status:`cancelled`}:{status:`error`,error:e instanceof Error?e:Error(`Failed to pick document: ${e instanceof Error?e.message:String(e)}`)}}}async pickImage(e){try{return new Promise(n=>{t.launchImageLibrary({mediaType:`photo`,selectionLimit:e?.allowMultiple?0:1,quality:1},e=>{let t=e;if(t.didCancel)n({status:`cancelled`});else if(t.errorCode)n({status:`error`,error:Error(`Image picker error: ${t.errorCode}`)});else if(t.assets&&t.assets.length>0){let e=t.assets[0];n(e?{status:`success`,data:{uri:e.uri,name:e.fileName||`image-${Date.now()}.jpg`,size:e.fileSize||0,mimeType:e.type||`image/jpeg`}}:{status:`cancelled`})}else n({status:`cancelled`})})})}catch(e){return{status:`error`,error:e instanceof Error?e:Error(`Failed to pick image: ${e instanceof Error?e.message:String(e)}`)}}}async pickVideo(e){try{return new Promise(n=>{t.launchImageLibrary({mediaType:`video`,selectionLimit:e?.allowMultiple?0:1},e=>{let t=e;if(t.didCancel)n({status:`cancelled`});else if(t.errorCode)n({status:`error`,error:Error(`Video picker error: ${t.errorCode}`)});else if(t.assets&&t.assets.length>0){let e=t.assets[0];n(e?{status:`success`,data:{uri:e.uri,name:e.fileName||`video-${Date.now()}.mp4`,size:e.fileSize||0,mimeType:e.type||`video/mp4`}}:{status:`cancelled`})}else n({status:`cancelled`})})})}catch(e){return{status:`error`,error:e instanceof Error?e:Error(`Failed to pick video: ${e instanceof Error?e.message:String(e)}`)}}}async pickCamera(e){try{return new Promise(n=>{t.launchCamera({mediaType:`photo`,cameraType:e?.cameraType===`front`?`front`:`back`,quality:e?.quality??1},e=>{let t=e;if(t.didCancel)n({status:`cancelled`});else if(t.errorCode)n({status:`error`,error:Error(`Camera error: ${t.errorCode}`)});else if(t.assets&&t.assets.length>0){let e=t.assets[0];n(e?{status:`success`,data:{uri:e.uri,name:e.fileName||`photo-${Date.now()}.jpg`,size:e.fileSize||0,mimeType:e.type||`image/jpeg`}}:{status:`cancelled`})}else n({status:`cancelled`})})})}catch(e){return{status:`error`,error:e instanceof Error?e:Error(`Failed to capture photo: ${e instanceof Error?e.message:String(e)}`)}}}async readFile(e){try{let t=await n.fs.readFile(e,`base64`),r=atob(t),i=new Uint8Array(r.length);for(let e=0;e<r.length;e++)i[e]=r.charCodeAt(e);return i.buffer}catch(e){throw Error(`Failed to read file: ${e instanceof Error?e.message:String(e)}`)}}async getDocumentUri(e){return e}async getFileInfo(e){try{let t=await n.fs.stat(e);return{uri:e,name:t.filename||e.split(`/`).pop()||`unknown`,size:t.size||0,modificationTime:t.lastModified?typeof t.lastModified==`string`?parseInt(t.lastModified,10):t.lastModified:void 0}}catch(e){throw Error(`Failed to get file info: ${e instanceof Error?e.message:String(e)}`)}}};export{r as NativeFileSystemProvider};
2
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/services/native-file-system-provider.ts"],"sourcesContent":["import * as DocumentPicker from \"@react-native-documents/picker\";\nimport type {\n CameraOptions,\n FileInfo,\n FilePickResult,\n FileSystemProvider,\n PickerOptions,\n} from \"@uploadista/react-native-core\";\nimport * as ImagePicker from \"react-native-image-picker\";\nimport RNFetchBlob from \"rn-fetch-blob\";\n\n/**\n * File system provider implementation for bare React Native environment\n * Uses react-native-image-picker, react-native-fs, and native APIs\n */\nexport class NativeFileSystemProvider implements FileSystemProvider {\n async pickDocument(options?: PickerOptions): Promise<FilePickResult> {\n try {\n const result = await DocumentPicker.pick({\n type: options?.allowedTypes || [DocumentPicker.types.allFiles],\n ...(options?.allowMultiple && { isMultiple: true }),\n });\n\n const file = Array.isArray(result) ? result[0] : result;\n\n if (!file) {\n return { status: \"cancelled\" };\n }\n\n return {\n status: \"success\",\n data: {\n uri: file.uri,\n name: file.name || \"document\",\n size: file.size || 0,\n mimeType: file.type || undefined,\n localPath: file.uri || undefined,\n },\n };\n } catch (error) {\n if (\n error instanceof Error &&\n (error.message.includes(\"cancelled\") ||\n error.message.includes(\"Cancelled\"))\n ) {\n return { status: \"cancelled\" };\n }\n return {\n status: \"error\",\n error:\n error instanceof Error\n ? error\n : new Error(\n `Failed to pick document: ${error instanceof Error ? error.message : String(error)}`,\n ),\n };\n }\n }\n\n async pickImage(options?: PickerOptions): Promise<FilePickResult> {\n try {\n return new Promise((resolve) => {\n ImagePicker.launchImageLibrary(\n {\n mediaType: \"photo\",\n selectionLimit: options?.allowMultiple ? 0 : 1,\n quality: 1,\n // biome-ignore lint/suspicious/noExplicitAny: react-native-image-picker type mismatch\n } as any,\n (response: unknown) => {\n const res = response as {\n didCancel?: boolean;\n errorCode?: string;\n assets?: Array<{\n uri: string;\n fileName?: string;\n fileSize?: number;\n type?: string;\n }>;\n };\n\n if (res.didCancel) {\n resolve({ status: \"cancelled\" });\n } else if (res.errorCode) {\n resolve({\n status: \"error\",\n error: new Error(`Image picker error: ${res.errorCode}`),\n });\n } else if (res.assets && res.assets.length > 0) {\n const asset = res.assets[0];\n if (asset) {\n resolve({\n status: \"success\",\n data: {\n uri: asset.uri,\n name: asset.fileName || `image-${Date.now()}.jpg`,\n size: asset.fileSize || 0,\n mimeType: asset.type || \"image/jpeg\",\n },\n });\n } else {\n resolve({ status: \"cancelled\" });\n }\n } else {\n resolve({ status: \"cancelled\" });\n }\n },\n );\n });\n } catch (error) {\n return {\n status: \"error\",\n error:\n error instanceof Error\n ? error\n : new Error(\n `Failed to pick image: ${error instanceof Error ? error.message : String(error)}`,\n ),\n };\n }\n }\n\n async pickVideo(options?: PickerOptions): Promise<FilePickResult> {\n try {\n return new Promise((resolve) => {\n ImagePicker.launchImageLibrary(\n {\n mediaType: \"video\",\n selectionLimit: options?.allowMultiple ? 0 : 1,\n },\n (response: unknown) => {\n const res = response as {\n didCancel?: boolean;\n errorCode?: string;\n assets?: Array<{\n uri: string;\n fileName?: string;\n fileSize?: number;\n type?: string;\n }>;\n };\n\n if (res.didCancel) {\n resolve({ status: \"cancelled\" });\n } else if (res.errorCode) {\n resolve({\n status: \"error\",\n error: new Error(`Video picker error: ${res.errorCode}`),\n });\n } else if (res.assets && res.assets.length > 0) {\n const asset = res.assets[0];\n if (asset) {\n resolve({\n status: \"success\",\n data: {\n uri: asset.uri,\n name: asset.fileName || `video-${Date.now()}.mp4`,\n size: asset.fileSize || 0,\n mimeType: asset.type || \"video/mp4\",\n },\n });\n } else {\n resolve({ status: \"cancelled\" });\n }\n } else {\n resolve({ status: \"cancelled\" });\n }\n },\n );\n });\n } catch (error) {\n return {\n status: \"error\",\n error:\n error instanceof Error\n ? error\n : new Error(\n `Failed to pick video: ${error instanceof Error ? error.message : String(error)}`,\n ),\n };\n }\n }\n\n async pickCamera(options?: CameraOptions): Promise<FilePickResult> {\n try {\n return new Promise((resolve) => {\n ImagePicker.launchCamera(\n {\n mediaType: \"photo\",\n cameraType: options?.cameraType === \"front\" ? \"front\" : \"back\",\n quality: options?.quality ?? 1,\n // biome-ignore lint/suspicious/noExplicitAny: react-native-image-picker type mismatch\n } as any,\n (response: unknown) => {\n const res = response as {\n didCancel?: boolean;\n errorCode?: string;\n assets?: Array<{\n uri: string;\n fileName?: string;\n fileSize?: number;\n type?: string;\n }>;\n };\n\n if (res.didCancel) {\n resolve({ status: \"cancelled\" });\n } else if (res.errorCode) {\n resolve({\n status: \"error\",\n error: new Error(`Camera error: ${res.errorCode}`),\n });\n } else if (res.assets && res.assets.length > 0) {\n const asset = res.assets[0];\n if (asset) {\n resolve({\n status: \"success\",\n data: {\n uri: asset.uri,\n name: asset.fileName || `photo-${Date.now()}.jpg`,\n size: asset.fileSize || 0,\n mimeType: asset.type || \"image/jpeg\",\n },\n });\n } else {\n resolve({ status: \"cancelled\" });\n }\n } else {\n resolve({ status: \"cancelled\" });\n }\n },\n );\n });\n } catch (error) {\n return {\n status: \"error\",\n error:\n error instanceof Error\n ? error\n : new Error(\n `Failed to capture photo: ${error instanceof Error ? error.message : String(error)}`,\n ),\n };\n }\n }\n\n async readFile(uri: string): Promise<ArrayBuffer> {\n try {\n // Read file as base64\n const base64Data = await RNFetchBlob.fs.readFile(uri, \"base64\");\n\n // Convert base64 to ArrayBuffer\n const binaryString = atob(base64Data);\n const bytes = new Uint8Array(binaryString.length);\n for (let i = 0; i < binaryString.length; i++) {\n bytes[i] = binaryString.charCodeAt(i);\n }\n return bytes.buffer;\n } catch (error) {\n throw new Error(\n `Failed to read file: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n async getDocumentUri(filePath: string): Promise<string> {\n // In bare RN with native modules, the path is typically already a URI\n return filePath;\n }\n\n async getFileInfo(uri: string): Promise<FileInfo> {\n try {\n const stat = await RNFetchBlob.fs.stat(uri);\n\n return {\n uri,\n name: stat.filename || uri.split(\"/\").pop() || \"unknown\",\n size: stat.size || 0,\n modificationTime: stat.lastModified\n ? typeof stat.lastModified === \"string\"\n ? parseInt(stat.lastModified, 10)\n : stat.lastModified\n : undefined,\n };\n } catch (error) {\n throw new Error(\n `Failed to get file info: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -2,15 +2,15 @@
2
2
  "name": "@uploadista/react-native-bare",
3
3
  "type": "module",
4
4
  "description": "Bare React Native Client for Uploadista",
5
- "version": "0.0.8",
5
+ "version": "0.0.9",
6
6
  "license": "MIT",
7
7
  "author": "Uploadista",
8
8
  "exports": {
9
9
  ".": "./src/index.ts"
10
10
  },
11
11
  "dependencies": {
12
- "@uploadista/client-core": "0.0.8",
13
- "@uploadista/react-native-core": "0.0.8"
12
+ "@uploadista/client-core": "0.0.9",
13
+ "@uploadista/react-native-core": "0.0.9"
14
14
  },
15
15
  "peerDependencies": {
16
16
  "react": ">=16.8.0",
@@ -21,8 +21,8 @@
21
21
  },
22
22
  "devDependencies": {
23
23
  "@types/react": ">=18.0.0",
24
- "tsdown": "0.15.10",
25
- "@uploadista/typescript-config": "0.0.8"
24
+ "tsdown": "0.16.0",
25
+ "@uploadista/typescript-config": "0.0.9"
26
26
  },
27
27
  "scripts": {
28
28
  "build": "tsdown",
@@ -24,15 +24,18 @@ export class NativeFileSystemProvider implements FileSystemProvider {
24
24
  const file = Array.isArray(result) ? result[0] : result;
25
25
 
26
26
  if (!file) {
27
- throw new Error("No document selected");
27
+ return { status: "cancelled" };
28
28
  }
29
29
 
30
30
  return {
31
- uri: file.uri,
32
- name: file.name || "document",
33
- size: file.size || 0,
34
- mimeType: file.type || undefined,
35
- localPath: file.uri || undefined,
31
+ status: "success",
32
+ data: {
33
+ uri: file.uri,
34
+ name: file.name || "document",
35
+ size: file.size || 0,
36
+ mimeType: file.type || undefined,
37
+ localPath: file.uri || undefined,
38
+ },
36
39
  };
37
40
  } catch (error) {
38
41
  if (
@@ -40,17 +43,23 @@ export class NativeFileSystemProvider implements FileSystemProvider {
40
43
  (error.message.includes("cancelled") ||
41
44
  error.message.includes("Cancelled"))
42
45
  ) {
43
- throw error;
46
+ return { status: "cancelled" };
44
47
  }
45
- throw new Error(
46
- `Failed to pick document: ${error instanceof Error ? error.message : String(error)}`,
47
- );
48
+ return {
49
+ status: "error",
50
+ error:
51
+ error instanceof Error
52
+ ? error
53
+ : new Error(
54
+ `Failed to pick document: ${error instanceof Error ? error.message : String(error)}`,
55
+ ),
56
+ };
48
57
  }
49
58
  }
50
59
 
51
60
  async pickImage(options?: PickerOptions): Promise<FilePickResult> {
52
61
  try {
53
- return new Promise((resolve, reject) => {
62
+ return new Promise((resolve) => {
54
63
  ImagePicker.launchImageLibrary(
55
64
  {
56
65
  mediaType: "photo",
@@ -71,37 +80,49 @@ export class NativeFileSystemProvider implements FileSystemProvider {
71
80
  };
72
81
 
73
82
  if (res.didCancel) {
74
- reject(new Error("Image picker was cancelled"));
83
+ resolve({ status: "cancelled" });
75
84
  } else if (res.errorCode) {
76
- reject(new Error(`Image picker error: ${res.errorCode}`));
85
+ resolve({
86
+ status: "error",
87
+ error: new Error(`Image picker error: ${res.errorCode}`),
88
+ });
77
89
  } else if (res.assets && res.assets.length > 0) {
78
90
  const asset = res.assets[0];
79
91
  if (asset) {
80
92
  resolve({
81
- uri: asset.uri,
82
- name: asset.fileName || `image-${Date.now()}.jpg`,
83
- size: asset.fileSize || 0,
84
- mimeType: asset.type || "image/jpeg",
93
+ status: "success",
94
+ data: {
95
+ uri: asset.uri,
96
+ name: asset.fileName || `image-${Date.now()}.jpg`,
97
+ size: asset.fileSize || 0,
98
+ mimeType: asset.type || "image/jpeg",
99
+ },
85
100
  });
86
101
  } else {
87
- reject(new Error("No image selected"));
102
+ resolve({ status: "cancelled" });
88
103
  }
89
104
  } else {
90
- reject(new Error("No image selected"));
105
+ resolve({ status: "cancelled" });
91
106
  }
92
107
  },
93
108
  );
94
109
  });
95
110
  } catch (error) {
96
- throw new Error(
97
- `Failed to pick image: ${error instanceof Error ? error.message : String(error)}`,
98
- );
111
+ return {
112
+ status: "error",
113
+ error:
114
+ error instanceof Error
115
+ ? error
116
+ : new Error(
117
+ `Failed to pick image: ${error instanceof Error ? error.message : String(error)}`,
118
+ ),
119
+ };
99
120
  }
100
121
  }
101
122
 
102
123
  async pickVideo(options?: PickerOptions): Promise<FilePickResult> {
103
124
  try {
104
- return new Promise((resolve, reject) => {
125
+ return new Promise((resolve) => {
105
126
  ImagePicker.launchImageLibrary(
106
127
  {
107
128
  mediaType: "video",
@@ -120,37 +141,49 @@ export class NativeFileSystemProvider implements FileSystemProvider {
120
141
  };
121
142
 
122
143
  if (res.didCancel) {
123
- reject(new Error("Video picker was cancelled"));
144
+ resolve({ status: "cancelled" });
124
145
  } else if (res.errorCode) {
125
- reject(new Error(`Video picker error: ${res.errorCode}`));
146
+ resolve({
147
+ status: "error",
148
+ error: new Error(`Video picker error: ${res.errorCode}`),
149
+ });
126
150
  } else if (res.assets && res.assets.length > 0) {
127
151
  const asset = res.assets[0];
128
152
  if (asset) {
129
153
  resolve({
130
- uri: asset.uri,
131
- name: asset.fileName || `video-${Date.now()}.mp4`,
132
- size: asset.fileSize || 0,
133
- mimeType: asset.type || "video/mp4",
154
+ status: "success",
155
+ data: {
156
+ uri: asset.uri,
157
+ name: asset.fileName || `video-${Date.now()}.mp4`,
158
+ size: asset.fileSize || 0,
159
+ mimeType: asset.type || "video/mp4",
160
+ },
134
161
  });
135
162
  } else {
136
- reject(new Error("No video selected"));
163
+ resolve({ status: "cancelled" });
137
164
  }
138
165
  } else {
139
- reject(new Error("No video selected"));
166
+ resolve({ status: "cancelled" });
140
167
  }
141
168
  },
142
169
  );
143
170
  });
144
171
  } catch (error) {
145
- throw new Error(
146
- `Failed to pick video: ${error instanceof Error ? error.message : String(error)}`,
147
- );
172
+ return {
173
+ status: "error",
174
+ error:
175
+ error instanceof Error
176
+ ? error
177
+ : new Error(
178
+ `Failed to pick video: ${error instanceof Error ? error.message : String(error)}`,
179
+ ),
180
+ };
148
181
  }
149
182
  }
150
183
 
151
184
  async pickCamera(options?: CameraOptions): Promise<FilePickResult> {
152
185
  try {
153
- return new Promise((resolve, reject) => {
186
+ return new Promise((resolve) => {
154
187
  ImagePicker.launchCamera(
155
188
  {
156
189
  mediaType: "photo",
@@ -171,31 +204,43 @@ export class NativeFileSystemProvider implements FileSystemProvider {
171
204
  };
172
205
 
173
206
  if (res.didCancel) {
174
- reject(new Error("Camera was cancelled"));
207
+ resolve({ status: "cancelled" });
175
208
  } else if (res.errorCode) {
176
- reject(new Error(`Camera error: ${res.errorCode}`));
209
+ resolve({
210
+ status: "error",
211
+ error: new Error(`Camera error: ${res.errorCode}`),
212
+ });
177
213
  } else if (res.assets && res.assets.length > 0) {
178
214
  const asset = res.assets[0];
179
215
  if (asset) {
180
216
  resolve({
181
- uri: asset.uri,
182
- name: asset.fileName || `photo-${Date.now()}.jpg`,
183
- size: asset.fileSize || 0,
184
- mimeType: asset.type || "image/jpeg",
217
+ status: "success",
218
+ data: {
219
+ uri: asset.uri,
220
+ name: asset.fileName || `photo-${Date.now()}.jpg`,
221
+ size: asset.fileSize || 0,
222
+ mimeType: asset.type || "image/jpeg",
223
+ },
185
224
  });
186
225
  } else {
187
- reject(new Error("No photo captured"));
226
+ resolve({ status: "cancelled" });
188
227
  }
189
228
  } else {
190
- reject(new Error("No photo captured"));
229
+ resolve({ status: "cancelled" });
191
230
  }
192
231
  },
193
232
  );
194
233
  });
195
234
  } catch (error) {
196
- throw new Error(
197
- `Failed to capture photo: ${error instanceof Error ? error.message : String(error)}`,
198
- );
235
+ return {
236
+ status: "error",
237
+ error:
238
+ error instanceof Error
239
+ ? error
240
+ : new Error(
241
+ `Failed to capture photo: ${error instanceof Error ? error.message : String(error)}`,
242
+ ),
243
+ };
199
244
  }
200
245
  }
201
246
 
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../src/services/native-file-system-provider.ts"],"sourcesContent":[],"mappings":";;;;;;AAeA;;AACuD,cAD1C,wBAAA,YAAoC,kBACM,CAAA;EAAR,YAAA,CAAA,OAAA,CAAA,EAAhB,aAAgB,CAAA,EAAA,OAAA,CAAQ,cAAR,CAAA;EAkCnB,SAAA,CAAA,OAAA,CAAA,EAAA,aAAA,CAAA,EAAgB,OAAhB,CAAwB,cAAxB,CAAA;EAAwB,SAAA,CAAA,OAAA,CAAA,EAmDxB,aAnDwB,CAAA,EAmDR,OAnDQ,CAmDA,cAnDA,CAAA;EAAR,UAAA,CAAA,OAAA,CAAA,EAoGf,aApGe,CAAA,EAoGC,OApGD,CAoGS,cApGT,CAAA;EAmDhB,QAAA,CAAA,GAAA,EAAA,MAAA,CAAA,EAoGG,OApGH,CAoGW,WApGX,CAAA;EAAwB,cAAA,CAAA,QAAA,EAAA,MAAA,CAAA,EAuHV,OAvHU,CAAA,MAAA,CAAA;EAAR,WAAA,CAAA,GAAA,EAAA,MAAA,CAAA,EA4HV,OA5HU,CA4HF,QA5HE,CAAA"}
package/dist/index.js DELETED
@@ -1,2 +0,0 @@
1
- import*as e from"@react-native-documents/picker";import*as t from"react-native-image-picker";import n from"rn-fetch-blob";var r=class{async pickDocument(t){try{let n=await e.pick({type:t?.allowedTypes||[e.types.allFiles],...t?.allowMultiple&&{isMultiple:!0}}),r=Array.isArray(n)?n[0]:n;if(!r)throw Error(`No document selected`);return{uri:r.uri,name:r.name||`document`,size:r.size||0,mimeType:r.type||void 0,localPath:r.uri||void 0}}catch(e){throw e instanceof Error&&(e.message.includes(`cancelled`)||e.message.includes(`Cancelled`))?e:Error(`Failed to pick document: ${e instanceof Error?e.message:String(e)}`)}}async pickImage(e){try{return new Promise((n,r)=>{t.launchImageLibrary({mediaType:`photo`,selectionLimit:e?.allowMultiple?0:1,quality:1},e=>{let t=e;if(t.didCancel)r(Error(`Image picker was cancelled`));else if(t.errorCode)r(Error(`Image picker error: ${t.errorCode}`));else if(t.assets&&t.assets.length>0){let e=t.assets[0];e?n({uri:e.uri,name:e.fileName||`image-${Date.now()}.jpg`,size:e.fileSize||0,mimeType:e.type||`image/jpeg`}):r(Error(`No image selected`))}else r(Error(`No image selected`))})})}catch(e){throw Error(`Failed to pick image: ${e instanceof Error?e.message:String(e)}`)}}async pickVideo(e){try{return new Promise((n,r)=>{t.launchImageLibrary({mediaType:`video`,selectionLimit:e?.allowMultiple?0:1},e=>{let t=e;if(t.didCancel)r(Error(`Video picker was cancelled`));else if(t.errorCode)r(Error(`Video picker error: ${t.errorCode}`));else if(t.assets&&t.assets.length>0){let e=t.assets[0];e?n({uri:e.uri,name:e.fileName||`video-${Date.now()}.mp4`,size:e.fileSize||0,mimeType:e.type||`video/mp4`}):r(Error(`No video selected`))}else r(Error(`No video selected`))})})}catch(e){throw Error(`Failed to pick video: ${e instanceof Error?e.message:String(e)}`)}}async pickCamera(e){try{return new Promise((n,r)=>{t.launchCamera({mediaType:`photo`,cameraType:e?.cameraType===`front`?`front`:`back`,quality:e?.quality??1},e=>{let t=e;if(t.didCancel)r(Error(`Camera was cancelled`));else if(t.errorCode)r(Error(`Camera error: ${t.errorCode}`));else if(t.assets&&t.assets.length>0){let e=t.assets[0];e?n({uri:e.uri,name:e.fileName||`photo-${Date.now()}.jpg`,size:e.fileSize||0,mimeType:e.type||`image/jpeg`}):r(Error(`No photo captured`))}else r(Error(`No photo captured`))})})}catch(e){throw Error(`Failed to capture photo: ${e instanceof Error?e.message:String(e)}`)}}async readFile(e){try{let t=await n.fs.readFile(e,`base64`),r=atob(t),i=new Uint8Array(r.length);for(let e=0;e<r.length;e++)i[e]=r.charCodeAt(e);return i.buffer}catch(e){throw Error(`Failed to read file: ${e instanceof Error?e.message:String(e)}`)}}async getDocumentUri(e){return e}async getFileInfo(e){try{let t=await n.fs.stat(e);return{uri:e,name:t.filename||e.split(`/`).pop()||`unknown`,size:t.size||0,modificationTime:t.lastModified?typeof t.lastModified==`string`?parseInt(t.lastModified,10):t.lastModified:void 0}}catch(e){throw Error(`Failed to get file info: ${e instanceof Error?e.message:String(e)}`)}}};export{r as NativeFileSystemProvider};
2
- //# sourceMappingURL=index.js.map
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/services/native-file-system-provider.ts"],"sourcesContent":["import * as DocumentPicker from \"@react-native-documents/picker\";\nimport type {\n CameraOptions,\n FileInfo,\n FilePickResult,\n FileSystemProvider,\n PickerOptions,\n} from \"@uploadista/react-native-core\";\nimport * as ImagePicker from \"react-native-image-picker\";\nimport RNFetchBlob from \"rn-fetch-blob\";\n\n/**\n * File system provider implementation for bare React Native environment\n * Uses react-native-image-picker, react-native-fs, and native APIs\n */\nexport class NativeFileSystemProvider implements FileSystemProvider {\n async pickDocument(options?: PickerOptions): Promise<FilePickResult> {\n try {\n const result = await DocumentPicker.pick({\n type: options?.allowedTypes || [DocumentPicker.types.allFiles],\n ...(options?.allowMultiple && { isMultiple: true }),\n });\n\n const file = Array.isArray(result) ? result[0] : result;\n\n if (!file) {\n throw new Error(\"No document selected\");\n }\n\n return {\n uri: file.uri,\n name: file.name || \"document\",\n size: file.size || 0,\n mimeType: file.type || undefined,\n localPath: file.uri || undefined,\n };\n } catch (error) {\n if (\n error instanceof Error &&\n (error.message.includes(\"cancelled\") ||\n error.message.includes(\"Cancelled\"))\n ) {\n throw error;\n }\n throw new Error(\n `Failed to pick document: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n async pickImage(options?: PickerOptions): Promise<FilePickResult> {\n try {\n return new Promise((resolve, reject) => {\n ImagePicker.launchImageLibrary(\n {\n mediaType: \"photo\",\n selectionLimit: options?.allowMultiple ? 0 : 1,\n quality: 1,\n // biome-ignore lint/suspicious/noExplicitAny: react-native-image-picker type mismatch\n } as any,\n (response: unknown) => {\n const res = response as {\n didCancel?: boolean;\n errorCode?: string;\n assets?: Array<{\n uri: string;\n fileName?: string;\n fileSize?: number;\n type?: string;\n }>;\n };\n\n if (res.didCancel) {\n reject(new Error(\"Image picker was cancelled\"));\n } else if (res.errorCode) {\n reject(new Error(`Image picker error: ${res.errorCode}`));\n } else if (res.assets && res.assets.length > 0) {\n const asset = res.assets[0];\n if (asset) {\n resolve({\n uri: asset.uri,\n name: asset.fileName || `image-${Date.now()}.jpg`,\n size: asset.fileSize || 0,\n mimeType: asset.type || \"image/jpeg\",\n });\n } else {\n reject(new Error(\"No image selected\"));\n }\n } else {\n reject(new Error(\"No image selected\"));\n }\n },\n );\n });\n } catch (error) {\n throw new Error(\n `Failed to pick image: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n async pickVideo(options?: PickerOptions): Promise<FilePickResult> {\n try {\n return new Promise((resolve, reject) => {\n ImagePicker.launchImageLibrary(\n {\n mediaType: \"video\",\n selectionLimit: options?.allowMultiple ? 0 : 1,\n },\n (response: unknown) => {\n const res = response as {\n didCancel?: boolean;\n errorCode?: string;\n assets?: Array<{\n uri: string;\n fileName?: string;\n fileSize?: number;\n type?: string;\n }>;\n };\n\n if (res.didCancel) {\n reject(new Error(\"Video picker was cancelled\"));\n } else if (res.errorCode) {\n reject(new Error(`Video picker error: ${res.errorCode}`));\n } else if (res.assets && res.assets.length > 0) {\n const asset = res.assets[0];\n if (asset) {\n resolve({\n uri: asset.uri,\n name: asset.fileName || `video-${Date.now()}.mp4`,\n size: asset.fileSize || 0,\n mimeType: asset.type || \"video/mp4\",\n });\n } else {\n reject(new Error(\"No video selected\"));\n }\n } else {\n reject(new Error(\"No video selected\"));\n }\n },\n );\n });\n } catch (error) {\n throw new Error(\n `Failed to pick video: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n async pickCamera(options?: CameraOptions): Promise<FilePickResult> {\n try {\n return new Promise((resolve, reject) => {\n ImagePicker.launchCamera(\n {\n mediaType: \"photo\",\n cameraType: options?.cameraType === \"front\" ? \"front\" : \"back\",\n quality: options?.quality ?? 1,\n // biome-ignore lint/suspicious/noExplicitAny: react-native-image-picker type mismatch\n } as any,\n (response: unknown) => {\n const res = response as {\n didCancel?: boolean;\n errorCode?: string;\n assets?: Array<{\n uri: string;\n fileName?: string;\n fileSize?: number;\n type?: string;\n }>;\n };\n\n if (res.didCancel) {\n reject(new Error(\"Camera was cancelled\"));\n } else if (res.errorCode) {\n reject(new Error(`Camera error: ${res.errorCode}`));\n } else if (res.assets && res.assets.length > 0) {\n const asset = res.assets[0];\n if (asset) {\n resolve({\n uri: asset.uri,\n name: asset.fileName || `photo-${Date.now()}.jpg`,\n size: asset.fileSize || 0,\n mimeType: asset.type || \"image/jpeg\",\n });\n } else {\n reject(new Error(\"No photo captured\"));\n }\n } else {\n reject(new Error(\"No photo captured\"));\n }\n },\n );\n });\n } catch (error) {\n throw new Error(\n `Failed to capture photo: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n async readFile(uri: string): Promise<ArrayBuffer> {\n try {\n // Read file as base64\n const base64Data = await RNFetchBlob.fs.readFile(uri, \"base64\");\n\n // Convert base64 to ArrayBuffer\n const binaryString = atob(base64Data);\n const bytes = new Uint8Array(binaryString.length);\n for (let i = 0; i < binaryString.length; i++) {\n bytes[i] = binaryString.charCodeAt(i);\n }\n return bytes.buffer;\n } catch (error) {\n throw new Error(\n `Failed to read file: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n async getDocumentUri(filePath: string): Promise<string> {\n // In bare RN with native modules, the path is typically already a URI\n return filePath;\n }\n\n async getFileInfo(uri: string): Promise<FileInfo> {\n try {\n const stat = await RNFetchBlob.fs.stat(uri);\n\n return {\n uri,\n name: stat.filename || uri.split(\"/\").pop() || \"unknown\",\n size: stat.size || 0,\n modificationTime: stat.lastModified\n ? typeof stat.lastModified === \"string\"\n ? parseInt(stat.lastModified, 10)\n : stat.lastModified\n : undefined,\n };\n } catch (error) {\n throw new Error(\n `Failed to get file info: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n}\n"],"mappings":"0HAeA,IAAa,EAAb,KAAoE,CAClE,MAAM,aAAa,EAAkD,CACnE,GAAI,CACF,IAAM,EAAS,MAAM,EAAe,KAAK,CACvC,KAAM,GAAS,cAAgB,CAAC,EAAe,MAAM,SAAS,CAC9D,GAAI,GAAS,eAAiB,CAAE,WAAY,GAAM,CACnD,CAAC,CAEI,EAAO,MAAM,QAAQ,EAAO,CAAG,EAAO,GAAK,EAEjD,GAAI,CAAC,EACH,MAAU,MAAM,uBAAuB,CAGzC,MAAO,CACL,IAAK,EAAK,IACV,KAAM,EAAK,MAAQ,WACnB,KAAM,EAAK,MAAQ,EACnB,SAAU,EAAK,MAAQ,IAAA,GACvB,UAAW,EAAK,KAAO,IAAA,GACxB,OACM,EAAO,CAQd,MANE,aAAiB,QAChB,EAAM,QAAQ,SAAS,YAAY,EAClC,EAAM,QAAQ,SAAS,YAAY,EAE/B,EAEE,MACR,4BAA4B,aAAiB,MAAQ,EAAM,QAAU,OAAO,EAAM,GACnF,EAIL,MAAM,UAAU,EAAkD,CAChE,GAAI,CACF,OAAO,IAAI,SAAS,EAAS,IAAW,CACtC,EAAY,mBACV,CACE,UAAW,QACX,eAAgB,GAAS,cAAgB,EAAI,EAC7C,QAAS,EAEV,CACA,GAAsB,CACrB,IAAM,EAAM,EAWZ,GAAI,EAAI,UACN,EAAW,MAAM,6BAA6B,CAAC,SACtC,EAAI,UACb,EAAW,MAAM,uBAAuB,EAAI,YAAY,CAAC,SAChD,EAAI,QAAU,EAAI,OAAO,OAAS,EAAG,CAC9C,IAAM,EAAQ,EAAI,OAAO,GACrB,EACF,EAAQ,CACN,IAAK,EAAM,IACX,KAAM,EAAM,UAAY,SAAS,KAAK,KAAK,CAAC,MAC5C,KAAM,EAAM,UAAY,EACxB,SAAU,EAAM,MAAQ,aACzB,CAAC,CAEF,EAAW,MAAM,oBAAoB,CAAC,MAGxC,EAAW,MAAM,oBAAoB,CAAC,EAG3C,EACD,OACK,EAAO,CACd,MAAU,MACR,yBAAyB,aAAiB,MAAQ,EAAM,QAAU,OAAO,EAAM,GAChF,EAIL,MAAM,UAAU,EAAkD,CAChE,GAAI,CACF,OAAO,IAAI,SAAS,EAAS,IAAW,CACtC,EAAY,mBACV,CACE,UAAW,QACX,eAAgB,GAAS,cAAgB,EAAI,EAC9C,CACA,GAAsB,CACrB,IAAM,EAAM,EAWZ,GAAI,EAAI,UACN,EAAW,MAAM,6BAA6B,CAAC,SACtC,EAAI,UACb,EAAW,MAAM,uBAAuB,EAAI,YAAY,CAAC,SAChD,EAAI,QAAU,EAAI,OAAO,OAAS,EAAG,CAC9C,IAAM,EAAQ,EAAI,OAAO,GACrB,EACF,EAAQ,CACN,IAAK,EAAM,IACX,KAAM,EAAM,UAAY,SAAS,KAAK,KAAK,CAAC,MAC5C,KAAM,EAAM,UAAY,EACxB,SAAU,EAAM,MAAQ,YACzB,CAAC,CAEF,EAAW,MAAM,oBAAoB,CAAC,MAGxC,EAAW,MAAM,oBAAoB,CAAC,EAG3C,EACD,OACK,EAAO,CACd,MAAU,MACR,yBAAyB,aAAiB,MAAQ,EAAM,QAAU,OAAO,EAAM,GAChF,EAIL,MAAM,WAAW,EAAkD,CACjE,GAAI,CACF,OAAO,IAAI,SAAS,EAAS,IAAW,CACtC,EAAY,aACV,CACE,UAAW,QACX,WAAY,GAAS,aAAe,QAAU,QAAU,OACxD,QAAS,GAAS,SAAW,EAE9B,CACA,GAAsB,CACrB,IAAM,EAAM,EAWZ,GAAI,EAAI,UACN,EAAW,MAAM,uBAAuB,CAAC,SAChC,EAAI,UACb,EAAW,MAAM,iBAAiB,EAAI,YAAY,CAAC,SAC1C,EAAI,QAAU,EAAI,OAAO,OAAS,EAAG,CAC9C,IAAM,EAAQ,EAAI,OAAO,GACrB,EACF,EAAQ,CACN,IAAK,EAAM,IACX,KAAM,EAAM,UAAY,SAAS,KAAK,KAAK,CAAC,MAC5C,KAAM,EAAM,UAAY,EACxB,SAAU,EAAM,MAAQ,aACzB,CAAC,CAEF,EAAW,MAAM,oBAAoB,CAAC,MAGxC,EAAW,MAAM,oBAAoB,CAAC,EAG3C,EACD,OACK,EAAO,CACd,MAAU,MACR,4BAA4B,aAAiB,MAAQ,EAAM,QAAU,OAAO,EAAM,GACnF,EAIL,MAAM,SAAS,EAAmC,CAChD,GAAI,CAEF,IAAM,EAAa,MAAM,EAAY,GAAG,SAAS,EAAK,SAAS,CAGzD,EAAe,KAAK,EAAW,CAC/B,EAAQ,IAAI,WAAW,EAAa,OAAO,CACjD,IAAK,IAAI,EAAI,EAAG,EAAI,EAAa,OAAQ,IACvC,EAAM,GAAK,EAAa,WAAW,EAAE,CAEvC,OAAO,EAAM,aACN,EAAO,CACd,MAAU,MACR,wBAAwB,aAAiB,MAAQ,EAAM,QAAU,OAAO,EAAM,GAC/E,EAIL,MAAM,eAAe,EAAmC,CAEtD,OAAO,EAGT,MAAM,YAAY,EAAgC,CAChD,GAAI,CACF,IAAM,EAAO,MAAM,EAAY,GAAG,KAAK,EAAI,CAE3C,MAAO,CACL,MACA,KAAM,EAAK,UAAY,EAAI,MAAM,IAAI,CAAC,KAAK,EAAI,UAC/C,KAAM,EAAK,MAAQ,EACnB,iBAAkB,EAAK,aACnB,OAAO,EAAK,cAAiB,SAC3B,SAAS,EAAK,aAAc,GAAG,CAC/B,EAAK,aACP,IAAA,GACL,OACM,EAAO,CACd,MAAU,MACR,4BAA4B,aAAiB,MAAQ,EAAM,QAAU,OAAO,EAAM,GACnF"}