react-native-cloud-storage 2.2.2 → 3.0.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 (216) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +1 -1
  3. package/android/build.gradle +88 -0
  4. package/android/gradle.properties +5 -0
  5. package/android/src/main/AndroidManifest.xml +3 -0
  6. package/android/src/main/AndroidManifestNew.xml +2 -0
  7. package/android/src/main/java/com/voicekit/CloudStorageError.kt +86 -0
  8. package/android/src/main/java/com/voicekit/CloudStorageLocalFileSystemModule.kt +232 -0
  9. package/android/src/main/java/com/voicekit/CloudStoragePackage.kt +32 -0
  10. package/android/src/main/java/com/voicekit/FileUtils.kt +41 -0
  11. package/android/src/main/java/com/voicekit/Types.kt +6 -0
  12. package/app.plugin.js +1 -1
  13. package/{lib/commonjs/RNCloudStorage.js → dist/commonjs/cloud-storage.js} +177 -92
  14. package/dist/commonjs/cloud-storage.js.map +1 -0
  15. package/dist/commonjs/expo-plugin/index.js +13 -0
  16. package/dist/commonjs/expo-plugin/index.js.map +1 -0
  17. package/{lib/commonjs/expo-plugin/withRNCloudStorageIos.js → dist/commonjs/expo-plugin/ios.js} +1 -1
  18. package/dist/commonjs/expo-plugin/ios.js.map +1 -0
  19. package/{lib/commonjs/hooks/useCloudFile.js → dist/commonjs/hooks/use-cloud-file.js} +26 -8
  20. package/dist/commonjs/hooks/use-cloud-file.js.map +1 -0
  21. package/{lib/commonjs/hooks/useIsCloudAvailable.js → dist/commonjs/hooks/use-is-cloud-available.js} +3 -3
  22. package/dist/commonjs/hooks/use-is-cloud-available.js.map +1 -0
  23. package/{lib → dist}/commonjs/index.js +10 -10
  24. package/dist/commonjs/index.js.map +1 -0
  25. package/dist/commonjs/specs/NativeCloudStorageCloudKitIOS.js +9 -0
  26. package/dist/commonjs/specs/NativeCloudStorageCloudKitIOS.js.map +1 -0
  27. package/dist/commonjs/specs/NativeCloudStorageLocalFileSystem.js +9 -0
  28. package/dist/commonjs/specs/NativeCloudStorageLocalFileSystem.js.map +1 -0
  29. package/dist/commonjs/storages/cloudkit.js +12 -0
  30. package/dist/commonjs/storages/cloudkit.js.map +1 -0
  31. package/{lib/commonjs → dist/commonjs/storages}/google-drive/client.js +83 -40
  32. package/dist/commonjs/storages/google-drive/client.js.map +1 -0
  33. package/dist/commonjs/storages/google-drive/index.js +399 -0
  34. package/dist/commonjs/storages/google-drive/index.js.map +1 -0
  35. package/dist/commonjs/storages/google-drive/types.js.map +1 -0
  36. package/{lib → dist}/commonjs/types/main.js.map +1 -1
  37. package/dist/commonjs/types/native.js +28 -0
  38. package/dist/commonjs/types/native.js.map +1 -0
  39. package/{lib/commonjs/utils/CloudStorageError.js → dist/commonjs/utils/cloud-storage-error.js} +3 -1
  40. package/dist/commonjs/utils/cloud-storage-error.js.map +1 -0
  41. package/dist/commonjs/utils/constants.js +25 -0
  42. package/dist/commonjs/utils/constants.js.map +1 -0
  43. package/dist/commonjs/utils/local-fs.js +17 -0
  44. package/dist/commonjs/utils/local-fs.js.map +1 -0
  45. package/dist/commonjs/utils/native.js +35 -0
  46. package/dist/commonjs/utils/native.js.map +1 -0
  47. package/{lib/module/RNCloudStorage.js → dist/module/cloud-storage.js} +178 -93
  48. package/dist/module/cloud-storage.js.map +1 -0
  49. package/dist/module/expo-plugin/index.js +8 -0
  50. package/dist/module/expo-plugin/index.js.map +1 -0
  51. package/{lib/module/expo-plugin/withRNCloudStorageIos.js → dist/module/expo-plugin/ios.js} +1 -1
  52. package/dist/module/expo-plugin/ios.js.map +1 -0
  53. package/{lib/module/hooks/useCloudFile.js → dist/module/hooks/use-cloud-file.js} +25 -7
  54. package/dist/module/hooks/use-cloud-file.js.map +1 -0
  55. package/{lib/module/hooks/useIsCloudAvailable.js → dist/module/hooks/use-is-cloud-available.js} +2 -2
  56. package/dist/module/hooks/use-is-cloud-available.js.map +1 -0
  57. package/dist/module/index.js +9 -0
  58. package/dist/module/index.js.map +1 -0
  59. package/dist/module/specs/NativeCloudStorageCloudKitIOS.js +5 -0
  60. package/dist/module/specs/NativeCloudStorageCloudKitIOS.js.map +1 -0
  61. package/dist/module/specs/NativeCloudStorageLocalFileSystem.js +5 -0
  62. package/dist/module/specs/NativeCloudStorageLocalFileSystem.js.map +1 -0
  63. package/dist/module/storages/cloudkit.js +7 -0
  64. package/dist/module/storages/cloudkit.js.map +1 -0
  65. package/{lib/module → dist/module/storages}/google-drive/client.js +83 -40
  66. package/dist/module/storages/google-drive/client.js.map +1 -0
  67. package/dist/module/storages/google-drive/index.js +392 -0
  68. package/dist/module/storages/google-drive/index.js.map +1 -0
  69. package/dist/module/storages/google-drive/types.js.map +1 -0
  70. package/{lib → dist}/module/types/main.js.map +1 -1
  71. package/dist/module/types/native.js +24 -0
  72. package/dist/module/types/native.js.map +1 -0
  73. package/{lib/module/utils/CloudStorageError.js → dist/module/utils/cloud-storage-error.js} +3 -1
  74. package/dist/module/utils/cloud-storage-error.js.map +1 -0
  75. package/dist/module/utils/constants.js +21 -0
  76. package/dist/module/utils/constants.js.map +1 -0
  77. package/dist/module/utils/local-fs.js +12 -0
  78. package/dist/module/utils/local-fs.js.map +1 -0
  79. package/dist/module/utils/native.js +30 -0
  80. package/dist/module/utils/native.js.map +1 -0
  81. package/{lib/typescript/RNCloudStorage.d.ts → dist/typescript/cloud-storage.d.ts} +67 -8
  82. package/dist/typescript/cloud-storage.d.ts.map +1 -0
  83. package/{lib/typescript/expo-plugin/withRNCloudStorage.d.ts → dist/typescript/expo-plugin/index.d.ts} +1 -1
  84. package/dist/typescript/expo-plugin/index.d.ts.map +1 -0
  85. package/{lib/typescript/expo-plugin/withRNCloudStorageIos.d.ts → dist/typescript/expo-plugin/ios.d.ts} +1 -1
  86. package/dist/typescript/expo-plugin/ios.d.ts.map +1 -0
  87. package/{lib/typescript/hooks/useCloudFile.d.ts → dist/typescript/hooks/use-cloud-file.d.ts} +22 -4
  88. package/dist/typescript/hooks/use-cloud-file.d.ts.map +1 -0
  89. package/{lib/typescript/hooks/useIsCloudAvailable.d.ts → dist/typescript/hooks/use-is-cloud-available.d.ts} +2 -2
  90. package/dist/typescript/hooks/use-is-cloud-available.d.ts.map +1 -0
  91. package/dist/typescript/index.d.ts +7 -0
  92. package/dist/typescript/index.d.ts.map +1 -0
  93. package/dist/typescript/specs/NativeCloudStorageCloudKitIOS.d.ts +30 -0
  94. package/dist/typescript/specs/NativeCloudStorageCloudKitIOS.d.ts.map +1 -0
  95. package/dist/typescript/specs/NativeCloudStorageLocalFileSystem.d.ts +24 -0
  96. package/dist/typescript/specs/NativeCloudStorageLocalFileSystem.d.ts.map +1 -0
  97. package/dist/typescript/storages/cloudkit.d.ts +6 -0
  98. package/dist/typescript/storages/cloudkit.d.ts.map +1 -0
  99. package/{lib/typescript → dist/typescript/storages}/google-drive/client.d.ts +10 -3
  100. package/dist/typescript/storages/google-drive/client.d.ts.map +1 -0
  101. package/dist/typescript/storages/google-drive/index.d.ts +41 -0
  102. package/dist/typescript/storages/google-drive/index.d.ts.map +1 -0
  103. package/dist/typescript/storages/google-drive/types.d.ts.map +1 -0
  104. package/{lib → dist}/typescript/types/main.d.ts +8 -0
  105. package/dist/typescript/types/main.d.ts.map +1 -0
  106. package/dist/typescript/types/native.d.ts +27 -0
  107. package/dist/typescript/types/native.d.ts.map +1 -0
  108. package/dist/typescript/utils/cloud-storage-error.d.ts +8 -0
  109. package/dist/typescript/utils/cloud-storage-error.d.ts.map +1 -0
  110. package/dist/typescript/utils/constants.d.ts +4 -0
  111. package/dist/typescript/utils/constants.d.ts.map +1 -0
  112. package/{lib → dist}/typescript/utils/helpers.d.ts.map +1 -1
  113. package/dist/typescript/utils/local-fs.d.ts +2 -0
  114. package/dist/typescript/utils/local-fs.d.ts.map +1 -0
  115. package/dist/typescript/utils/native.d.ts +7 -0
  116. package/dist/typescript/utils/native.d.ts.map +1 -0
  117. package/ios/CloudStorage-Bridging-Header.h +0 -1
  118. package/ios/CloudStorage.xcodeproj/project.pbxproj +12 -6
  119. package/ios/CloudStorageCloudKit.swift +159 -0
  120. package/ios/CloudStorageLocalFileSystem.swift +216 -0
  121. package/ios/RCTCloudStorageCloudKit.mm +209 -0
  122. package/ios/RCTCloudStorageLocalFileSystem.mm +149 -0
  123. package/ios/Utils/CloudKitUtils.swift +12 -6
  124. package/ios/Utils/CloudStorageError.swift +8 -0
  125. package/ios/Utils/FileUtils.swift +21 -4
  126. package/ios/Utils/Promise.swift +1 -0
  127. package/ios/Utils/Types.swift +8 -1
  128. package/ios/react_native_cloud_storage.h +6 -0
  129. package/package.json +64 -110
  130. package/react-native-cloud-storage.podspec +2 -0
  131. package/src/{RNCloudStorage.ts → cloud-storage.ts} +210 -100
  132. package/src/expo-plugin/{withRNCloudStorage.ts → index.ts} +2 -2
  133. package/src/hooks/{useCloudFile.ts → use-cloud-file.ts} +24 -6
  134. package/src/hooks/{useIsCloudAvailable.ts → use-is-cloud-available.ts} +1 -1
  135. package/src/index.ts +5 -6
  136. package/src/specs/NativeCloudStorageCloudKitIOS.ts +33 -0
  137. package/src/specs/NativeCloudStorageLocalFileSystem.ts +28 -0
  138. package/src/storages/cloudkit.ts +13 -0
  139. package/src/{google-drive → storages/google-drive}/client.ts +100 -41
  140. package/src/storages/google-drive/index.ts +488 -0
  141. package/src/types/main.ts +9 -0
  142. package/src/types/native.ts +14 -22
  143. package/src/utils/cloud-storage-error.ts +15 -0
  144. package/src/utils/constants.ts +21 -0
  145. package/src/utils/local-fs.ts +19 -0
  146. package/src/utils/native.ts +40 -0
  147. package/ios/CloudStorage.m +0 -22
  148. package/ios/CloudStorage.swift +0 -103
  149. package/ios/CloudStorageEventEmitter.m +0 -16
  150. package/ios/CloudStorageEventEmitter.swift +0 -30
  151. package/lib/commonjs/RNCloudStorage.js.map +0 -1
  152. package/lib/commonjs/expo-plugin/withRNCloudStorage.js +0 -13
  153. package/lib/commonjs/expo-plugin/withRNCloudStorage.js.map +0 -1
  154. package/lib/commonjs/expo-plugin/withRNCloudStorageIos.js.map +0 -1
  155. package/lib/commonjs/google-drive/client.js.map +0 -1
  156. package/lib/commonjs/google-drive/index.js +0 -321
  157. package/lib/commonjs/google-drive/index.js.map +0 -1
  158. package/lib/commonjs/google-drive/types.js.map +0 -1
  159. package/lib/commonjs/hooks/useCloudFile.js.map +0 -1
  160. package/lib/commonjs/hooks/useIsCloudAvailable.js.map +0 -1
  161. package/lib/commonjs/index.js.map +0 -1
  162. package/lib/commonjs/types/native.js +0 -26
  163. package/lib/commonjs/types/native.js.map +0 -1
  164. package/lib/commonjs/utils/CloudStorageError.js.map +0 -1
  165. package/lib/module/RNCloudStorage.js.map +0 -1
  166. package/lib/module/expo-plugin/withRNCloudStorage.js +0 -8
  167. package/lib/module/expo-plugin/withRNCloudStorage.js.map +0 -1
  168. package/lib/module/expo-plugin/withRNCloudStorageIos.js.map +0 -1
  169. package/lib/module/google-drive/client.js.map +0 -1
  170. package/lib/module/google-drive/index.js +0 -313
  171. package/lib/module/google-drive/index.js.map +0 -1
  172. package/lib/module/google-drive/types.js.map +0 -1
  173. package/lib/module/hooks/useCloudFile.js.map +0 -1
  174. package/lib/module/hooks/useIsCloudAvailable.js.map +0 -1
  175. package/lib/module/index.js +0 -10
  176. package/lib/module/index.js.map +0 -1
  177. package/lib/module/types/native.js +0 -22
  178. package/lib/module/types/native.js.map +0 -1
  179. package/lib/module/utils/CloudStorageError.js.map +0 -1
  180. package/lib/typescript/RNCloudStorage.d.ts.map +0 -1
  181. package/lib/typescript/expo-plugin/withRNCloudStorage.d.ts.map +0 -1
  182. package/lib/typescript/expo-plugin/withRNCloudStorageIos.d.ts.map +0 -1
  183. package/lib/typescript/google-drive/client.d.ts.map +0 -1
  184. package/lib/typescript/google-drive/index.d.ts +0 -34
  185. package/lib/typescript/google-drive/index.d.ts.map +0 -1
  186. package/lib/typescript/google-drive/types.d.ts.map +0 -1
  187. package/lib/typescript/hooks/useCloudFile.d.ts.map +0 -1
  188. package/lib/typescript/hooks/useIsCloudAvailable.d.ts.map +0 -1
  189. package/lib/typescript/index.d.ts +0 -8
  190. package/lib/typescript/index.d.ts.map +0 -1
  191. package/lib/typescript/types/main.d.ts.map +0 -1
  192. package/lib/typescript/types/native.d.ts +0 -40
  193. package/lib/typescript/types/native.d.ts.map +0 -1
  194. package/lib/typescript/utils/CloudStorageError.d.ts +0 -8
  195. package/lib/typescript/utils/CloudStorageError.d.ts.map +0 -1
  196. package/src/google-drive/index.ts +0 -399
  197. package/src/utils/CloudStorageError.ts +0 -14
  198. /package/{lib → dist}/commonjs/expo-plugin/types/index.js +0 -0
  199. /package/{lib → dist}/commonjs/expo-plugin/types/index.js.map +0 -0
  200. /package/{lib/commonjs → dist/commonjs/storages}/google-drive/types.js +0 -0
  201. /package/{lib → dist}/commonjs/types/main.js +0 -0
  202. /package/{lib → dist}/commonjs/utils/helpers.js +0 -0
  203. /package/{lib → dist}/commonjs/utils/helpers.js.map +0 -0
  204. /package/{lib → dist}/module/expo-plugin/types/index.js +0 -0
  205. /package/{lib → dist}/module/expo-plugin/types/index.js.map +0 -0
  206. /package/{lib → dist}/module/package.json +0 -0
  207. /package/{lib/module → dist/module/storages}/google-drive/types.js +0 -0
  208. /package/{lib → dist}/module/types/main.js +0 -0
  209. /package/{lib → dist}/module/utils/helpers.js +0 -0
  210. /package/{lib → dist}/module/utils/helpers.js.map +0 -0
  211. /package/{lib → dist}/typescript/expo-plugin/types/index.d.ts +0 -0
  212. /package/{lib → dist}/typescript/expo-plugin/types/index.d.ts.map +0 -0
  213. /package/{lib/typescript → dist/typescript/storages}/google-drive/types.d.ts +0 -0
  214. /package/{lib → dist}/typescript/utils/helpers.d.ts +0 -0
  215. /package/src/expo-plugin/{withRNCloudStorageIos.ts → ios.ts} +0 -0
  216. /package/src/{google-drive → storages/google-drive}/types.ts +0 -0
