react-native-cloud-storage 1.4.1 → 1.5.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.
Files changed (103) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +7 -6
  3. package/ios/CloudStorage.swift +52 -262
  4. package/ios/CloudStorage.xcodeproj/project.pbxproj +28 -0
  5. package/ios/CloudStorageEventEmitter.m +1 -1
  6. package/ios/CloudStorageEventEmitter.swift +4 -4
  7. package/ios/Utils/CloudKitUtils.swift +112 -0
  8. package/ios/Utils/CloudStorageError.swift +78 -0
  9. package/ios/Utils/FileUtils.swift +132 -0
  10. package/ios/Utils/Promise.swift +58 -0
  11. package/ios/Utils/Types.swift +36 -0
  12. package/lib/commonjs/RNCloudStorage.js +361 -66
  13. package/lib/commonjs/RNCloudStorage.js.map +1 -1
  14. package/lib/commonjs/expo-plugin/types/index.js.map +1 -1
  15. package/lib/commonjs/expo-plugin/withRNCloudStorage.js +2 -3
  16. package/lib/commonjs/expo-plugin/withRNCloudStorage.js.map +1 -1
  17. package/lib/commonjs/expo-plugin/withRNCloudStorageIos.js +4 -7
  18. package/lib/commonjs/expo-plugin/withRNCloudStorageIos.js.map +1 -1
  19. package/lib/commonjs/google-drive/client.js +16 -20
  20. package/lib/commonjs/google-drive/client.js.map +1 -1
  21. package/lib/commonjs/google-drive/index.js +42 -64
  22. package/lib/commonjs/google-drive/index.js.map +1 -1
  23. package/lib/commonjs/google-drive/types.js +1 -2
  24. package/lib/commonjs/google-drive/types.js.map +1 -1
  25. package/lib/commonjs/hooks/useCloudFile.js +14 -17
  26. package/lib/commonjs/hooks/useCloudFile.js.map +1 -1
  27. package/lib/commonjs/hooks/useIsCloudAvailable.js +11 -21
  28. package/lib/commonjs/hooks/useIsCloudAvailable.js.map +1 -1
  29. package/lib/commonjs/index.js +1 -7
  30. package/lib/commonjs/index.js.map +1 -1
  31. package/lib/commonjs/package.json +1 -0
  32. package/lib/commonjs/types/main.js +8 -3
  33. package/lib/commonjs/types/main.js.map +1 -1
  34. package/lib/commonjs/types/native.js +3 -3
  35. package/lib/commonjs/types/native.js.map +1 -1
  36. package/lib/commonjs/utils/CloudStorageError.js +1 -2
  37. package/lib/commonjs/utils/CloudStorageError.js.map +1 -1
  38. package/lib/commonjs/utils/helpers.js +8 -15
  39. package/lib/commonjs/utils/helpers.js.map +1 -1
  40. package/lib/module/RNCloudStorage.js +362 -65
  41. package/lib/module/RNCloudStorage.js.map +1 -1
  42. package/lib/module/expo-plugin/types/index.js +1 -1
  43. package/lib/module/expo-plugin/types/index.js.map +1 -1
  44. package/lib/module/expo-plugin/withRNCloudStorage.js +2 -0
  45. package/lib/module/expo-plugin/withRNCloudStorage.js.map +1 -1
  46. package/lib/module/expo-plugin/withRNCloudStorageIos.js +5 -5
  47. package/lib/module/expo-plugin/withRNCloudStorageIos.js.map +1 -1
  48. package/lib/module/google-drive/client.js +18 -20
  49. package/lib/module/google-drive/client.js.map +1 -1
  50. package/lib/module/google-drive/index.js +41 -62
  51. package/lib/module/google-drive/index.js.map +1 -1
  52. package/lib/module/google-drive/types.js +2 -0
  53. package/lib/module/google-drive/types.js.map +1 -1
  54. package/lib/module/hooks/useCloudFile.js +15 -16
  55. package/lib/module/hooks/useCloudFile.js.map +1 -1
  56. package/lib/module/hooks/useIsCloudAvailable.js +13 -21
  57. package/lib/module/hooks/useIsCloudAvailable.js.map +1 -1
  58. package/lib/module/index.js +2 -5
  59. package/lib/module/index.js.map +1 -1
  60. package/lib/module/package.json +1 -0
  61. package/lib/module/types/main.js +9 -0
  62. package/lib/module/types/main.js.map +1 -1
  63. package/lib/module/types/native.js +4 -1
  64. package/lib/module/types/native.js.map +1 -1
  65. package/lib/module/utils/CloudStorageError.js +2 -0
  66. package/lib/module/utils/CloudStorageError.js.map +1 -1
  67. package/lib/module/utils/helpers.js +8 -13
  68. package/lib/module/utils/helpers.js.map +1 -1
  69. package/lib/typescript/RNCloudStorage.d.ts +159 -39
  70. package/lib/typescript/RNCloudStorage.d.ts.map +1 -1
  71. package/lib/typescript/google-drive/client.d.ts +3 -3
  72. package/lib/typescript/google-drive/client.d.ts.map +1 -1
  73. package/lib/typescript/google-drive/index.d.ts +6 -18
  74. package/lib/typescript/google-drive/index.d.ts.map +1 -1
  75. package/lib/typescript/hooks/useCloudFile.d.ts +4 -7
  76. package/lib/typescript/hooks/useCloudFile.d.ts.map +1 -1
  77. package/lib/typescript/hooks/useIsCloudAvailable.d.ts +3 -2
  78. package/lib/typescript/hooks/useIsCloudAvailable.d.ts.map +1 -1
  79. package/lib/typescript/index.d.ts +0 -4
  80. package/lib/typescript/index.d.ts.map +1 -1
  81. package/lib/typescript/types/main.d.ts +33 -0
  82. package/lib/typescript/types/main.d.ts.map +1 -1
  83. package/lib/typescript/types/native.d.ts +2 -1
  84. package/lib/typescript/types/native.d.ts.map +1 -1
  85. package/lib/typescript/utils/helpers.d.ts +2 -9
  86. package/lib/typescript/utils/helpers.d.ts.map +1 -1
  87. package/package.json +9 -11
  88. package/src/RNCloudStorage.ts +387 -68
  89. package/src/google-drive/client.ts +8 -7
  90. package/src/google-drive/index.ts +38 -63
  91. package/src/hooks/useCloudFile.ts +13 -16
  92. package/src/hooks/useIsCloudAvailable.ts +12 -25
  93. package/src/index.ts +0 -5
  94. package/src/types/main.ts +38 -0
  95. package/src/types/native.ts +2 -1
  96. package/src/utils/helpers.ts +8 -15
  97. package/lib/commonjs/createRNCloudStorage.js +0 -48
  98. package/lib/commonjs/createRNCloudStorage.js.map +0 -1
  99. package/lib/module/createRNCloudStorage.js +0 -41
  100. package/lib/module/createRNCloudStorage.js.map +0 -1
  101. package/lib/typescript/createRNCloudStorage.d.ts +0 -3
  102. package/lib/typescript/createRNCloudStorage.d.ts.map +0 -1
  103. package/src/createRNCloudStorage.ts +0 -53
