react-native-cloud-storage 2.2.2 → 2.3.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 (188) hide show
  1. package/LICENSE +1 -1
  2. package/android/build.gradle +101 -0
  3. package/android/gradle.properties +5 -0
  4. package/android/src/main/AndroidManifest.xml +3 -0
  5. package/android/src/main/AndroidManifestNew.xml +2 -0
  6. package/android/src/main/java/com/voicekit/CloudStorageError.kt +86 -0
  7. package/android/src/main/java/com/voicekit/CloudStorageLocalFileSystemModule.kt +236 -0
  8. package/android/src/main/java/com/voicekit/CloudStoragePackage.kt +17 -0
  9. package/android/src/main/java/com/voicekit/FileUtils.kt +41 -0
  10. package/android/src/main/java/com/voicekit/Types.kt +6 -0
  11. package/app.plugin.js +1 -1
  12. package/{lib/commonjs/RNCloudStorage.js → dist/commonjs/cloud-storage.js} +130 -80
  13. package/dist/commonjs/cloud-storage.js.map +1 -0
  14. package/dist/commonjs/expo-plugin/index.js +13 -0
  15. package/dist/commonjs/expo-plugin/index.js.map +1 -0
  16. package/{lib/commonjs/expo-plugin/withRNCloudStorageIos.js → dist/commonjs/expo-plugin/ios.js} +1 -1
  17. package/dist/commonjs/expo-plugin/ios.js.map +1 -0
  18. package/{lib/commonjs/hooks/useCloudFile.js → dist/commonjs/hooks/use-cloud-file.js} +26 -8
  19. package/dist/commonjs/hooks/use-cloud-file.js.map +1 -0
  20. package/{lib/commonjs/hooks/useIsCloudAvailable.js → dist/commonjs/hooks/use-is-cloud-available.js} +3 -3
  21. package/dist/commonjs/hooks/use-is-cloud-available.js.map +1 -0
  22. package/{lib → dist}/commonjs/index.js +10 -10
  23. package/dist/commonjs/index.js.map +1 -0
  24. package/dist/commonjs/storages/cloudkit.js +10 -0
  25. package/dist/commonjs/storages/cloudkit.js.map +1 -0
  26. package/{lib/commonjs → dist/commonjs/storages}/google-drive/client.js +80 -38
  27. package/dist/commonjs/storages/google-drive/client.js.map +1 -0
  28. package/{lib/commonjs → dist/commonjs/storages}/google-drive/index.js +120 -64
  29. package/dist/commonjs/storages/google-drive/index.js.map +1 -0
  30. package/dist/commonjs/storages/google-drive/types.js.map +1 -0
  31. package/dist/commonjs/types/native.js +28 -0
  32. package/dist/commonjs/types/native.js.map +1 -0
  33. package/{lib/commonjs/utils/CloudStorageError.js → dist/commonjs/utils/cloud-storage-error.js} +3 -1
  34. package/dist/commonjs/utils/cloud-storage-error.js.map +1 -0
  35. package/dist/commonjs/utils/constants.js +24 -0
  36. package/dist/commonjs/utils/constants.js.map +1 -0
  37. package/dist/commonjs/utils/local-fs.js +16 -0
  38. package/dist/commonjs/utils/local-fs.js.map +1 -0
  39. package/dist/commonjs/utils/native.js +35 -0
  40. package/dist/commonjs/utils/native.js.map +1 -0
  41. package/{lib/module/RNCloudStorage.js → dist/module/cloud-storage.js} +130 -80
  42. package/dist/module/cloud-storage.js.map +1 -0
  43. package/dist/module/expo-plugin/index.js +8 -0
  44. package/dist/module/expo-plugin/index.js.map +1 -0
  45. package/{lib/module/expo-plugin/withRNCloudStorageIos.js → dist/module/expo-plugin/ios.js} +1 -1
  46. package/dist/module/expo-plugin/ios.js.map +1 -0
  47. package/{lib/module/hooks/useCloudFile.js → dist/module/hooks/use-cloud-file.js} +25 -7
  48. package/dist/module/hooks/use-cloud-file.js.map +1 -0
  49. package/{lib/module/hooks/useIsCloudAvailable.js → dist/module/hooks/use-is-cloud-available.js} +2 -2
  50. package/dist/module/hooks/use-is-cloud-available.js.map +1 -0
  51. package/dist/module/index.js +9 -0
  52. package/dist/module/index.js.map +1 -0
  53. package/dist/module/storages/cloudkit.js +6 -0
  54. package/dist/module/storages/cloudkit.js.map +1 -0
  55. package/{lib/module → dist/module/storages}/google-drive/client.js +80 -38
  56. package/dist/module/storages/google-drive/client.js.map +1 -0
  57. package/{lib/module → dist/module/storages}/google-drive/index.js +119 -62
  58. package/dist/module/storages/google-drive/index.js.map +1 -0
  59. package/dist/module/storages/google-drive/types.js.map +1 -0
  60. package/dist/module/types/native.js +24 -0
  61. package/dist/module/types/native.js.map +1 -0
  62. package/{lib/module/utils/CloudStorageError.js → dist/module/utils/cloud-storage-error.js} +3 -1
  63. package/dist/module/utils/cloud-storage-error.js.map +1 -0
  64. package/dist/module/utils/constants.js +20 -0
  65. package/dist/module/utils/constants.js.map +1 -0
  66. package/dist/module/utils/local-fs.js +12 -0
  67. package/dist/module/utils/local-fs.js.map +1 -0
  68. package/dist/module/utils/native.js +30 -0
  69. package/dist/module/utils/native.js.map +1 -0
  70. package/{lib/typescript/RNCloudStorage.d.ts → dist/typescript/cloud-storage.d.ts} +60 -8
  71. package/dist/typescript/cloud-storage.d.ts.map +1 -0
  72. package/{lib/typescript/expo-plugin/withRNCloudStorage.d.ts → dist/typescript/expo-plugin/index.d.ts} +1 -1
  73. package/dist/typescript/expo-plugin/index.d.ts.map +1 -0
  74. package/{lib/typescript/expo-plugin/withRNCloudStorageIos.d.ts → dist/typescript/expo-plugin/ios.d.ts} +1 -1
  75. package/dist/typescript/expo-plugin/ios.d.ts.map +1 -0
  76. package/{lib/typescript/hooks/useCloudFile.d.ts → dist/typescript/hooks/use-cloud-file.d.ts} +22 -4
  77. package/dist/typescript/hooks/use-cloud-file.d.ts.map +1 -0
  78. package/{lib/typescript/hooks/useIsCloudAvailable.d.ts → dist/typescript/hooks/use-is-cloud-available.d.ts} +2 -2
  79. package/dist/typescript/hooks/use-is-cloud-available.d.ts.map +1 -0
  80. package/dist/typescript/index.d.ts +7 -0
  81. package/dist/typescript/index.d.ts.map +1 -0
  82. package/dist/typescript/storages/cloudkit.d.ts +3 -0
  83. package/dist/typescript/storages/cloudkit.d.ts.map +1 -0
  84. package/{lib/typescript → dist/typescript/storages}/google-drive/client.d.ts +9 -2
  85. package/dist/typescript/storages/google-drive/client.d.ts.map +1 -0
  86. package/dist/typescript/storages/google-drive/index.d.ts +35 -0
  87. package/dist/typescript/storages/google-drive/index.d.ts.map +1 -0
  88. package/dist/typescript/storages/google-drive/types.d.ts.map +1 -0
  89. package/dist/typescript/types/native.d.ts +64 -0
  90. package/dist/typescript/types/native.d.ts.map +1 -0
  91. package/dist/typescript/utils/cloud-storage-error.d.ts +8 -0
  92. package/dist/typescript/utils/cloud-storage-error.d.ts.map +1 -0
  93. package/dist/typescript/utils/constants.d.ts +4 -0
  94. package/dist/typescript/utils/constants.d.ts.map +1 -0
  95. package/{lib → dist}/typescript/utils/helpers.d.ts.map +1 -1
  96. package/dist/typescript/utils/local-fs.d.ts +3 -0
  97. package/dist/typescript/utils/local-fs.d.ts.map +1 -0
  98. package/dist/typescript/utils/native.d.ts +7 -0
  99. package/dist/typescript/utils/native.d.ts.map +1 -0
  100. package/ios/CloudStorage.xcodeproj/project.pbxproj +12 -6
  101. package/ios/{CloudStorage.m → CloudStorageCloudKit.m} +4 -2
  102. package/ios/{CloudStorage.swift → CloudStorageCloudKit.swift} +60 -5
  103. package/ios/CloudStorageLocalFileSystem.m +15 -0
  104. package/ios/CloudStorageLocalFileSystem.swift +215 -0
  105. package/ios/Utils/CloudKitUtils.swift +4 -4
  106. package/ios/Utils/CloudStorageError.swift +8 -0
  107. package/ios/Utils/FileUtils.swift +19 -0
  108. package/ios/Utils/Types.swift +7 -1
  109. package/package.json +44 -103
  110. package/src/{RNCloudStorage.ts → cloud-storage.ts} +147 -85
  111. package/src/expo-plugin/{withRNCloudStorage.ts → index.ts} +2 -2
  112. package/src/hooks/{useCloudFile.ts → use-cloud-file.ts} +24 -6
  113. package/src/hooks/{useIsCloudAvailable.ts → use-is-cloud-available.ts} +1 -1
  114. package/src/index.ts +5 -6
  115. package/src/storages/cloudkit.ts +5 -0
  116. package/src/{google-drive → storages/google-drive}/client.ts +98 -40
  117. package/src/{google-drive → storages/google-drive}/index.ts +172 -89
  118. package/src/types/native.ts +50 -14
  119. package/src/utils/cloud-storage-error.ts +15 -0
  120. package/src/utils/constants.ts +20 -0
  121. package/src/utils/local-fs.ts +19 -0
  122. package/src/utils/native.ts +40 -0
  123. package/lib/commonjs/RNCloudStorage.js.map +0 -1
  124. package/lib/commonjs/expo-plugin/withRNCloudStorage.js +0 -13
  125. package/lib/commonjs/expo-plugin/withRNCloudStorage.js.map +0 -1
  126. package/lib/commonjs/expo-plugin/withRNCloudStorageIos.js.map +0 -1
  127. package/lib/commonjs/google-drive/client.js.map +0 -1
  128. package/lib/commonjs/google-drive/index.js.map +0 -1
  129. package/lib/commonjs/google-drive/types.js.map +0 -1
  130. package/lib/commonjs/hooks/useCloudFile.js.map +0 -1
  131. package/lib/commonjs/hooks/useIsCloudAvailable.js.map +0 -1
  132. package/lib/commonjs/index.js.map +0 -1
  133. package/lib/commonjs/types/native.js +0 -26
  134. package/lib/commonjs/types/native.js.map +0 -1
  135. package/lib/commonjs/utils/CloudStorageError.js.map +0 -1
  136. package/lib/module/RNCloudStorage.js.map +0 -1
  137. package/lib/module/expo-plugin/withRNCloudStorage.js +0 -8
  138. package/lib/module/expo-plugin/withRNCloudStorage.js.map +0 -1
  139. package/lib/module/expo-plugin/withRNCloudStorageIos.js.map +0 -1
  140. package/lib/module/google-drive/client.js.map +0 -1
  141. package/lib/module/google-drive/index.js.map +0 -1
  142. package/lib/module/google-drive/types.js.map +0 -1
  143. package/lib/module/hooks/useCloudFile.js.map +0 -1
  144. package/lib/module/hooks/useIsCloudAvailable.js.map +0 -1
  145. package/lib/module/index.js +0 -10
  146. package/lib/module/index.js.map +0 -1
  147. package/lib/module/types/native.js +0 -22
  148. package/lib/module/types/native.js.map +0 -1
  149. package/lib/module/utils/CloudStorageError.js.map +0 -1
  150. package/lib/typescript/RNCloudStorage.d.ts.map +0 -1
  151. package/lib/typescript/expo-plugin/withRNCloudStorage.d.ts.map +0 -1
  152. package/lib/typescript/expo-plugin/withRNCloudStorageIos.d.ts.map +0 -1
  153. package/lib/typescript/google-drive/client.d.ts.map +0 -1
  154. package/lib/typescript/google-drive/index.d.ts +0 -34
  155. package/lib/typescript/google-drive/index.d.ts.map +0 -1
  156. package/lib/typescript/google-drive/types.d.ts.map +0 -1
  157. package/lib/typescript/hooks/useCloudFile.d.ts.map +0 -1
  158. package/lib/typescript/hooks/useIsCloudAvailable.d.ts.map +0 -1
  159. package/lib/typescript/index.d.ts +0 -8
  160. package/lib/typescript/index.d.ts.map +0 -1
  161. package/lib/typescript/types/native.d.ts +0 -40
  162. package/lib/typescript/types/native.d.ts.map +0 -1
  163. package/lib/typescript/utils/CloudStorageError.d.ts +0 -8
  164. package/lib/typescript/utils/CloudStorageError.d.ts.map +0 -1
  165. package/src/utils/CloudStorageError.ts +0 -14
  166. /package/{lib → dist}/commonjs/expo-plugin/types/index.js +0 -0
  167. /package/{lib → dist}/commonjs/expo-plugin/types/index.js.map +0 -0
  168. /package/{lib/commonjs → dist/commonjs/storages}/google-drive/types.js +0 -0
  169. /package/{lib → dist}/commonjs/types/main.js +0 -0
  170. /package/{lib → dist}/commonjs/types/main.js.map +0 -0
  171. /package/{lib → dist}/commonjs/utils/helpers.js +0 -0
  172. /package/{lib → dist}/commonjs/utils/helpers.js.map +0 -0
  173. /package/{lib → dist}/module/expo-plugin/types/index.js +0 -0
  174. /package/{lib → dist}/module/expo-plugin/types/index.js.map +0 -0
  175. /package/{lib → dist}/module/package.json +0 -0
  176. /package/{lib/module → dist/module/storages}/google-drive/types.js +0 -0
  177. /package/{lib → dist}/module/types/main.js +0 -0
  178. /package/{lib → dist}/module/types/main.js.map +0 -0
  179. /package/{lib → dist}/module/utils/helpers.js +0 -0
  180. /package/{lib → dist}/module/utils/helpers.js.map +0 -0
  181. /package/{lib → dist}/typescript/expo-plugin/types/index.d.ts +0 -0
  182. /package/{lib → dist}/typescript/expo-plugin/types/index.d.ts.map +0 -0
  183. /package/{lib/typescript → dist/typescript/storages}/google-drive/types.d.ts +0 -0
  184. /package/{lib → dist}/typescript/types/main.d.ts +0 -0
  185. /package/{lib → dist}/typescript/types/main.d.ts.map +0 -0
  186. /package/{lib → dist}/typescript/utils/helpers.d.ts +0 -0
  187. /package/src/expo-plugin/{withRNCloudStorageIos.ts → ios.ts} +0 -0
  188. /package/src/{google-drive → storages/google-drive}/types.ts +0 -0