@@ -5,62 +5,22 @@ import {
5
5
  type CloudStorageProviderOptions,
6
6
  type DeepRequired,
7
7
  } from './types/main';
8
- import type NativeRNCloudStorage from './types/native';
8
+ import { NativeCloudStorageErrorCode, type NativeStorage, type NativeStorageScope } from './types/native';
9
9
  import { isProviderSupported } from './utils/helpers';
10
- import { NativeEventEmitter, NativeModules, Platform } from 'react-native';
11
- import CloudStorageError from './utils/CloudStorageError';
12
- import { CloudStorageErrorCode } from './types/native';
13
- import GoogleDrive from './google-drive';
14
-
15
- const LINKING_ERROR =
16
- `The package 'react-native-cloud-storage' doesn't seem to be linked. Make sure: \n\n` +
17
- Platform.select({ ios: "- You have run 'pod install'\n", default: '' }) +
18
- '- You rebuilt the app after installing the package\n' +
19
- '- You are not using Expo Go\n';
20
-
21
- // proxy NativeModules.CloudStorage to catch any errors thrown by the native module and wrap them in a CloudStorageError
22
- const nativeIosInstance = NativeModules.CloudStorage
23
- ? new Proxy(NativeModules.CloudStorage, {
24
- get(target: NativeRNCloudStorage, prop: keyof NativeRNCloudStorage) {
25
- const originalFunction = target[prop];
26
- if (typeof originalFunction === 'function') {
27
- return async (...args: any[]) => {
28
- try {
29
- // @ts-expect-error - we can't know the types of the functions and their arguments
30
- return await originalFunction(...args);
31
- } catch (error: any) {
32
- if (error?.code && Object.values(CloudStorageErrorCode).includes(error.code)) {
33
- throw new CloudStorageError(error?.message || '', error.code as CloudStorageErrorCode);
34
- } else {
35
- throw new CloudStorageError('Unknown error', CloudStorageErrorCode.UNKNOWN, error);
36
- }
37
- }
38
- };
39
- }
40
- return originalFunction;
41
- },
42
- })
43
- : null;
44
-
45
- const defaultProviderOptions: DeepRequired<CloudStorageProviderOptions> = {
46
- [CloudStorageProvider.ICloud]: {
47
- scope: CloudStorageScope.AppData,
48
- },
49
- [CloudStorageProvider.GoogleDrive]: {
50
- scope: CloudStorageScope.AppData,
51
- accessToken: null,
52
- strictFilenames: false,
53
- timeout: 3000,
54
- },
55
- };
10
+ import { Platform, type EventSubscription } from 'react-native';
11
+ import GoogleDrive from './storages/google-drive';
12
+ import { NativeCloudKit, NativeCloudKitModule, type NativeCloudStorageCloudKitTurboModule } from './storages/cloudkit';
13
+ import { DEFAULT_PROVIDER_OPTIONS, LINKING_ERROR } from './utils/constants';
14
+ import CloudStorageError from './utils/cloud-storage-error';
56
15
 