@@ -1,4 +1,4 @@
1
- import type NativeRNCloudStorage from '../types/native';
1
+ import type NativeproviderService from '../types/native';
2
2
  import {
3
3
  CloudStorageErrorCode,
4
4
  type NativeRNCloudCloudStorageFileStat,
@@ -6,28 +6,30 @@ import {
6
6
  } from '../types/native';
7
7
  import CloudStorageError from '../utils/CloudStorageError';
8
8
  import { MimeTypes, type GoogleDriveFile, type GoogleDriveFileSpace } from './types';
9
- import { DeviceEventEmitter } from 'react-native';
10
9
  import GoogleDriveApiClient, { GoogleDriveHttpError } from './client';
10
+ import { type CloudStorageProviderOptions, type DeepRequired } from '../types/main';
11
11
 
12
12
  /**
13
13
  * A proxy class that wraps the Google Drive API client implementation to match the native iOS interface.
14
14
  */
15
- export default class GoogleDrive implements NativeRNCloudStorage {
16
- private static drive: GoogleDriveApiClient = new GoogleDriveApiClient();
17
- public static throwOnFilesWithSameName = false;
18
- public filesWithSameNameSubscribers: (({ path, fileIds }: { path: string; fileIds: string[] }) => void)[];
15
+ export default class GoogleDrive implements NativeproviderService {
16
+ private drive: GoogleDriveApiClient;
17
+ private options: DeepRequired<CloudStorageProviderOptions['googledrive']>;
18
+
19
+ constructor(options: DeepRequired<CloudStorageProviderOptions['googledrive']>) {
20
+ this.options = options;
21
+ this.drive = new GoogleDriveApiClient(options);
19
22
 
20
- constructor() {
21
- this.filesWithSameNameSubscribers = [];
22
23
  return new Proxy(this, {
23
24
  // before calling any function, check if the access token is set
24
25
  get(target: GoogleDrive, prop: keyof GoogleDrive) {
25
- const allowedFunctions = ['isCloudAvailable', 'subscribeToFilesWithSameName'];
26
+ const allowedFunctions = ['isCloudAvailable'];
26
27
  if (typeof target[prop] === 'function' && !allowedFunctions.includes(prop.toString())) {
27
- if (!GoogleDrive.drive.accessToken.length) {
28
+ const { accessToken } = options;
29
+ if (!accessToken?.length) {
28
30
  throw new CloudStorageError(
29
31
  `Google Drive access token is not set, cannot call function ${prop.toString()}`,
30
- CloudStorageErrorCode.GOOGLE_DRIVE_ACCESS_TOKEN_MISSING
32
+ CloudStorageErrorCode.ACCESS_TOKEN_MISSING
31
33
  );
32
34
  }
33
35
  }
@@ -37,37 +39,10 @@ export default class GoogleDrive implements NativeRNCloudStorage {
37
39
  });
38
40
  }
39
41
 
40
- // when setting accessToken, set it on the GDrive instance
41
- public static set accessToken(accessToken: string | null) {
42
- GoogleDrive.drive.accessToken = accessToken ?? '';
43
-
44
- // emit an event for the useIsCloudAvailable hook
45
- DeviceEventEmitter.emit('RNCloudStorage.cloud.availability-changed', {
46
- available: !!accessToken?.length,
47
- });
48
- }
49
-
50
- public static set timeout(timeout: number) {
51
- GoogleDrive.drive.timeout = timeout;
52
- }
53
-
54
- public static get accessToken(): string | null {
55
- return GoogleDrive.drive.accessToken.length ? GoogleDrive.drive.accessToken : null;
56
- }
57
-
58
- public subscribeToFilesWithSameName(subscriber: ({ path, fileIds }: { path: string; fileIds: string[] }) => void): {
59
- remove: () => void;
60
- } {
61
- this.filesWithSameNameSubscribers.push(subscriber);
62
-
63
- return {
64
- remove: () => {
65
- this.filesWithSameNameSubscribers = this.filesWithSameNameSubscribers.filter((s) => s !== subscriber);
66
- },
67
- };
68
- }
69
-
70
- public isCloudAvailable: () => Promise<boolean> = async () => !!GoogleDrive.drive.accessToken.length;
42
+ public isCloudAvailable: () => Promise<boolean> = async () => {
43
+ const { accessToken } = this.options;
44
+ return !!accessToken?.length;
45
+ };
71
46
 
72
47
  private getRootDirectory(scope: NativeRNCloudCloudStorageScope): GoogleDriveFileSpace {
73
48
  switch (scope) {
@@ -141,7 +116,7 @@ export default class GoogleDrive implements NativeRNCloudStorage {
141
116
  * @returns A promise that resolves to the ID of the root directory or null if it could not be found.
142
117
  */
143
118
  private async getRootDirectoryId(scope: NativeRNCloudCloudStorageScope): Promise<string | null> {
144
- const files = await GoogleDrive.drive.listFiles(this.getRootDirectory(scope));
119
+ const files = await this.drive.listFiles(this.getRootDirectory(scope));
145
120
  for (const file of files) {
146
121
  if (!files.find((f) => f.id === file.parents![0])) return file.parents![0] ?? null;
147
122
  }
@@ -155,6 +130,8 @@ export default class GoogleDrive implements NativeRNCloudStorage {
155
130
  filename: string,
156
131
  parentDirectoryId: string | null
157
132
  ) {
133
+ const { strictFilenames } = this.options;
134
+
158
135
  let possibleFiles: GoogleDriveFile[];
159
136
  if (parentDirectoryId) {
160
137
  possibleFiles = files.filter((f) => f.name === filename && f.parents![0] === parentDirectoryId);
@@ -164,13 +141,11 @@ export default class GoogleDrive implements NativeRNCloudStorage {
164
141
 
165
142
  if (possibleFiles.length <= 1) return;
166
143
 
167
- if (GoogleDrive.throwOnFilesWithSameName) {
144
+ if (strictFilenames) {
168
145
  throw new CloudStorageError(
169
146
  `Multiple files with the same name found at path ${path}: ${possibleFiles.map((f) => f.id).join(', ')}`,
170
147
  CloudStorageErrorCode.MULTIPLE_FILES_SAME_NAME
171
148
  );
172
- } else {
173
- this.filesWithSameNameSubscribers.forEach((s) => s({ path, fileIds: possibleFiles.map((f) => f.id) }));
174
149
  }
175
150
  }
176
151
 
@@ -180,7 +155,7 @@ export default class GoogleDrive implements NativeRNCloudStorage {
180
155
  throwIf: 'directory' | 'file' | false = false
181
156
  ): Promise<string> {
182
157
  try {
183
- const files = await GoogleDrive.drive.listFiles(this.getRootDirectory(scope));
158
+ const files = await this.drive.listFiles(this.getRootDirectory(scope));
184
159
 
185
160
  if (path === '' || path === '/') {
186
161
  const rootDirectoryId = await this.getRootDirectoryId(scope);
@@ -240,7 +215,7 @@ export default class GoogleDrive implements NativeRNCloudStorage {
240
215
  let prevContent = '';
241
216
  try {
242
217
  fileId = await this.getFileId(path, scope);
243
- prevContent = await GoogleDrive.drive.getFileText(fileId);
218
+ prevContent = await this.drive.getFileText(fileId);
244
219
  } catch (e: any) {
245
220
  if (e instanceof CloudStorageError && e.code === CloudStorageErrorCode.FILE_NOT_FOUND) {
246
221
  /* do nothing, simply create the file */
@@ -250,15 +225,15 @@ export default class GoogleDrive implements NativeRNCloudStorage {
250
225
  }
251
226
 
252
227
  if (fileId) {
253
- await GoogleDrive.drive.updateFile(fileId, {
228
+ await this.drive.updateFile(fileId, {
254
229
  body: prevContent + data,
255
230
  mimeType: MimeTypes.TEXT,
256
231
  });
257
232
  } else {
258
- const files = await GoogleDrive.drive.listFiles(this.getRootDirectory(scope));
233
+ const files = await this.drive.listFiles(this.getRootDirectory(scope));
259
234
  const { directories, filename } = this.resolvePathToDirectories(path);
260
235
  const parentDirectoryId = this.findParentDirectoryId(files, directories);
261
- await GoogleDrive.drive.createFile(
236
+ await this.drive.createFile(
262
237
  {
263
238
  name: filename,
264
239
  parents: parentDirectoryId
@@ -306,15 +281,15 @@ export default class GoogleDrive implements NativeRNCloudStorage {
306
281
  }
307
282
 
308
283
  if (fileId) {
309
- await GoogleDrive.drive.updateFile(fileId, {
284
+ await this.drive.updateFile(fileId, {
310
285
  body: data,
311
286
  mimeType: MimeTypes.TEXT,
312
287
  });
313
288
  } else {
314
- const files = await GoogleDrive.drive.listFiles(this.getRootDirectory(scope));
289
+ const files = await this.drive.listFiles(this.getRootDirectory(scope));
315
290
  const { directories, filename } = this.resolvePathToDirectories(path);
316
291
  const parentDirectoryId = this.findParentDirectoryId(files, directories);
317
- await GoogleDrive.drive.createFile(
292
+ await this.drive.createFile(
318
293
  {
319
294
  name: filename,
320
295
  parents: parentDirectoryId
@@ -332,7 +307,7 @@ export default class GoogleDrive implements NativeRNCloudStorage {
332
307
  }
333
308
 
334
309
  async listFiles(path: string, scope: NativeRNCloudCloudStorageScope): Promise<string[]> {
335
- const allFiles = await GoogleDrive.drive.listFiles(this.getRootDirectory(scope));
310
+ const allFiles = await this.drive.listFiles(this.getRootDirectory(scope));
336
311
  if (path !== '') {
337
312
  const fileId = await this.getFileId(path, scope);
338
313
  const files = allFiles.filter((f) => (f.parents ?? [])[0] === fileId);
@@ -358,11 +333,11 @@ export default class GoogleDrive implements NativeRNCloudStorage {
358
333
  }
359
334
  }
360
335
 
361
- const files = await GoogleDrive.drive.listFiles(this.getRootDirectory(scope));
336
+ const files = await this.drive.listFiles(this.getRootDirectory(scope));
362
337
  const { directories, filename } = this.resolvePathToDirectories(path);
363
338
  const parentDirectoryId = this.findParentDirectoryId(files, directories);
364
339
 
365
- await GoogleDrive.drive.createDirectory({
340
+ await this.drive.createDirectory({
366
341
  name: filename,
367
342
  parents: parentDirectoryId
368
343
  ? [parentDirectoryId]
@@ -374,19 +349,19 @@ export default class GoogleDrive implements NativeRNCloudStorage {
374
349
 
375
350
  async readFile(path: string, scope: NativeRNCloudCloudStorageScope): Promise<string> {
376
351
  const fileId = await this.getFileId(path, scope);
377
- const content = await GoogleDrive.drive.getFileText(fileId);
352
+ const content = await this.drive.getFileText(fileId);
378
353
  return content;
379
354
  }
380
355
 
381
356
  async downloadFile(_path: string, _scope: NativeRNCloudCloudStorageScope): Promise<void> {
382
- // Not doing anything here, just a placeholder to conform to the interface so it doesn't fail on Android
357
+ // Downloading files from Google Drive is not necessary / possible, as they need to be downloaded on every read operation via the API anyway
383
358
  return;
384
359
  }
385
360
 
386
361
  async deleteFile(path: string, scope: NativeRNCloudCloudStorageScope): Promise<void> {
387
362
  // if trying to pass a directory, throw an error
388
363
  const fileId = await this.getFileId(path, scope, 'directory');
389
- await GoogleDrive.drive.deleteFile(fileId);
364
+ await this.drive.deleteFile(fileId);
390
365
  }
391
366
 
392
367
  async deleteDirectory(path: string, recursive: boolean, scope: NativeRNCloudCloudStorageScope): Promise<void> {
@@ -395,7 +370,7 @@ export default class GoogleDrive implements NativeRNCloudStorage {
395
370
 
396
371
  if (!recursive) {
397
372
  // check if the directory is empty
398
- const files = await GoogleDrive.drive.listFiles(this.getRootDirectory(scope));
373
+ const files = await this.drive.listFiles(this.getRootDirectory(scope));
399
374
  const filesInDirectory = files.filter((f) => (f.parents ?? [])[0] === fileId);
400
375
  if (filesInDirectory.length > 0) {
401
376
  throw new CloudStorageError(
@@ -406,12 +381,12 @@ export default class GoogleDrive implements NativeRNCloudStorage {
406
381
  }
407
382
  }
408
383
 
409
- await GoogleDrive.drive.deleteFile(fileId);
384
+ await this.drive.deleteFile(fileId);
410
385
  }
411
386
 
412
387
  async statFile(path: string, scope: NativeRNCloudCloudStorageScope): Promise<NativeRNCloudCloudStorageFileStat> {
413
388
  const fileId = await this.getFileId(path, scope, false);
414
- const file = await GoogleDrive.drive.getFile(fileId!);
389
+ const file = await this.drive.getFile(fileId!);
415
390
 
416
391
  return {
417
392
  size: file.size ?? 0,
@@ -5,20 +5,22 @@ import { useCallback, useEffect, useState } from 'react';
5
5
  /**
6
6
  * A utility hook for reading and writing to a single file in the cloud.
7
7
  * @param path The path to the file.
8
- * @param scope The directory scope the path is in. If not provided, defaults to the default scope set in the library.
8
+ * @param scope The directory scope the path is in. Defaults to the default scope set for the current provider.
9
+ * @param cloudStorageInstance An optional instance of RNCloudStorage to use instead of the default instance.
9
10
  * @returns An object containing the file's contents and functions for downloading, reading, writing, and removing the file.
10
11
  */
11
- export const useCloudFile = (path: string, scope?: CloudStorageScope) => {
12
+ export const useCloudFile = (path: string, scope?: CloudStorageScope, cloudStorageInstance?: RNCloudStorage) => {
12
13
  const [content, setContent] = useState<string | null>(null);
14
+ const instance = cloudStorageInstance ?? RNCloudStorage;
13
15
 
14
16
  const read = useCallback(async () => {
15
- const exists = await RNCloudStorage.exists(path, scope);
17
+ const exists = await instance.exists(path, scope);
16
18
  if (!exists) {
17
19
  setContent(null);
18
20
  return;
19
21
  }
20
- RNCloudStorage.readFile(path, scope).then(setContent);
21
- }, [path, scope]);
22
+ instance.readFile(path, scope).then(setContent);
23
+ }, [path, scope, instance]);
22
24
 
23
25
  useEffect(() => {
24
26
  read();
@@ -26,31 +28,26 @@ export const useCloudFile = (path: string, scope?: CloudStorageScope) => {
26
28
 
27
29
  const write = useCallback(
28
30
  async (newContent: string) => {
29
- await RNCloudStorage.writeFile(path, newContent, scope);
31
+ await instance.writeFile(path, newContent, scope);
30
32
  read();
31
33
  },
32
- [path, scope, read]
34
+ [path, scope, read, instance]
33
35
  );
34
36
 
35
37
  const remove = useCallback(async () => {
36
- await RNCloudStorage.unlink(path, scope);
38
+ await instance.unlink(path, scope);
37
39
  setContent(null);
38
- }, [path, scope]);
40
+ }, [path, scope, instance]);
39
41
 
40
42
  const download = useCallback(async () => {
41
- await RNCloudStorage.downloadFile(path, scope);
42
- }, [path, scope]);
43
+ await instance.downloadFile(path, scope);
44
+ }, [path, scope, instance]);
43
45
 
44
46
  return {
45
47
  content,
46
48
  read,
47
49
  write,
48
50
  remove,
49
- /**
50
- * @deprecated Use `write` instead.
51
- * @alias write
52
- */
53
- update: write,
54
51
  /**
55
52
  * Downloads the file from iCloud to the device. Needed if the file hasn't been synced yet. Has no effect on
56
53
  * Google Drive.
@@ -1,43 +1,30 @@
1
- import { useEffect, useState } from 'react';
2
- import { NativeEventEmitter, NativeModules, Platform, DeviceEventEmitter } from 'react-native';
1
+ import { useCallback, useEffect, useState } from 'react';
3
2
  import RNCloudStorage from '../RNCloudStorage';
4
3
 
5
4
  /**
6
5
  * A hook that tests whether or not the cloud storage is available.
7
- * @param _iCloudTimeout DEPRECATED: This parameter is deprecated and has no effect. It will be removed in a future version.
6
+ * @param cloudStorageInstance - An optional instance of RNCloudStorage to use instead of the default instance.
8
7
  * @returns A boolean indicating whether or not the cloud storage is available.
9
8
  */
10
- export const useIsCloudAvailable = (_iCloudTimeout?: number) => {
9
+ export const useIsCloudAvailable = (cloudStorageInstance?: RNCloudStorage) => {
11
10
  const [isAvailable, setIsAvailable] = useState(false);
11
+ const instance = cloudStorageInstance ?? RNCloudStorage.getDefaultInstance();
12
+
13
+ const handleAvailabilityChange = useCallback((available: boolean) => {
14
+ setIsAvailable(available);
15
+ }, []);
12
16
 
13
17
  useEffect(() => {
14
18
  // Set the initial availability state
15
- RNCloudStorage.isCloudAvailable().then(setIsAvailable);
19
+ instance.isCloudAvailable().then(setIsAvailable);
16
20
 
17
21
  // Listen for changes to the cloud availability using the native event emitter
18
- let eventEmitter: NativeEventEmitter | typeof DeviceEventEmitter;
19
- if (Platform.OS === 'ios') {
20
- eventEmitter = new NativeEventEmitter(NativeModules.CloudStorageEventEmitter);
21
- } else {
22
- eventEmitter = DeviceEventEmitter;
23
- }
24
-
25
- eventEmitter.addListener('RNCloudStorage.cloud.availability-changed', (event: { available: boolean }) => {
26
- setIsAvailable(event.available);
27
- });
22
+ instance.subscribeToCloudAvailability(handleAvailabilityChange);
28
23
 
29
24
  return () => {
30
- eventEmitter.removeAllListeners('RNCloudStorage.cloud.availability-changed');
25
+ instance.unsubscribeFromCloudAvailability(handleAvailabilityChange);
31
26
  };
32
- }, []);
33
-
34
- useEffect(() => {
35
- if (_iCloudTimeout !== undefined) {
36
- console.warn(
37
- 'The iCloudTimeout parameter for useIsCloudFile is deprecated and has no effect. It will be removed in a future version. Please remove it from your code.'
38
- );
39
- }
40
- }, [_iCloudTimeout]);
27
+ }, [instance, handleAvailabilityChange]);
41
28
 
42
29
  return isAvailable;
43
30
  };
package/src/index.ts CHANGED
@@ -6,8 +6,3 @@ export * from './hooks/useIsCloudAvailable';
6
6
  import CloudStorageError from './utils/CloudStorageError';
7
7
 
8
8
  export { RNCloudStorage as CloudStorage, CloudStorageError, CloudStorageErrorCode };
9
-
10
- /**
11
- * @deprecated Use the named export `CloudStorage` instead.
12
- */
13
- export default RNCloudStorage;
package/src/types/main.ts CHANGED
@@ -1,3 +1,8 @@
1
+ /* Custom utility type to make properties required, but still allow null if defined */
2
+ export type DeepRequired<T> = {
3
+ [P in keyof T]-?: T[P] extends object ? DeepRequired<T[P]> : T[P];
4
+ };
5
+
1
6
  export enum CloudStorageScope {
2
7
  Documents = 'documents',
3
8
  AppData = 'app_data',
@@ -12,3 +17,36 @@ export interface CloudStorageFileStat {
12
17
  isDirectory: () => boolean;
13
18
  isFile: () => boolean;
14
19
  }
20
+
21
+ export enum CloudStorageProvider {
22
+ ICloud = 'icloud',
23
+ GoogleDrive = 'googledrive',
24
+ }
25
+
26
+ export interface CloudStorageProviderOptions {
27
+ [CloudStorageProvider.ICloud]: {
28
+ /**
29
+ * The directory scope to use for iCloud operations. Defaults to 'app_data'.
30
+ */
31
+ scope?: CloudStorageScope;
32
+ };
33
+
34
+ [CloudStorageProvider.GoogleDrive]: {
35
+ /**
36
+ * The directory scope to use for Google Drive operations. Defaults to 'app_data'.
37
+ */
38
+ scope?: CloudStorageScope;
39
+ /**
40
+ * The access token to use for Google Drive operations.
41
+ */
42
+ accessToken?: string | null;
43
+ /**
44
+ * Whether or not to throw an error if multiple files with the same filename are found. Defaults to false.
45
+ */
46
+ strictFilenames?: boolean;
47
+ /**
48
+ * The timeout in milliseconds after which to cancel an API request. Defaults to 3000.
49
+ */
50
+ timeout?: number;
51
+ };
52
+ }
@@ -9,6 +9,7 @@ export interface NativeRNCloudCloudStorageFileStat {
9
9
  }
10
10
 
11
11
  export enum CloudStorageErrorCode {
12
+ INVALID_SCOPE = 'ERR_INVALID_SCOPE',
12
13
  FILE_NOT_FOUND = 'ERR_FILE_NOT_FOUND',
13
14
  PATH_IS_FILE = 'ERR_PATH_IS_FILE',
14
15
  PATH_IS_DIRECTORY = 'ERR_PATH_IS_DIRECTORY',
@@ -23,7 +24,7 @@ export enum CloudStorageErrorCode {
23
24
  STAT_ERROR = 'ERR_STAT_ERROR',
24
25
  UNKNOWN = 'ERR_UNKNOWN',
25
26
  FILE_NOT_DOWNLOADABLE = 'ERR_FILE_NOT_DOWNLOADABLE',
26
- GOOGLE_DRIVE_ACCESS_TOKEN_MISSING = 'ERR_GOOGLE_DRIVE_ACCESS_TOKEN_MISSING',
27
+ ACCESS_TOKEN_MISSING = 'ERR_ACCESS_TOKEN_MISSING',
27
28
  }
28
29
 
29
30
  export default interface NativeRNCloudStorage {
@@ -1,17 +1,10 @@
1
- /**
2
- * Checks if the path starts with a leading slash and adds one if it doesn't to maintain backwards compatibility.
3
- * Will log a warning to the console if it had to add a leading slash. Will throw an error in the future.
4
- *
5
- * @param path The path to check.
6
- * @returns The path with a leading slash, if it didn't have one already.
7
- * @private
8
- */
9
- export const verifyLeadingSlash = (path: string) => {
10
- if (!path.startsWith('/')) {
11
- console.warn(
12
- `[react-native-cloud-storage] Path "${path}" did not start with a leading slash. This is deprecated and will be an error in the future.`
13
- );
14
- return `/${path}`;
1
+ import { CloudStorageProvider } from '../types/main';
2
+ import { Platform } from 'react-native';
3
+
4
+ export const isProviderSupported = (provider: CloudStorageProvider): boolean => {
5
+ if (Platform.OS !== 'ios' && provider === CloudStorageProvider.ICloud) {
6
+ return false;
15
7
  }
16
- return path;
8
+
9
+ return true;
17
10
  };
@@ -1,48 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.default = createRNCloudStorage;
7
- var _reactNative = require("react-native");
8
- var _googleDrive = _interopRequireDefault(require("./google-drive"));
9
- var _native = require("./types/native");
10
- var _CloudStorageError = _interopRequireDefault(require("./utils/CloudStorageError"));
11
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
12
- const LINKING_ERROR = `The package 'react-native-cloud-storage' doesn't seem to be linked. Make sure: \n\n` + _reactNative.Platform.select({
13
- ios: "- You have run 'pod install'\n",
14
- default: ''
15
- }) + '- You rebuilt the app after installing the package\n' + '- You are not using Expo Go\n';
16
-
17
- // proxy NativeModules.CloudStorage to catch any errors thrown by the native module and wrap them in a CloudStorageError
18
- const nativeIosInstance = _reactNative.NativeModules.CloudStorage ? new Proxy(_reactNative.NativeModules.CloudStorage, {
19
- get(target, prop) {
20
- const originalFunction = target[prop];
21
- if (typeof originalFunction === 'function') {
22
- return async function () {
23
- try {
24
- // @ts-expect-error - we can't know the types of the functions and their arguments
25
- return await originalFunction(...arguments);
26
- } catch (error) {
27
- if (error !== null && error !== void 0 && error.code && Object.values(_native.CloudStorageErrorCode).includes(error.code)) {
28
- throw new _CloudStorageError.default((error === null || error === void 0 ? void 0 : error.message) || '', error.code);
29
- } else {
30
- throw new _CloudStorageError.default('Unknown error', _native.CloudStorageErrorCode.UNKNOWN, error);
31
- }
32
- }
33
- };
34
- }
35
- return originalFunction;
36
- }
37
- }) : null;
38
- function createRNCloudStorage() {
39
- if (_reactNative.Platform.OS === 'ios') {
40
- return nativeIosInstance ?? new Proxy({}, {
41
- get() {
42
- throw new Error(LINKING_ERROR);
43
- }
44
- });
45
- }
46
- return new _googleDrive.default();
47
- }
48
- //# sourceMappingURL=createRNCloudStorage.js.map
@@ -1 +0,0 @@
1
- {"version":3,"names":["_reactNative","require","_googleDrive","_interopRequireDefault","_native","_CloudStorageError","obj","__esModule","default","LINKING_ERROR","Platform","select","ios","nativeIosInstance","NativeModules","CloudStorage","Proxy","get","target","prop","originalFunction","arguments","error","code","Object","values","CloudStorageErrorCode","includes","CloudStorageError","message","UNKNOWN","createRNCloudStorage","OS","Error","GoogleDrive"],"sourceRoot":"../../src","sources":["createRNCloudStorage.ts"],"mappings":";;;;;;AAAA,IAAAA,YAAA,GAAAC,OAAA;AAEA,IAAAC,YAAA,GAAAC,sBAAA,CAAAF,OAAA;AACA,IAAAG,OAAA,GAAAH,OAAA;AACA,IAAAI,kBAAA,GAAAF,sBAAA,CAAAF,OAAA;AAA0D,SAAAE,uBAAAG,GAAA,WAAAA,GAAA,IAAAA,GAAA,CAAAC,UAAA,GAAAD,GAAA,KAAAE,OAAA,EAAAF,GAAA;AAE1D,MAAMG,aAAa,GAChB,qFAAoF,GACrFC,qBAAQ,CAACC,MAAM,CAAC;EAAEC,GAAG,EAAE,gCAAgC;EAAEJ,OAAO,EAAE;AAAG,CAAC,CAAC,GACvE,sDAAsD,GACtD,+BAA+B;;AAEjC;AACA,MAAMK,iBAAiB,GAAGC,0BAAa,CAACC,YAAY,GAChD,IAAIC,KAAK,CAACF,0BAAa,CAACC,YAAY,EAAE;EACpCE,GAAGA,CAACC,MAA4B,EAAEC,IAAgC,EAAE;IAClE,MAAMC,gBAAgB,GAAGF,MAAM,CAACC,IAAI,CAAC;IACrC,IAAI,OAAOC,gBAAgB,KAAK,UAAU,EAAE;MAC1C,OAAO,kBAA0B;QAC/B,IAAI;UACF;UACA,OAAO,MAAMA,gBAAgB,CAAC,GAAAC,SAAO,CAAC;QACxC,CAAC,CAAC,OAAOC,KAAU,EAAE;UACnB,IAAIA,KAAK,aAALA,KAAK,eAALA,KAAK,CAAEC,IAAI,IAAIC,MAAM,CAACC,MAAM,CAACC,6BAAqB,CAAC,CAACC,QAAQ,CAACL,KAAK,CAACC,IAAI,CAAC,EAAE;YAC5E,MAAM,IAAIK,0BAAiB,CAAC,CAAAN,KAAK,aAALA,KAAK,uBAALA,KAAK,CAAEO,OAAO,KAAI,EAAE,EAAEP,KAAK,CAACC,IAAI,CAA0B;UACxF,CAAC,MAAM;YACL,MAAM,IAAIK,0BAAiB,CAAC,eAAe,EAAEF,6BAAqB,CAACI,OAAO,EAAER,KAAK,CAAC;UACpF;QACF;MACF,CAAC;IACH;IACA,OAAOF,gBAAgB;EACzB;AACF,CAAC,CAAC,GACF,IAAI;AAEO,SAASW,oBAAoBA,CAAA,EAAyB;EACnE,IAAIrB,qBAAQ,CAACsB,EAAE,KAAK,KAAK,EAAE;IACzB,OACEnB,iBAAiB,IACjB,IAAIG,KAAK,CACP,CAAC,CAAC,EACF;MACEC,GAAGA,CAAA,EAAG;QACJ,MAAM,IAAIgB,KAAK,CAACxB,aAAa,CAAC;MAChC;IACF,CAAC,CACF;EAEL;EAEA,OAAO,IAAIyB,oBAAW,EAAE;AAC1B"}
@@ -1,41 +0,0 @@
1
- import { NativeModules, Platform } from 'react-native';
2
- import GoogleDrive from './google-drive';
3
- import { CloudStorageErrorCode } from './types/native';
4
- import CloudStorageError from './utils/CloudStorageError';
5
- const LINKING_ERROR = `The package 'react-native-cloud-storage' doesn't seem to be linked. Make sure: \n\n` + Platform.select({
6
- ios: "- You have run 'pod install'\n",
7
- default: ''
8
- }) + '- You rebuilt the app after installing the package\n' + '- You are not using Expo Go\n';
9
-
10
- // proxy NativeModules.CloudStorage to catch any errors thrown by the native module and wrap them in a CloudStorageError
11
- const nativeIosInstance = NativeModules.CloudStorage ? new Proxy(NativeModules.CloudStorage, {
12
- get(target, prop) {
13
- const originalFunction = target[prop];
14
- if (typeof originalFunction === 'function') {
15
- return async function () {
16
- try {
17
- // @ts-expect-error - we can't know the types of the functions and their arguments
18
- return await originalFunction(...arguments);
19
- } catch (error) {
20
- if (error !== null && error !== void 0 && error.code && Object.values(CloudStorageErrorCode).includes(error.code)) {
21
- throw new CloudStorageError((error === null || error === void 0 ? void 0 : error.message) || '', error.code);
22
- } else {
23
- throw new CloudStorageError('Unknown error', CloudStorageErrorCode.UNKNOWN, error);
24
- }
25
- }
26
- };
27
- }
28
- return originalFunction;
29
- }
30
- }) : null;
31
- export default function createRNCloudStorage() {
32
- if (Platform.OS === 'ios') {
33
- return nativeIosInstance ?? new Proxy({}, {
34
- get() {
35
- throw new Error(LINKING_ERROR);
36
- }
37
- });
38
- }
39
- return new GoogleDrive();
40
- }
41
- //# sourceMappingURL=createRNCloudStorage.js.map
@@ -1 +0,0 @@
1
- {"version":3,"names":["NativeModules","Platform","GoogleDrive","CloudStorageErrorCode","CloudStorageError","LINKING_ERROR","select","ios","default","nativeIosInstance","CloudStorage","Proxy","get","target","prop","originalFunction","arguments","error","code","Object","values","includes","message","UNKNOWN","createRNCloudStorage","OS","Error"],"sourceRoot":"../../src","sources":["createRNCloudStorage.ts"],"mappings":"AAAA,SAASA,aAAa,EAAEC,QAAQ,QAAQ,cAAc;AAEtD,OAAOC,WAAW,MAAM,gBAAgB;AACxC,SAASC,qBAAqB,QAAQ,gBAAgB;AACtD,OAAOC,iBAAiB,MAAM,2BAA2B;AAEzD,MAAMC,aAAa,GAChB,qFAAoF,GACrFJ,QAAQ,CAACK,MAAM,CAAC;EAAEC,GAAG,EAAE,gCAAgC;EAAEC,OAAO,EAAE;AAAG,CAAC,CAAC,GACvE,sDAAsD,GACtD,+BAA+B;;AAEjC;AACA,MAAMC,iBAAiB,GAAGT,aAAa,CAACU,YAAY,GAChD,IAAIC,KAAK,CAACX,aAAa,CAACU,YAAY,EAAE;EACpCE,GAAGA,CAACC,MAA4B,EAAEC,IAAgC,EAAE;IAClE,MAAMC,gBAAgB,GAAGF,MAAM,CAACC,IAAI,CAAC;IACrC,IAAI,OAAOC,gBAAgB,KAAK,UAAU,EAAE;MAC1C,OAAO,kBAA0B;QAC/B,IAAI;UACF;UACA,OAAO,MAAMA,gBAAgB,CAAC,GAAAC,SAAO,CAAC;QACxC,CAAC,CAAC,OAAOC,KAAU,EAAE;UACnB,IAAIA,KAAK,aAALA,KAAK,eAALA,KAAK,CAAEC,IAAI,IAAIC,MAAM,CAACC,MAAM,CAACjB,qBAAqB,CAAC,CAACkB,QAAQ,CAACJ,KAAK,CAACC,IAAI,CAAC,EAAE;YAC5E,MAAM,IAAId,iBAAiB,CAAC,CAAAa,KAAK,aAALA,KAAK,uBAALA,KAAK,CAAEK,OAAO,KAAI,EAAE,EAAEL,KAAK,CAACC,IAAI,CAA0B;UACxF,CAAC,MAAM;YACL,MAAM,IAAId,iBAAiB,CAAC,eAAe,EAAED,qBAAqB,CAACoB,OAAO,EAAEN,KAAK,CAAC;UACpF;QACF;MACF,CAAC;IACH;IACA,OAAOF,gBAAgB;EACzB;AACF,CAAC,CAAC,GACF,IAAI;AAER,eAAe,SAASS,oBAAoBA,CAAA,EAAyB;EACnE,IAAIvB,QAAQ,CAACwB,EAAE,KAAK,KAAK,EAAE;IACzB,OACEhB,iBAAiB,IACjB,IAAIE,KAAK,CACP,CAAC,CAAC,EACF;MACEC,GAAGA,CAAA,EAAG;QACJ,MAAM,IAAIc,KAAK,CAACrB,aAAa,CAAC;MAChC;IACF,CAAC,CACF;EAEL;EAEA,OAAO,IAAIH,WAAW,EAAE;AAC1B"}
@@ -1,3 +0,0 @@
1
- import type NativeRNCloudStorage from './types/native';
2
- export default function createRNCloudStorage(): NativeRNCloudStorage;
3
- //# sourceMappingURL=createRNCloudStorage.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"createRNCloudStorage.d.ts","sourceRoot":"","sources":["../../src/createRNCloudStorage.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,oBAAoB,MAAM,gBAAgB,CAAC;AAmCvD,MAAM,CAAC,OAAO,UAAU,oBAAoB,IAAI,oBAAoB,CAgBnE"}
@@ -1,53 +0,0 @@
1
- import { NativeModules, Platform } from 'react-native';
2
- import type NativeRNCloudStorage from './types/native';
3
- import GoogleDrive from './google-drive';
4
- import { CloudStorageErrorCode } from './types/native';
5
- import CloudStorageError from './utils/CloudStorageError';
6
-
7
- const LINKING_ERROR =
8
- `The package 'react-native-cloud-storage' doesn't seem to be linked. Make sure: \n\n` +
9
- Platform.select({ ios: "- You have run 'pod install'\n", default: '' }) +
10
- '- You rebuilt the app after installing the package\n' +
11
- '- You are not using Expo Go\n';
12
-
13
- // proxy NativeModules.CloudStorage to catch any errors thrown by the native module and wrap them in a CloudStorageError
14
- const nativeIosInstance = NativeModules.CloudStorage
15
- ? new Proxy(NativeModules.CloudStorage, {
16
- get(target: NativeRNCloudStorage, prop: keyof NativeRNCloudStorage) {
17
- const originalFunction = target[prop];
18
- if (typeof originalFunction === 'function') {
19
- return async (...args: any[]) => {
20
- try {
21
- // @ts-expect-error - we can't know the types of the functions and their arguments
22
- return await originalFunction(...args);
23
- } catch (error: any) {
24
- if (error?.code && Object.values(CloudStorageErrorCode).includes(error.code)) {
25
- throw new CloudStorageError(error?.message || '', error.code as CloudStorageErrorCode);
26
- } else {
27
- throw new CloudStorageError('Unknown error', CloudStorageErrorCode.UNKNOWN, error);
28
- }
29
- }
30
- };
31
- }
32
- return originalFunction;
33
- },
34
- })
35
- : null;
36
-
37
- export default function createRNCloudStorage(): NativeRNCloudStorage {
38
- if (Platform.OS === 'ios') {
39
- return (
40
- nativeIosInstance ??
41
- new Proxy(
42
- {},
43
- {
44
- get() {
45
- throw new Error(LINKING_ERROR);
46
- },
47
- }
48
- )
49
- );
50
- }
51
-
52
- return new GoogleDrive();
53
- }