@@ -1,7 +1,7 @@
1
1
  import Foundation
2
2
 
3
- @objc(CloudStorage)
4
- class CloudStorage: NSObject {
3
+ @objc(CloudStorageCloudKit)
4
+ class CloudStorageCloudKit: NSObject {
5
5
  @objc(fileExists:withScope:withResolver:withRejecter:)
6
6
  func fileExists(path: String, scope: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
7
7
  withPromise(resolve: resolve, reject: reject) {
@@ -62,11 +62,11 @@ class CloudStorage: NSObject {
62
62
  }
63
63
  }
64
64
 
65
- @objc(downloadFile:withScope:withResolver:withRejecter:)
66
- func downloadFile(path: String, scope: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
65
+ @objc(triggerSync:withScope:withResolver:withRejecter:)
66
+ func triggerSync(path: String, scope: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
67
67
  withPromise(resolve: resolve, reject: reject) {
68
68
  let fileUrl = try CloudKitUtils.getFileURL(path: path, scope: scope)
69
- return try CloudKitUtils.downloadFile(fileUrl: fileUrl)
69
+ return try CloudKitUtils.triggerSync(fileUrl: fileUrl)
70
70
  }
71
71
  }
72
72
 
@@ -94,6 +94,61 @@ class CloudStorage: NSObject {
94
94
  }
95
95
  }
96
96
 
97
+ @objc(downloadFile:withLocalPath:withScope:withResolver:withRejecter:)
98
+ func downloadFile(remotePath: String, localPath: String, scope: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
99
+ withPromise(resolve: resolve, reject: reject) {
100
+ let sourceUrl = try CloudKitUtils.getFileURL(path: remotePath, scope: scope, true)
101
+
102
+ let sourceStat = try FileUtils.statFile(fileUrl: sourceUrl)
103
+ if sourceStat.isDirectory {
104
+ throw CloudStorageError.pathIsDirectory(path: remotePath)
105
+ }
106
+
107
+ let destinationUrl = URL(fileURLWithPath: localPath)
108
+ let destinationDirectoryUrl = destinationUrl.deletingLastPathComponent()
109
+
110
+ if try !FileUtils.checkFileExists(fileUrl: destinationDirectoryUrl) {
111
+ throw CloudStorageError.directoryNotFound(path: destinationDirectoryUrl.path)
112
+ }
113
+
114
+ let destDirStat = try FileUtils.statFile(fileUrl: destinationDirectoryUrl)
115
+ if !destDirStat.isDirectory {
116
+ throw CloudStorageError.pathIsFile(path: destinationDirectoryUrl.path)
117
+ }
118
+
119
+ if try FileUtils.checkFileExists(fileUrl: destinationUrl) {
120
+ throw CloudStorageError.fileAlreadyExists(path: localPath)
121
+ }
122
+
123
+ return try FileUtils.copyFile(from: sourceUrl, to: destinationUrl)
124
+ }
125
+ }
126
+
127
+ @objc(uploadFile:withLocalPath:withMimeType:withScope:withOverwrite:withResolver:withRejecter:)
128
+ func uploadFile(remotePath: String, localPath: String, mimeType _: String, scope: String, overwrite: Bool, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
129
+ withPromise(resolve: resolve, reject: reject) {
130
+ let destinationUrl = try CloudKitUtils.getFileURL(path: remotePath, scope: scope)
131
+ let sourceUrl = URL(fileURLWithPath: localPath)
132
+
133
+ if try !FileUtils.checkFileExists(fileUrl: sourceUrl) {
134
+ throw CloudStorageError.fileNotFound(path: localPath)
135
+ }
136
+
137
+ let destinationDirectoryUrl = destinationUrl.deletingLastPathComponent()
138
+ try FileUtils.createDirectory(directoryUrl: destinationDirectoryUrl)
139
+
140
+ if try FileUtils.checkFileExists(fileUrl: destinationUrl) {
141
+ if overwrite {
142
+ try FileUtils.deleteFileOrDirectory(fileUrl: destinationUrl)
143
+ } else {
144
+ throw CloudStorageError.fileAlreadyExists(path: remotePath)
145
+ }
146
+ }
147
+
148
+ return try FileUtils.copyFile(from: sourceUrl, to: destinationUrl)
149
+ }
150
+ }
151
+
97
152
  @objc(isCloudAvailable:withRejecter:)
98
153
  func isCloudAvailable(resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
99
154
  withPromise(resolve: resolve, reject: reject) {
@@ -0,0 +1,15 @@
1
+ #import <React/RCTBridgeModule.h>
2
+
3
+ @interface RCT_EXTERN_MODULE(CloudStorageLocalFileSystem, NSObject)
4
+
5
+ RCT_EXTERN_METHOD(readFile:(NSString *)path withResolver:(RCTPromiseResolveBlock)resolve withRejecter:(RCTPromiseRejectBlock)reject)
6
+ RCT_EXTERN_METHOD(createFile:(NSString *)path withData:(NSString *)data withResolver:(RCTPromiseResolveBlock)resolve withRejecter:(RCTPromiseRejectBlock)reject)
7
+ RCT_EXTERN_METHOD(downloadFile:(NSString *)remoteUri withLocalPath:(NSString *)localPath withOptions:(NSDictionary *)options withResolver:(RCTPromiseResolveBlock)resolve withRejecter:(RCTPromiseRejectBlock)reject)
8
+ RCT_EXTERN_METHOD(uploadFile:(NSString *)localPath withRemoteUri:(NSString *)remoteUri withOptions:(NSDictionary *)options withResolver:(RCTPromiseResolveBlock)resolve withRejecter:(RCTPromiseRejectBlock)reject)
9
+
10
+ + (BOOL)requiresMainQueueSetup
11
+ {
12
+ return NO;
13
+ }
14
+
15
+ @end
@@ -0,0 +1,215 @@
1
+ import Foundation
2
+ import MobileCoreServices
3
+
4
+ // MARK: - CloudStorageLocalFileSystem
5
+
6
+ @objc(CloudStorageLocalFileSystem)
7
+ class CloudStorageLocalFileSystem: NSObject {
8
+ @objc
9
+ func constantsToExport() -> [AnyHashable: Any]! {
10
+ [
11
+ "temporaryDirectory": FileUtils.temporaryDirectory.path,
12
+ ]
13
+ }
14
+
15
+ @objc(createFile:withData:withResolver:withRejecter:)
16
+ func createFile(path: String, data: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
17
+ withPromise(resolve: resolve, reject: reject) {
18
+ let fileUrl = URL(fileURLWithPath: path)
19
+ let directoryUrl = fileUrl.deletingLastPathComponent()
20
+
21
+ var isDirectory: ObjCBool = false
22
+ if !FileManager.default.fileExists(atPath: directoryUrl.path, isDirectory: &isDirectory) {
23
+ throw CloudStorageError.directoryNotFound(path: directoryUrl.path)
24
+ }
25
+
26
+ if !isDirectory.boolValue {
27
+ throw CloudStorageError.pathIsFile(path: directoryUrl.path)
28
+ }
29
+
30
+ try FileUtils.writeFile(fileUrl: fileUrl, content: data)
31
+ return fileUrl.path
32
+ }
33
+ }
34
+
35
+ @objc(readFile:withResolver:withRejecter:)
36
+ func readFile(path: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
37
+ withPromise(resolve: resolve, reject: reject) {
38
+ let fileUrl = URL(fileURLWithPath: path)
39
+ return try FileUtils.readFile(fileUrl: fileUrl)
40
+ }
41
+ }
42
+
43
+ @objc(downloadFile:withLocalPath:withOptions:withResolver:withRejecter:)
44
+ func downloadFile(remoteUri: String, localPath: String, options: [String: Any]?, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
45
+ guard let remoteUrl = URL(string: remoteUri) else {
46
+ let error = CloudStorageError.invalidUrl(url: remoteUri)
47
+ reject(error.code, error.message, nil)
48
+ return
49
+ }
50
+
51
+ let sanitizedPath = sanitizePath(localPath)
52
+ let localUrl = URL(fileURLWithPath: sanitizedPath)
53
+
54
+ let configuration = URLSessionConfiguration.default
55
+ if let headers = options?["headers"] as? [String: String] {
56
+ configuration.httpAdditionalHeaders = headers
57
+ }
58
+ let session = URLSession(configuration: configuration)
59
+
60
+ let downloadTask = session.downloadTask(with: remoteUrl) { tempLocalUrl, _, error in
61
+ if let error {
62
+ let nsError = error as NSError
63
+ let cloudError = CloudStorageError.networkError(message: "Download error for path \(remoteUri): \(nsError.localizedDescription)")
64
+ reject(cloudError.code, cloudError.message, nsError)
65
+ return
66
+ }
67
+
68
+ guard let tempLocalUrl else {
69
+ let cloudError = CloudStorageError.unknown(message: "Download failed: temporary file location is missing.")
70
+ reject(cloudError.code, cloudError.message, nil)
71
+ return
72
+ }
73
+
74
+ do {
75
+ let directory = localUrl.deletingLastPathComponent()
76
+ try FileManager.default.createDirectory(at: directory, withIntermediateDirectories: true, attributes: nil)
77
+
78
+ if FileManager.default.fileExists(atPath: localUrl.path) {
79
+ try FileManager.default.removeItem(at: localUrl)
80
+ }
81
+
82
+ try FileManager.default.moveItem(at: tempLocalUrl, to: localUrl)
83
+ resolve(nil)
84
+ } catch {
85
+ let nsError = error as NSError
86
+ let cloudError = CloudStorageError.writeError(path: localUrl.path)
87
+ reject(cloudError.code, cloudError.message, nsError)
88
+ }
89
+ }
90
+
91
+ downloadTask.resume()
92
+ }
93
+
94
+ @objc(uploadFile:withRemoteUri:withOptions:withResolver:withRejecter:)
95
+ func uploadFile(localPath: String, remoteUri: String, options: [String: Any], resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
96
+ guard let remoteUrl = URL(string: remoteUri) else {
97
+ let error = CloudStorageError.invalidUrl(url: remoteUri)
98
+ reject(error.code, error.message, nil)
99
+ return
100
+ }
101
+
102
+ let sanitizedPath = sanitizePath(localPath)
103
+ let localUrl = URL(fileURLWithPath: sanitizedPath)
104
+
105
+ guard let uploadTypeString = options["uploadType"] as? String,
106
+ let uploadType = UploadType(rawValue: uploadTypeString) else {
107
+ let error = CloudStorageError.unknown(message: "uploadType is required and must be either 'multipart' or 'binary'")
108
+ reject(error.code, error.message, nil)
109
+ return
110
+ }
111
+
112
+ var request = URLRequest(url: remoteUrl)
113
+ request.httpMethod = (options["method"] as? String)?.uppercased() ?? "POST"
114
+
115
+ if let headers = options["headers"] as? [String: String] {
116
+ for (key, value) in headers {
117
+ request.setValue(value, forHTTPHeaderField: key)
118
+ }
119
+ }
120
+
121
+ do {
122
+ let fileData = try Data(contentsOf: localUrl)
123
+
124
+ switch uploadType {
125
+ case .binary:
126
+ request.httpBody = fileData
127
+ if request.value(forHTTPHeaderField: "Content-Type") == nil {
128
+ request.setValue("application/octet-stream", forHTTPHeaderField: "Content-Type")
129
+ }
130
+ case .multipart:
131
+ guard let fieldName = options["fieldName"] as? String else {
132
+ let error = CloudStorageError.unknown(message: "fieldName is required for multipart uploads")
133
+ reject(error.code, error.message, nil)
134
+ return
135
+ }
136
+
137
+ let boundary = "Boundary-\(UUID().uuidString)"
138
+ request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
139
+
140
+ var body = Data()
141
+ let lineBreak = "\r\n"
142
+
143
+ if let parameters = options["parameters"] as? [String: String] {
144
+ for (key, value) in parameters {
145
+ body.append("--\(boundary)\(lineBreak)")
146
+ body.append("Content-Disposition: form-data; name=\"\(key)\"\(lineBreak)\(lineBreak)")
147
+ body.append("\(value)\(lineBreak)")
148
+ }
149
+ }
150
+
151
+ body.append("--\(boundary)\(lineBreak)")
152
+ body.append("Content-Disposition: form-data; name=\"\(fieldName)\"; filename=\"\(localUrl.lastPathComponent)\"\(lineBreak)")
153
+ if let mimeType = getMimeType(for: localUrl) {
154
+ body.append("Content-Type: \(mimeType)\(lineBreak)\(lineBreak)")
155
+ } else {
156
+ body.append("Content-Type: application/octet-stream\(lineBreak)\(lineBreak)")
157
+ }
158
+ body.append(fileData)
159
+ body.append(lineBreak)
160
+ body.append("--\(boundary)--\(lineBreak)")
161
+
162
+ request.httpBody = body
163
+ }
164
+
165
+ let task = URLSession.shared.dataTask(with: request) { _, response, error in
166
+ if let error {
167
+ let nsError = error as NSError
168
+ let cloudError = CloudStorageError.networkError(message: "Upload error for path \(sanitizedPath): \(nsError.localizedDescription)")
169
+ reject(cloudError.code, cloudError.message, nsError)
170
+ return
171
+ }
172
+
173
+ guard let httpResponse = response as? HTTPURLResponse, (200 ... 299).contains(httpResponse.statusCode) else {
174
+ let httpResponse = response as? HTTPURLResponse
175
+ let message = "Upload failed for path \(sanitizedPath) with status code: \(httpResponse?.statusCode ?? -1)"
176
+ let cloudError = CloudStorageError.networkError(message: message)
177
+ reject(cloudError.code, cloudError.message, nil)
178
+ return
179
+ }
180
+
181
+ resolve(nil)
182
+ }
183
+ task.resume()
184
+ } catch {
185
+ let nsError = error as NSError
186
+ let cloudError = CloudStorageError.readError(path: sanitizedPath)
187
+ reject(cloudError.code, cloudError.message, nsError)
188
+ }
189
+ }
190
+
191
+ private func sanitizePath(_ path: String) -> String {
192
+ if path.hasPrefix("file://") {
193
+ return String(path.dropFirst("file://".count))
194
+ }
195
+ return path
196
+ }
197
+
198
+ private func getMimeType(for url: URL) -> String? {
199
+ let pathExtension = url.pathExtension
200
+ if let uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, pathExtension as CFString, nil)?.takeRetainedValue() {
201
+ if let mimetype = UTTypeCopyPreferredTagWithClass(uti, kUTTagClassMIMEType)?.takeRetainedValue() {
202
+ return mimetype as String
203
+ }
204
+ }
205
+ return nil
206
+ }
207
+ }
208
+
209
+ extension Data {
210
+ mutating func append(_ string: String) {
211
+ if let data = string.data(using: .utf8) {
212
+ append(data)
213
+ }
214
+ }
215
+ }
@@ -21,12 +21,12 @@ enum CloudKitUtils {
21
21
  }
22
22
 
23
23
  /**
24
- Downloads a file from iCloud.
24
+ Syncs a file from iCloud to the device.
25
25
 
26
- - Parameter fileUrl: The URL of the file to download.
27
- - Throws: An NSError if the file is not downloadable or the download failed.
26
+ - Parameter fileUrl: The URL of the file to sync.
27
+ - Throws: An NSError if the file is not downloadable or the sync failed.
28
28
  */
29
- static func downloadFile(fileUrl: URL) throws {
29
+ static func triggerSync(fileUrl: URL) throws {
30
30
  let isDownloadable = fileManager.isUbiquitousItem(at: fileUrl)
31
31
 
32
32
  if !isDownloadable {
@@ -23,6 +23,8 @@ enum CloudStorageError: Error {
23
23
  case statError(path: String)
24
24
  case unknown(message: String = "An unknown error occurred")
25
25
  case fileNotDownloadable(path: String)
26
+ case invalidUrl(url: String)
27
+ case networkError(message: String)
26
28
 
27
29
  var code: String {
28
30
  switch self {
@@ -40,6 +42,8 @@ enum CloudStorageError: Error {
40
42
  case .statError: "ERR_STAT_ERROR"
41
43
  case .unknown: "ERR_UNKNOWN"
42
44
  case .fileNotDownloadable: "ERR_FILE_NOT_DOWNLOADABLE"
45
+ case .invalidUrl: "ERR_INVALID_URL"
46
+ case .networkError: "ERR_NETWORK_ERROR"
43
47
  }
44
48
  }
45
49
 
@@ -73,6 +77,10 @@ enum CloudStorageError: Error {
73
77
  message
74
78
  case let .fileNotDownloadable(path):
75
79
  "File not downloadable at path \(path)"
80
+ case let .invalidUrl(url):
81
+ "Invalid URL provided: \(url)"
82
+ case let .networkError(message):
83
+ message
76
84
  }
77
85
  }
78
86
  }
@@ -94,6 +94,21 @@ enum FileUtils {
94
94
  }
95
95
  }
96
96
 
97
+ /**
98
+ Copies a file from a source to a destination.
99
+
100
+ - Parameter sourceUrl: The URL of the file to copy from.
101
+ - Parameter destinationUrl: The URL to copy the file to.
102
+ - Throws: An NSError if the file couldn't be copied.
103
+ */
104
+ static func copyFile(from sourceUrl: URL, to destinationUrl: URL) throws {
105
+ do {
106
+ try fileManager.copyItem(at: sourceUrl, to: destinationUrl)
107
+ } catch {
108
+ throw CloudStorageError.writeError(path: destinationUrl.path)
109
+ }
110
+ }
111
+
97
112
  /**
98
113
  Gets the stats of a file.
99
114
 
@@ -129,4 +144,8 @@ enum FileUtils {
129
144
  static func sanitizePath(path: String) -> String {
130
145
  path.replacingOccurrences(of: "^/+", with: "", options: .regularExpression)
131
146
  }
147
+
148
+ static var temporaryDirectory: URL {
149
+ fileManager.temporaryDirectory
150
+ }
132
151
  }
@@ -8,9 +8,15 @@
8
8
 
9
9
  import Foundation
10
10
 
11
+ // MARK: - UploadType
12
+
13
+ enum UploadType: String {
14
+ case multipart
15
+ case binary
16
+ }
17
+
11
18
  // MARK: - DirectoryScope
12
19
 
13
- @frozen
14
20
  enum DirectoryScope: String {
15
21
  case appData = "app_data"
16
22
  case documents
package/package.json CHANGED
@@ -1,21 +1,21 @@
1
1
  {
2
2
  "name": "react-native-cloud-storage",
3
- "version": "2.2.2",
4
- "description": "Save to & read from iCloud and Google Drive using React Native",
5
- "main": "lib/commonjs/index",
6
- "module": "lib/module/index",
7
- "types": "lib/typescript/index.d.ts",
3
+ "version": "2.3.0",
4
+ "description": "☁️ Save to & read from iCloud and Google Drive using React Native",
5
+ "main": "dist/commonjs/index",
6
+ "module": "dist/module/index",
7
+ "types": "dist/typescript/index.d.ts",
8
8
  "react-native": "src/index",
9
9
  "source": "src/index",
10
10
  "files": [
11
11
  "src",
12
- "lib",
12
+ "dist",
13
13
  "android",
14
14
  "ios",
15
15
  "cpp",
16
16
  "*.podspec",
17
17
  "app.plugin.js",
18
- "!lib/typescript/example",
18
+ "!dist/typescript/example",
19
19
  "!ios/build",
20
20
  "!android/build",
21
21
  "!android/gradle",
@@ -27,54 +27,48 @@
27
27
  "!**/__mocks__",
28
28
  "!**/.*"
29
29
  ],
30
+ "keywords": [
31
+ "react-native",
32
+ "ios",
33
+ "android",
34
+ "icloud",
35
+ "google-drive",
36
+ "file-system"
37
+ ],
30
38
  "scripts": {
39
+ "clean": "del-cli android/build ios/build dist",
40
+ "build": "yarn clean && bob build && rm -f dist/commonjs/package.json",
31
41
  "test": "jest",
32
- "example": "yarn workspace react-native-cloud-storage-example",
33
- "docs": "yarn workspace react-native-cloud-storage-docs",
34
42
  "typecheck": "tsc --noEmit",
35
- "lint": "eslint \"**/*.{js,ts,tsx}\"",
36
- "clean": "del-cli android/build example/android/build example/android/app/build example/ios/build lib",
37
- "prepare": "yarn clean && bob build && rm -f lib/commonjs/package.json",
43
+ "lint": "eslint src/**/*.ts",
44
+ "format": "prettier --write . && ./scripts/swiftformat.sh",
38
45
  "release": "release-it",
39
- "check": "yarn lint && scripts/swiftformat.sh"
46
+ "prepack": "cp ../../README.md ./README.md",
47
+ "postpack": "rm ./README.md"
40
48
  },
41
- "keywords": [
42
- "react-native",
43
- "ios",
44
- "android"
45
- ],
46
- "repository": "https://github.com/Kuatsu/react-native-cloud-storage",
47
- "author": "Kuatsu App Agency <hello@kuatsu.de> (https://github.com/Kuatsu)",
49
+ "repository": {
50
+ "type": "git",
51
+ "url": "git+https://github.com/kuatsu/react-native-cloud-storage.git"
52
+ },
53
+ "author": "Kuatsu App Agency <hello@kuatsu.de>",
48
54
  "license": "MIT",
49
55
  "bugs": {
50
- "url": "https://github.com/Kuatsu/react-native-cloud-storage/issues"
56
+ "url": "https://github.com/kuatsu/react-native-cloud-storage/issues"
51
57
  },
52
- "homepage": "https://github.com/Kuatsu/react-native-cloud-storage#readme",
58
+ "homepage": "https://github.com/kuatsu/react-native-cloud-storage#readme",
59
+ "packageManager": "yarn@3.6.1",
53
60
  "publishConfig": {
54
61
  "registry": "https://registry.npmjs.org/"
55
62
  },
56
63
  "devDependencies": {
57
- "@commitlint/config-conventional": "^17.0.2",
58
- "@evilmartians/lefthook": "^1.5.0",
59
- "@expo/config-plugins": "^7.2.5",
60
- "@react-native-community/eslint-config": "^3.2.0",
61
- "@react-native/eslint-config": "0.74.87",
64
+ "@expo/config-plugins": "^10.0.2",
62
65
  "@release-it/conventional-changelog": "^5.0.0",
63
- "@types/jest": "^28.1.2",
64
- "@types/react": "^18.2.6",
65
- "commitlint": "^17.0.2",
66
- "del-cli": "^5.0.0",
67
- "eslint": "^8.4.1",
68
- "eslint-config-prettier": "^8.5.0",
69
- "eslint-plugin-prettier": "^4.0.0",
70
- "jest": "^28.1.1",
71
- "pod-install": "^0.2.2",
72
- "prettier": "^2.0.5",
73
- "react": "18.2.0",
74
- "react-native": "0.74.5",
66
+ "@types/react": "~19.0.10",
67
+ "react": "19.0.0",
68
+ "react-native": "0.79.3",
75
69
  "react-native-builder-bob": "^0.30.2",
76
70
  "release-it": "^15.0.0",
77
- "typescript": "^5.0.2"
71
+ "typescript": "~5.8.3"
78
72
  },
79
73
  "peerDependencies": {
80
74
  "expo": ">=48.0.0",
@@ -86,24 +80,10 @@
86
80
  "optional": true
87
81
  }
88
82
  },
89
- "workspaces": [
90
- "example",
91
- "docs"
92
- ],
93
- "engines": {
94
- "node": ">= 18.0.0"
95
- },
96
- "packageManager": "yarn@3.6.1",
97
83
  "jest": {
98
84
  "preset": "react-native",
99
85
  "modulePathIgnorePatterns": [
100
- "<rootDir>/example/node_modules",
101
- "<rootDir>/lib/"
102
- ]
103
- },
104
- "commitlint": {
105
- "extends": [
106
- "@commitlint/config-conventional"
86
+ "<rootDir>/dist/"
107
87
  ]
108
88
  },
109
89
  "release-it": {
@@ -112,65 +92,26 @@
112
92
  "tagName": "v${version}"
113
93
  },
114
94
  "npm": {
115
- "publish": true
95
+ "publish": true,
96
+ "versionArgs": [
97
+ "--workspaces-update=false"
98
+ ]
116
99
  },
117
100
  "github": {
118
101
  "release": true
119
102
  },
120
103
  "plugins": {
121
104
  "@release-it/conventional-changelog": {
122
- "preset": "angular"
105
+ "preset": {
106
+ "name": "angular"
107
+ },
108
+ "infile": "CHANGELOG.md"
123
109
  }
124
110
  }
125
111
  },
126
- "eslintConfig": {
127
- "root": true,
128
- "extends": [
129
- "@react-native-community",
130
- "prettier"
131
- ],
132
- "rules": {
133
- "react-native/no-inline-styles": "off",
134
- "prettier/prettier": [
135
- "error",
136
- {
137
- "printWidth": 120,
138
- "tabWidth": 2,
139
- "useTabs": false,
140
- "semi": true,
141
- "singleQuote": true,
142
- "quoteProps": "consistent",
143
- "jsxSingleQuote": false,
144
- "trailingComma": "es5",
145
- "bracketSpacing": true,
146
- "bracketSameLine": true,
147
- "arrowParens": "always",
148
- "endOfLine": "lf"
149
- }
150
- ]
151
- }
152
- },
153
- "eslintIgnore": [
154
- "node_modules/",
155
- "lib/"
156
- ],
157
- "prettier": {
158
- "printWidth": 120,
159
- "tabWidth": 2,
160
- "useTabs": false,
161
- "semi": true,
162
- "singleQuote": true,
163
- "quoteProps": "consistent",
164
- "jsxSingleQuote": false,
165
- "trailingComma": "es5",
166
- "bracketSpacing": true,
167
- "bracketSameLine": true,
168
- "arrowParens": "always",
169
- "endOfLine": "lf"
170
- },
171
112
  "react-native-builder-bob": {
172
113
  "source": "src",
173
- "output": "lib",
114
+ "output": "dist",
174
115
  "targets": [
175
116
  "commonjs",
176
117
  "module",