57
16
  export default class RNCloudStorage {
58
17
  private static defaultInstance: RNCloudStorage;
59
18
  private provider: {
60
19
  provider: CloudStorageProvider;
61
- options: (typeof defaultProviderOptions)[keyof typeof defaultProviderOptions];
20
+ options: (typeof DEFAULT_PROVIDER_OPTIONS)[keyof typeof DEFAULT_PROVIDER_OPTIONS];
62
21
  };
63
22
  private cloudAvailabilityListeners: ((available: boolean) => void)[] = [];
23
+ private cloudAvailabilitySubscription: EventSubscription | null = null;
64
24
 
65
25
  //#region Constructor and configuration
66
26
  /**
@@ -77,7 +37,7 @@ export default class RNCloudStorage {
77
37
 
78
38
  this.provider = {
79
39
  provider: provider ?? RNCloudStorage.getDefaultProvider(),
80
- options: defaultProviderOptions[provider ?? RNCloudStorage.getDefaultProvider()],
40
+ options: DEFAULT_PROVIDER_OPTIONS[provider ?? RNCloudStorage.getDefaultProvider()],
81
41
  };
82
42
 
83
43
  this.setProvider(provider ?? RNCloudStorage.getDefaultProvider());
@@ -86,22 +46,24 @@ export default class RNCloudStorage {
86
46
  }
87
47
  }
88
48
 
89
- private get nativeInstance(): NativeRNCloudStorage {
49
+ private get nativeStorage(): NativeStorage {
90
50
  switch (this.provider.provider) {
91
- case CloudStorageProvider.ICloud:
51
+ case CloudStorageProvider.ICloud: {
92
52
  return (
93
- nativeIosInstance ??
94
- new Proxy(
53
+ NativeCloudKit ??
54
+ (new Proxy(
95
55
  {},
96
56
  {
97
57
  get() {
98
58
  throw new Error(LINKING_ERROR);
99
59
  },
100
60
  }
101
- )
61
+ ) as NativeStorage)
102
62
  );
103
- default:
63
+ }
64
+ default: {
104
65
  return new GoogleDrive(this.provider.options as DeepRequired<CloudStorageProviderOptions['googledrive']>);
66
+ }
105
67
  }
106
68
  }
107
69
 
@@ -111,10 +73,12 @@ export default class RNCloudStorage {
111
73
  */
112
74
  static getDefaultProvider(): CloudStorageProvider {
113
75
  switch (Platform.OS) {
114
- case 'ios':
76
+ case 'ios': {
115
77
  return CloudStorageProvider.ICloud;
116
- default:
78
+ }
79
+ default: {
117
80
  return CloudStorageProvider.GoogleDrive;
81
+ }
118
82
  }
119
83
  }
120
84
 
@@ -123,7 +87,7 @@ export default class RNCloudStorage {
123
87
  * @returns An array of supported CloudStorageProviders.
124
88
  */
125
89
  static getSupportedProviders(): CloudStorageProvider[] {
126
- return Object.values(CloudStorageProvider).filter(isProviderSupported);
90
+ return Object.values(CloudStorageProvider).filter((provider) => isProviderSupported(provider));
127
91
  }
128
92
 
129
93
  /**
@@ -134,6 +98,49 @@ export default class RNCloudStorage {
134
98
  return this.provider.provider;
135
99
  }
136
100
 
101
+ private notifyCloudAvailabilityListeners(available: boolean): void {
102
+ for (const listener of this.cloudAvailabilityListeners) {
103
+ listener(available);
104
+ }
105
+ }
106
+
107
+ private refreshCloudAvailability(): void {
108
+ this.nativeStorage
109
+ .isCloudAvailable()
110
+ .then((available) => {
111
+ this.notifyCloudAvailabilityListeners(available);
112
+ })
113
+ .catch(() => {
114
+ // ignore errors when refreshing availability after provider changes
115
+ });
116
+ }
117
+
118
+ private getNativeCloudKitModule(): NativeCloudStorageCloudKitTurboModule | null {
119
+ return this.provider.provider === CloudStorageProvider.ICloud ? NativeCloudKitModule : null;
120
+ }
121
+
122
+ private removeCloudAvailabilitySubscription(): void {
123
+ this.cloudAvailabilitySubscription?.remove();
124
+ this.cloudAvailabilitySubscription = null;
125
+ }
126
+
127
+ private configureCloudAvailabilitySubscription(): void {
128
+ this.removeCloudAvailabilitySubscription();
129
+
130
+ if (this.cloudAvailabilityListeners.length === 0) {
131
+ return;
132
+ }
133
+
134
+ const nativeCloudKitModule = this.getNativeCloudKitModule();
135
+ if (!nativeCloudKitModule) {
136
+ return;
137
+ }
138
+
139
+ this.cloudAvailabilitySubscription = nativeCloudKitModule.onCloudAvailabilityChanged((event) => {
140
+ this.notifyCloudAvailabilityListeners(event.available);
141
+ });
142
+ }
143
+
137
144
  /**
138
145
  * Sets the current CloudStorageProvider.
139
146
  * @param provider The provider to set.
@@ -145,25 +152,11 @@ export default class RNCloudStorage {
145
152
 
146
153
  this.provider = {
147
154
  provider,
148
- options: defaultProviderOptions[provider],
155
+ options: DEFAULT_PROVIDER_OPTIONS[provider],
149
156
  };
150
157
 
151
- // Emit an event to notify useIsCloudAvailable() hook consumers of the new cloud availability status
152
- this.nativeInstance.isCloudAvailable().then((available) => {
153
- this.cloudAvailabilityListeners.forEach((listener) => {
154
- listener(available);
155
- });
156
- });
157
-
158
- if (provider === CloudStorageProvider.ICloud) {
159
- // Listen to native cloud availability change events
160
- const eventEmitter = new NativeEventEmitter(NativeModules.CloudStorageEventEmitter);
161
- eventEmitter.addListener('RNCloudStorage.cloud.availability-changed', (event: { available: boolean }) => {
162
- this.cloudAvailabilityListeners.forEach((listener) => {
163
- listener(event.available);
164
- });
165
- });
166
- }
158
+ this.refreshCloudAvailability();
159
+ this.configureCloudAvailabilitySubscription();
167
160
  }
168
161
 
169
162
  /**
@@ -187,20 +180,44 @@ export default class RNCloudStorage {
187
180
 
188
181
  if (this.provider.provider === CloudStorageProvider.GoogleDrive && 'accessToken' in newOptions) {
189
182
  // Emit an event to notify useIsCloudAvailable() hook consumers of the new cloud availability status
190
- this.cloudAvailabilityListeners.forEach((listener) => {
191
- listener(
192
- !!(newOptions as Required<CloudStorageProviderOptions[CloudStorageProvider.GoogleDrive]>).accessToken?.length
193
- );
194
- });
183
+ this.notifyCloudAvailabilityListeners(
184
+ !!(newOptions as Required<CloudStorageProviderOptions[CloudStorageProvider.GoogleDrive]>).accessToken?.length
185
+ );
195
186
  }
196
187
  }
197
188
 
198
189
  subscribeToCloudAvailability(listener: (available: boolean) => void): void {
199
190
  this.cloudAvailabilityListeners.push(listener);
191
+
192
+ if (this.cloudAvailabilityListeners.length === 1) {
193
+ this.configureCloudAvailabilitySubscription();
194
+ this.refreshCloudAvailability();
195
+ }
200
196
  }
201
197
 
202
198
  unsubscribeFromCloudAvailability(listener: (available: boolean) => void): void {
203
199
  this.cloudAvailabilityListeners = this.cloudAvailabilityListeners.filter((l) => l !== listener);
200
+
201
+ if (this.cloudAvailabilityListeners.length === 0) {
202
+ this.removeCloudAvailabilitySubscription();
203
+ }
204
+ }
205
+
206
+ private resolveNativeScope(scope?: CloudStorageScope): NativeStorageScope {
207
+ const resolvedScope = scope ?? this.provider.options.scope;
208
+
209
+ if (this.provider.provider !== CloudStorageProvider.ICloud || resolvedScope !== CloudStorageScope.Documents) {
210
+ return resolvedScope;
211
+ }
212
+
213
+ const iCloudOptions = this.provider.options as DeepRequired<
214
+ CloudStorageProviderOptions[CloudStorageProvider.ICloud]
215
+ >;
216
+ if (iCloudOptions.documentsMode === 'legacy_sandbox') {
217
+ return 'documents_legacy';
218
+ }
219
+
220
+ return resolvedScope;
204
221
  }
205
222
  //#endregion
206
223
 
@@ -211,7 +228,7 @@ export default class RNCloudStorage {
211
228
  * @returns A promise that resolves to true if the cloud storage is available, false otherwise.
212
229
  */
213
230
  isCloudAvailable(): Promise<boolean> {
214
- return this.nativeInstance.isCloudAvailable();
231
+ return this.nativeStorage.isCloudAvailable();
215
232
  }
216
233
 
217
234
  /**
@@ -222,7 +239,7 @@ export default class RNCloudStorage {
222
239
  * @returns A promise that resolves when the data has been appended.
223
240
  */
224
241
  appendFile(path: string, data: string, scope?: CloudStorageScope): Promise<void> {
225
- return this.nativeInstance.appendToFile(path, data, scope ?? this.provider.options.scope);
242
+ return this.nativeStorage.appendToFile(path, data, this.resolveNativeScope(scope));
226
243
  }
227
244
 
228
245
  /**
@@ -232,7 +249,7 @@ export default class RNCloudStorage {
232
249
  * @returns A promise that resolves to true if the path exists, false otherwise.
233
250
  */
234
251
  exists(path: string, scope?: CloudStorageScope): Promise<boolean> {
235
- return this.nativeInstance.fileExists(path, scope ?? this.provider.options.scope);
252
+ return this.nativeStorage.fileExists(path, this.resolveNativeScope(scope));
236
253
  }
237
254
 
238
255
  /**
@@ -243,7 +260,7 @@ export default class RNCloudStorage {
243
260
  * @returns A promise that resolves when the file has been written.
244
261
  */
245
262
  writeFile(path: string, data: string, scope?: CloudStorageScope): Promise<void> {
246
- return this.nativeInstance.createFile(path, data, scope ?? this.provider.options.scope, true);
263
+ return this.nativeStorage.createFile(path, data, this.resolveNativeScope(scope), true);
247
264
  }
248
265
 
249
266
  /**
@@ -253,7 +270,7 @@ export default class RNCloudStorage {
253
270
  * @returns A promise that resolves when the directory has been created.
254
271
  */
255
272
  mkdir(path: string, scope?: CloudStorageScope): Promise<void> {
256
- return this.nativeInstance.createDirectory(path, scope ?? this.provider.options.scope);
273
+ return this.nativeStorage.createDirectory(path, this.resolveNativeScope(scope));
257
274
  }
258
275
 
259
276
  /**
@@ -263,7 +280,7 @@ export default class RNCloudStorage {
263
280
  * @returns A promise that resolves to an array of file names, excluding '.' and '..'.
264
281
  */
265
282
  readdir(path: string, scope?: CloudStorageScope): Promise<string[]> {
266
- return this.nativeInstance.listFiles(path, scope ?? this.provider.options.scope);
283
+ return this.nativeStorage.listFiles(path, this.resolveNativeScope(scope));
267
284
  }
268
285
 
269
286
  /**
@@ -273,17 +290,66 @@ export default class RNCloudStorage {
273
290
  * @returns A promise that resolves to the contents of the file.
274
291
  */
275
292
  readFile(path: string, scope?: CloudStorageScope): Promise<string> {
276
- return this.nativeInstance.readFile(path, scope ?? this.provider.options.scope);
293
+ return this.nativeStorage.readFile(path, this.resolveNativeScope(scope));
277
294
  }
278
295
 
279
296
  /**
280
- * Downloads the file at the given path. Does not have any effect on Google Drive.
281
- * @param path The file to trigger the download for.
297
+ * Triggers synchronization for the file at the given path. Does not have any effect on Google Drive.
298
+ * @param path The file to trigger synchronization for.
282
299
  * @param scope The directory scope the path is in. Defaults to set default scope set for the current provider.
283
- * @returns A promise that resolves once the download has been triggered.
300
+ * @returns A promise that resolves once the synchronization has been triggered.
284
301
  */
285
- downloadFile(path: string, scope?: CloudStorageScope): Promise<void> {
286
- return this.nativeInstance.downloadFile(path, scope ?? this.provider.options.scope);
302
+ triggerSync(path: string, scope?: CloudStorageScope): Promise<void> {
303
+ return this.nativeStorage.triggerSync(path, this.resolveNativeScope(scope));
304
+ }
305
+
306
+ /**
307
+ * Uploads the file at the given local path to the given path, creating it if it doesn't exist or overwriting it if it does.
308
+ * @param remotePath The remote path to upload to.
309
+ * @param localPath The local path of the file to upload.
310
+ * @param options The options for the upload. Must contain a `mimeType` property.
311
+ * @param scope The directory scope the path is in. Defaults to set default scope set for the current provider.
312
+ * @returns A promise that resolves when the file has been uploaded.
313
+ */
314
+ uploadFile(
315
+ remotePath: string,
316
+ localPath: string,
317
+ options: { mimeType: string },
318
+ scope?: CloudStorageScope
319
+ ): Promise<void> {
320
+ return this.nativeStorage.uploadFile(remotePath, localPath, options.mimeType, this.resolveNativeScope(scope), true);
321
+ }
322
+
323
+ /**
324
+ * Triggers synchronization for the file at the given path. Does not have any effect on Google Drive.
325
+ * @param path The file to trigger synchronization for.
326
+ * @param scope The directory scope the path is in. Defaults to set default scope set for the current provider.
327
+ * @returns A promise that resolves once the synchronization has been triggered.
328
+ * @deprecated Use `triggerSync` instead.
329
+ */
330
+ downloadFile(path: string, scope?: CloudStorageScope): Promise<void>;
331
+ /**
332
+ * Downloads the cloud file at the given remote path to the given local path.
333
+ * @param remotePath The remote path of the file to download from the cloud.
334
+ * @param localPath The local path to download the cloud file to.
335
+ * @param scope The directory scope the path is in. Defaults to set default scope set for the current provider.
336
+ */
337
+ downloadFile(remotePath: string, localPath: string, scope?: CloudStorageScope): Promise<void>;
338
+ downloadFile(remotePathOrPath: string, localPathOrScope?: string, scope?: CloudStorageScope): Promise<void> {
339
+ if (
340
+ !localPathOrScope ||
341
+ (!scope &&
342
+ typeof localPathOrScope === 'string' &&
343
+ Object.values(CloudStorageScope).includes(localPathOrScope as CloudStorageScope))
344
+ ) {
345
+ // deprecated `triggerSync` call
346
+ return this.triggerSync(remotePathOrPath, scope);
347
+ }
348
+
349
+ if (!localPathOrScope) {
350
+ throw new CloudStorageError('Invalid arguments provided to downloadFile', NativeCloudStorageErrorCode.UNKNOWN);
351
+ }
352
+ return this.nativeStorage.downloadFile(remotePathOrPath, localPathOrScope, this.resolveNativeScope(scope));
287
353
  }
288
354
 
289
355
  /**
@@ -293,7 +359,7 @@ export default class RNCloudStorage {
293
359
  * @returns A promise that resolves when the file has been deleted.
294
360
  */
295
361
  unlink(path: string, scope?: CloudStorageScope): Promise<void> {
296
- return this.nativeInstance.deleteFile(path, scope ?? this.provider.options.scope);
362
+ return this.nativeStorage.deleteFile(path, this.resolveNativeScope(scope));
297
363
  }
298
364
 
299
365
  /**
@@ -304,7 +370,7 @@ export default class RNCloudStorage {
304
370
  * @returns A promise that resolves when the directory has been deleted.
305
371
  */
306
372
  rmdir(path: string, options?: { recursive?: boolean }, scope?: CloudStorageScope): Promise<void> {
307
- return this.nativeInstance.deleteDirectory(path, options?.recursive ?? false, scope ?? this.provider.options.scope);
373
+ return this.nativeStorage.deleteDirectory(path, options?.recursive ?? false, this.resolveNativeScope(scope));
308
374
  }
309
375
 
310
376
  /**
@@ -314,7 +380,7 @@ export default class RNCloudStorage {
314
380
  * @returns A promise that resolves to the CloudStorageFileStat object.
315
381
  */
316
382
  async stat(path: string, scope?: CloudStorageScope): Promise<CloudStorageFileStat> {
317
- const native = await this.nativeInstance.statFile(path, scope ?? this.provider.options.scope);
383
+ const native = await this.nativeStorage.statFile(path, this.resolveNativeScope(scope));
318
384
 
319
385
  return {
320
386
  ...native,
@@ -438,13 +504,57 @@ export default class RNCloudStorage {
438
504
  }
439
505
 
440
506
  /**
441
- * Downloads the file at the given path in the provider of the default static instance. Does not have any effect on Google Drive.
442
- * @param path The file to trigger the download for.
507
+ * Triggers synchronization for the file at the given path in the provider of the default static instance. Does not have any effect on Google Drive.
508
+ * @param path The file to trigger synchronization for.
443
509
  * @param scope The directory scope the path is in. Defaults to the default scope set for the default static instance.
444
- * @returns A promise that resolves once the download has been triggered.
510
+ * @returns A promise that resolves once the synchronization has been triggered.
511
+ */
512
+ static triggerSync(path: string, scope?: CloudStorageScope): Promise<void> {
513
+ return RNCloudStorage.getDefaultInstance().triggerSync(path, scope);
514
+ }
515
+
516
+ /**
517
+ * Uploads the file at the given local path to the given path in the provider of the default static instance, creating it if it doesn't exist or overwriting it if it does.
518
+ * @param remotePath The remote path to upload to.
519
+ * @param localPath The local path of the file to upload.
520
+ * @param options The options for the upload. Must contain a `mimeType` property.
521
+ * @param scope The directory scope the path is in. Defaults to set default scope set for the current provider.
522
+ * @returns A promise that resolves when the file has been uploaded.
523
+ */
524
+ static uploadFile(
525
+ remotePath: string,
526
+ localPath: string,
527
+ options: { mimeType: string },
528
+ scope?: CloudStorageScope
529
+ ): Promise<void> {
530
+ return RNCloudStorage.getDefaultInstance().uploadFile(remotePath, localPath, options, scope);
531
+ }
532
+
533
+ /**
534
+ * Triggers synchronization for the file at the given path in the provider of the default static instance. Does not have any effect on Google Drive.
535
+ * @param path The file to trigger synchronization for.
536
+ * @param scope The directory scope the path is in. Defaults to set default scope set for the current provider.
537
+ * @returns A promise that resolves once the synchronization has been triggered.
538
+ * @deprecated Use `triggerSync` instead.
445
539
  */
446
- static downloadFile(path: string, scope?: CloudStorageScope): Promise<void> {
447
- return RNCloudStorage.getDefaultInstance().downloadFile(path, scope);
540
+ static downloadFile(path: string, scope?: CloudStorageScope): Promise<void>;
541
+ /**
542
+ * Downloads the cloud file at the given remote path to the given local path.
543
+ * @param remotePath The remote path of the file to download from the cloud.
544
+ * @param localPath The local path to download the cloud file to.
545
+ * @param scope The directory scope the path is in. Defaults to set default scope set for the current provider.
546
+ */
547
+ static downloadFile(remotePath: string, localPath: string, scope?: CloudStorageScope): Promise<void>;
548
+ static downloadFile(remotePathOrPath: string, localPathOrScope?: string, scope?: CloudStorageScope): Promise<void> {
549
+ if (typeof scope === 'string') {
550
+ if (!localPathOrScope) {
551
+ throw new CloudStorageError('Invalid arguments provided to downloadFile', NativeCloudStorageErrorCode.UNKNOWN);
552
+ }
553
+ return RNCloudStorage.getDefaultInstance().downloadFile(remotePathOrPath, localPathOrScope, scope);
554
+ } else {
555
+ // deprecated `triggerSync` call
556
+ return RNCloudStorage.getDefaultInstance().triggerSync(remotePathOrPath, scope);
557
+ }
448
558
  }
449
559
 
450
560
  /**
@@ -1,8 +1,8 @@
1
1
  import type { RNCloudStorageConfigPluginOptions } from './types';
2
- import withRNCloudStorageIos from './withRNCloudStorageIos';
2
+ import withRNCloudStorageIos from './ios';
3
3
  import type { ConfigPlugin } from '@expo/config-plugins';
4
4
 
5
- // Android config plugin not needed as there's no native code to configure.
5
+ // Android config plugin not needed as there's nothing to configure.
6
6
 
7
7
  const withRNCloudStorage: ConfigPlugin<RNCloudStorageConfigPluginOptions> = (config, options) =>
8
8
  withRNCloudStorageIos(config, options);
@@ -1,5 +1,5 @@
1
1
  import type { CloudStorageScope } from '../types/main';
2
- import RNCloudStorage from '../RNCloudStorage';
2
+ import RNCloudStorage from '../cloud-storage';
3
3
  import { useCallback, useEffect, useState } from 'react';
4
4
 
5
5
  /**
@@ -39,19 +39,37 @@ export const useCloudFile = (path: string, scope?: CloudStorageScope, cloudStora
39
39
  setContent(null);
40
40
  }, [path, scope, instance]);
41
41
 
42
- const download = useCallback(async () => {
43
- await instance.downloadFile(path, scope);
42
+ const sync = useCallback(async () => {
43
+ await instance.triggerSync(path, scope);
44
44
  }, [path, scope, instance]);
45
45
 
46
46
  return {
47
+ /**
48
+ * The content of the file.
49
+ */
47
50
  content,
51
+ /**
52
+ * Reads the file from the cloud.
53
+ */
48
54
  read,
55
+ /**
56
+ * Writes new content to the file.
57
+ */
49
58
  write,
59
+ /**
60
+ * Deletes the file.
61
+ */
50
62
  remove,
51
63
  /**
52
- * Downloads the file from iCloud to the device. Needed if the file hasn't been synced yet. Has no effect on
53
- * Google Drive.
64
+ * Triggers synchronization for the file. Needed if the file hasn't been synced yet from iCloud.
65
+ * Has no effect on Google Drive.
66
+ */
67
+ sync,
68
+ /**
69
+ * Triggers synchronization for the file. Needed if the file hasn't been synced yet from iCloud.
70
+ * Has no effect on Google Drive.
71
+ * @deprecated Use `sync` instead.
54
72
  */
55
- download,
73
+ download: sync,
56
74
  };
57
75
  };
@@ -1,5 +1,5 @@
1
1
  import { useCallback, useEffect, useState } from 'react';
2
- import RNCloudStorage from '../RNCloudStorage';
2
+ import RNCloudStorage from '../cloud-storage';
3
3
 
4
4
  /**
5
5
  * A hook that tests whether or not the cloud storage is available.
package/src/index.ts CHANGED
@@ -1,8 +1,7 @@
1
- import RNCloudStorage from './RNCloudStorage';
2
- import { CloudStorageErrorCode } from './types/native';
3
1
  export * from './types/main';
4
- export * from './hooks/useCloudFile';
5
- export * from './hooks/useIsCloudAvailable';
6
- import CloudStorageError from './utils/CloudStorageError';
2
+ export * from './hooks/use-cloud-file';
3
+ export * from './hooks/use-is-cloud-available';
7
4
 
8
- export { RNCloudStorage as CloudStorage, CloudStorageError, CloudStorageErrorCode };
5
+ export { NativeCloudStorageErrorCode as CloudStorageErrorCode } from './types/native';
6
+ export { default as CloudStorageError } from './utils/cloud-storage-error';
7
+ export { default as CloudStorage } from './cloud-storage';
@@ -0,0 +1,33 @@
1
+ import type { CodegenTypes, TurboModule } from 'react-native';
2
+ import { TurboModuleRegistry } from 'react-native';
3
+
4
+ export type CloudStorageFileStat = {
5
+ size: number;
6
+ birthtimeMs: number;
7
+ mtimeMs: number;
8
+ isDirectory: boolean;
9
+ isFile: boolean;
10
+ };
11
+
12
+ export type CloudAvailabilityChangedEvent = {
13
+ available: boolean;
14
+ };
15
+
16
+ export interface Spec extends TurboModule {
17
+ fileExists(path: string, scope: string): Promise<boolean>;
18
+ appendToFile(path: string, data: string, scope: string): Promise<void>;
19
+ createFile(path: string, data: string, scope: string, overwrite: boolean): Promise<void>;
20
+ createDirectory(path: string, scope: string): Promise<void>;
21
+ listFiles(path: string, scope: string): Promise<Array<string>>;
22
+ readFile(path: string, scope: string): Promise<string>;
23
+ triggerSync(path: string, scope: string): Promise<void>;
24
+ deleteFile(path: string, scope: string): Promise<void>;
25
+ deleteDirectory(path: string, recursive: boolean, scope: string): Promise<void>;
26
+ statFile(path: string, scope: string): Promise<CloudStorageFileStat>;
27
+ downloadFile(remotePath: string, localPath: string, scope: string): Promise<void>;
28
+ uploadFile(remotePath: string, localPath: string, mimeType: string, scope: string, overwrite: boolean): Promise<void>;
29
+ isCloudAvailable(): Promise<boolean>;
30
+ readonly onCloudAvailabilityChanged: CodegenTypes.EventEmitter<CloudAvailabilityChangedEvent>;
31
+ }
32
+
33
+ export default TurboModuleRegistry.get<Spec>('CloudStorageCloudKit');
@@ -0,0 +1,28 @@
1
+ import type { CodegenTypes, TurboModule } from 'react-native';
2
+ import { TurboModuleRegistry } from 'react-native';
3
+
4
+ export type LocalFileSystemConstants = {
5
+ temporaryDirectory: string;
6
+ };
7
+
8
+ export type LocalFileSystemDownloadOptions = {
9
+ headers?: CodegenTypes.UnsafeObject;
10
+ };
11
+
12
+ export type LocalFileSystemUploadOptions = {
13
+ headers?: CodegenTypes.UnsafeObject;
14
+ method?: string;
15
+ uploadType?: string;
16
+ fieldName?: string;
17
+ parameters?: CodegenTypes.UnsafeObject;
18
+ };
19
+
20
+ export interface Spec extends TurboModule {
21
+ getConstants(): LocalFileSystemConstants;
22
+ createFile(path: string, data: string): Promise<string>;
23
+ readFile(path: string): Promise<string>;
24
+ downloadFile(remoteUri: string, localPath: string, options?: LocalFileSystemDownloadOptions): Promise<void>;
25
+ uploadFile(localPath: string, remoteUri: string, options: LocalFileSystemUploadOptions): Promise<void>;
26
+ }
27
+
28
+ export default TurboModuleRegistry.get<Spec>('CloudStorageLocalFileSystem');
@@ -0,0 +1,13 @@
1
+ import NativeCloudStorageCloudKitIOS, {
2
+ type Spec as NativeCloudStorageCloudKitTurboModule,
3
+ } from '../specs/NativeCloudStorageCloudKitIOS';
4
+ import { NativeStorage } from '../types/native';
5
+ import { createProxiedNativeModule } from '../utils/native';
6
+
7
+ export const NativeCloudKitModule = NativeCloudStorageCloudKitIOS;
8
+
9
+ export const NativeCloudKit = createProxiedNativeModule<NativeStorage>(
10
+ NativeCloudStorageCloudKitIOS as unknown as NativeStorage | null
11
+ );
12
+
13
+ export type { NativeCloudStorageCloudKitTurboModule };