@react-native-firebase/storage 26.4.0 → 27.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 (31) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/RNFBStorage.podspec +9 -4
  3. package/android/build.gradle +3 -0
  4. package/android/src/main/java/io/invertase/firebase/storage/RNFBStorageTaskRegistry.kt +88 -0
  5. package/android/src/test/java/io/invertase/firebase/storage/RNFBStorageTaskRegistryTest.java +25 -0
  6. package/dist/module/index.js +1 -2
  7. package/dist/module/index.js.map +1 -1
  8. package/dist/module/version.js +1 -1
  9. package/dist/typescript/lib/index.d.ts +1 -1
  10. package/dist/typescript/lib/types/internal.d.ts +2 -3
  11. package/dist/typescript/lib/types/internal.d.ts.map +1 -1
  12. package/dist/typescript/lib/version.d.ts +1 -1
  13. package/ios/RNFBStorage/RNFBStorageCommon.m +17 -98
  14. package/ios/RNFBStorage/RNFBStorageErrorCodeMapper.swift +122 -0
  15. package/ios/RNFBStorage/RNFBStorageErrorSnapshotDictBuilder.swift +70 -0
  16. package/ios/RNFBStorage/RNFBStorageTaskRegistry.m +28 -35
  17. package/ios/RNFBStorage/RNFBStorageTaskRegistryStorage.swift +87 -0
  18. package/ios/RNFBStorage/RNFBStorageTaskStatusMapper.swift +57 -0
  19. package/ios/RNFBStorage.xcodeproj/project.pbxproj +26 -0
  20. package/ios/RNFBStorageUnitTests/RNFBStorageErrorCodeMapperFacadeTests.m +91 -0
  21. package/ios/RNFBStorageUnitTests/RNFBStorageErrorCodeMapperTests.swift +211 -0
  22. package/ios/RNFBStorageUnitTests/RNFBStorageErrorSnapshotDictBuilderFacadeTests.m +125 -0
  23. package/ios/RNFBStorageUnitTests/RNFBStorageTaskRegistryStorageTests.swift +154 -0
  24. package/ios/RNFBStorageUnitTests/RNFBStorageTaskStatusMapperFacadeTests.m +52 -0
  25. package/ios/RNFBStorageUnitTests/RNFBStorageTaskStatusMapperTests.swift +58 -0
  26. package/ios/RNFBStorageUnitTests/RNFBStorageUnitTests.xcodeproj/project.pbxproj +50 -0
  27. package/lib/index.ts +1 -1
  28. package/lib/types/internal.ts +5 -4
  29. package/lib/version.ts +1 -1
  30. package/package.json +4 -4
  31. package/android/src/main/java/io/invertase/firebase/storage/RNFBStorageTaskRegistry.java +0 -93
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Copyright (c) 2016-present Invertase Limited & Contributors
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this library except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ import Foundation
18
+
19
+ /**
20
+ * Error payload attachment previously inline in
21
+ * `+[RNFBStorageCommon buildErrorSnapshotDict:taskSnapshotDict:]` and
22
+ * `+[RNFBStorageCommon buildErrorSnapshotDictFromCodeAndMessage:taskSnapshotDict:]`.
23
+ *
24
+ * Mutates `taskSnapshotDict` in place and returns the same instance (or nil when
25
+ * the snapshot dict is nil — matching ObjC nil-messaging).
26
+ */
27
+ @objc(RNFBStorageErrorSnapshotDictBuilder)
28
+ public final class RNFBStorageErrorSnapshotDictBuilder: NSObject {
29
+ @objc(buildErrorSnapshotDict:taskSnapshotDict:)
30
+ public static func buildErrorSnapshotDict(
31
+ _ error: NSError?,
32
+ taskSnapshotDict: NSMutableDictionary?
33
+ ) -> NSDictionary? {
34
+ guard let taskSnapshotDict else {
35
+ return nil
36
+ }
37
+
38
+ let codeAndMessage = RNFBStorageErrorCodeMapper.codeAndMessage(for: error)
39
+ var errorPayload: [String: Any] = [
40
+ "code": codeAndMessage[0],
41
+ "message": codeAndMessage[1],
42
+ ]
43
+ // Pre-port ObjC always set this key from `[error localizedDescription]`.
44
+ if let error {
45
+ errorPayload["nativeErrorMessage"] = error.localizedDescription
46
+ } else {
47
+ errorPayload["nativeErrorMessage"] = NSNull()
48
+ }
49
+ taskSnapshotDict["error"] = errorPayload
50
+ return taskSnapshotDict
51
+ }
52
+
53
+ @objc(buildErrorSnapshotDictFromCodeAndMessage:taskSnapshotDict:)
54
+ public static func buildErrorSnapshotDictFromCodeAndMessage(
55
+ _ codeAndMessage: [Any]?,
56
+ taskSnapshotDict: NSMutableDictionary?
57
+ ) -> NSDictionary? {
58
+ guard let taskSnapshotDict else {
59
+ return nil
60
+ }
61
+
62
+ // Pre-port ObjC indexed without bounds checks; callers always pass [code, message].
63
+ let pair = codeAndMessage!
64
+ taskSnapshotDict["error"] = [
65
+ "code": pair[0],
66
+ "message": pair[1],
67
+ ]
68
+ return taskSnapshotDict
69
+ }
70
+ }
@@ -23,8 +23,18 @@
23
23
  #import "RNFBApp/RNFBHandleMap.h"
24
24
  #endif
25
25
 
26
+ #if __has_include(<RNFBStorage/RNFBStorage-Swift.h>)
27
+ #import <RNFBStorage/RNFBStorage-Swift.h>
28
+ #elif __has_include("RNFBStorage-Swift.h")
29
+ #import "RNFBStorage-Swift.h"
30
+ #elif __has_include("RNFBHandleMapStorage-Swift.inc")
31
+ #import "RNFBHandleMapStorage-Swift.inc"
32
+ #else
33
+ #error "RNFBStorageTaskRegistryStorage Swift interface not found"
34
+ #endif
35
+
26
36
  @interface RNFBStorageTaskRegistry ()
27
- @property(nonatomic, strong) RNFBHandleMap *map;
37
+ @property(nonatomic, strong) RNFBStorageTaskRegistryStorage *storage;
28
38
  @end
29
39
 
30
40
  @implementation RNFBStorageTaskRegistry
@@ -32,63 +42,46 @@
32
42
  - (instancetype)init {
33
43
  self = [super init];
34
44
  if (self) {
35
- _map = [[RNFBHandleMap alloc] init];
45
+ _storage = [[RNFBStorageTaskRegistryStorage alloc] init];
36
46
  }
37
47
  return self;
38
48
  }
39
49
 
40
- - (void)rnfb_cancelHandle:(id)handle {
41
- if (handle && [handle respondsToSelector:@selector(cancel)]) {
42
- [handle cancel];
43
- }
44
- }
45
-
46
50
  - (BOOL)put:(id)key value:(id)value error:(NSError **)error {
47
- return [self.map put:key value:value error:error];
51
+ if (![self.storage putIfAbsent:key value:value]) {
52
+ if (error != nil) {
53
+ NSString *message = [NSString stringWithFormat:@"Handle id already registered: %@", key];
54
+ *error = [NSError errorWithDomain:RNFBHandleMapErrorDomain
55
+ code:RNFBHandleMapErrorCollision
56
+ userInfo:@{NSLocalizedDescriptionKey : message}];
57
+ }
58
+ return NO;
59
+ }
60
+ return YES;
48
61
  }
49
62
 
50
63
  - (BOOL)putOrDiscard:(id)key value:(id)value {
51
- if ([self.map putIfAbsent:key value:value]) {
52
- return YES;
53
- }
54
- [self rnfb_cancelHandle:value];
55
- return NO;
64
+ return [self.storage putOrDiscard:key value:value];
56
65
  }
57
66
 
58
67
  - (id)get:(id)key {
59
- return [self.map get:key];
68
+ return [self.storage get:key];
60
69
  }
61
70
 
62
71
  - (id)take:(id)key {
63
- return [self.map take:key];
72
+ return [self.storage take:key];
64
73
  }
65
74
 
66
75
  - (id)takeIf:(id)key when:(BOOL (^)(id))condition {
67
- return [self.map takeIf:key when:condition];
76
+ return [self.storage takeIf:key when:condition];
68
77
  }
69
78
 
70
79
  - (BOOL)takeAndCancel:(id)key {
71
- // Align with Android RNFBStorageTaskRegistry.takeAndCancel: get → cancel → identity take.
72
- // FIRStorage*Task cancel is void (no BOOL), so there is no keep-on-false path; always
73
- // identity-take after cancel. Production setTaskStatus cancel uses takeIf then cancel
74
- // (RNFBStorageHelper) — identity-safe; this helper matches Android ordering for registry/tests.
75
- id handle = [self.map get:key];
76
- if (handle == nil) {
77
- return NO;
78
- }
79
- [self rnfb_cancelHandle:handle];
80
- [self.map takeIf:key
81
- when:^BOOL(id value) {
82
- return value == handle;
83
- }];
84
- return YES;
80
+ return [self.storage takeAndCancel:key];
85
81
  }
86
82
 
87
83
  - (void)cancelAll {
88
- NSArray *handlers = [self.map takeAll];
89
- for (id handler in handlers) {
90
- [self rnfb_cancelHandle:handler];
91
- }
84
+ [self.storage cancelAll];
92
85
  }
93
86
 
94
87
  @end
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Copyright (c) 2016-present Invertase Limited & Contributors
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this library except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ import Foundation
18
+
19
+ #if canImport(RNFBApp)
20
+ import RNFBApp
21
+ #endif
22
+
23
+ /// Pending upload/download task map storage. Composes `RNFBHandleMapStorage`.
24
+ /// `putOrDiscard` is first-wins and calls `cancel` on the incoming value on collision.
25
+ /// Unique `put` collision errors stay on the ObjC façade.
26
+ @objc(RNFBStorageTaskRegistryStorage)
27
+ public final class RNFBStorageTaskRegistryStorage: NSObject {
28
+ private static let cancelSelector = Selector(("cancel"))
29
+
30
+ private let storage = RNFBHandleMapStorage()
31
+
32
+ private func cancelHandle(_ handle: AnyObject?) {
33
+ guard let handle = handle, handle.responds(to: Self.cancelSelector) else {
34
+ return
35
+ }
36
+ _ = handle.perform(Self.cancelSelector)
37
+ }
38
+
39
+ /// First-wins store without discarding the incoming value. Used by façade `put`.
40
+ @objc(putIfAbsent:value:)
41
+ public func putIfAbsent(_ key: AnyObject, value: AnyObject) -> Bool {
42
+ storage.putIfAbsent(key, value: value)
43
+ }
44
+
45
+ /// Unique put. On collision, `cancel`s the incoming value and leaves the existing mapping.
46
+ @objc(putOrDiscard:value:)
47
+ public func putOrDiscard(_ key: AnyObject, value: AnyObject) -> Bool {
48
+ if storage.putIfAbsent(key, value: value) {
49
+ return true
50
+ }
51
+ cancelHandle(value)
52
+ return false
53
+ }
54
+
55
+ @objc(get:)
56
+ public func get(_ key: AnyObject) -> AnyObject? {
57
+ storage.get(key)
58
+ }
59
+
60
+ @objc(take:)
61
+ public func take(_ key: AnyObject) -> AnyObject? {
62
+ storage.take(key)
63
+ }
64
+
65
+ @objc(takeIf:when:)
66
+ public func takeIf(_ key: AnyObject, when condition: (AnyObject) -> Bool) -> AnyObject? {
67
+ storage.takeIf(key, when: condition)
68
+ }
69
+
70
+ /// get → cancel → identity take (Android shape). FIRStorage cancel is void (no keep-on-false).
71
+ @objc(takeAndCancel:)
72
+ public func takeAndCancel(_ key: AnyObject) -> Bool {
73
+ guard let handle = storage.get(key) else {
74
+ return false
75
+ }
76
+ cancelHandle(handle)
77
+ _ = storage.takeIf(key, when: { $0 === handle })
78
+ return true
79
+ }
80
+
81
+ @objc
82
+ public func cancelAll() {
83
+ for handle in storage.takeAll() {
84
+ cancelHandle(handle)
85
+ }
86
+ }
87
+ }
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Copyright (c) 2016-present Invertase Limited & Contributors
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this library except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ import Foundation
18
+
19
+ /**
20
+ * `FIRStorageTaskStatus` raw value → JS task-state string mapping previously
21
+ * inline in `+[RNFBStorageCommon getTaskStatus:]`.
22
+ *
23
+ * Raw ints from Firebase Storage `StorageTaskStatus`
24
+ * (`@objc(FIRStorageTaskStatus)` in `StorageConstants.swift`):
25
+ * - unknown = 0, resume = 1, progress = 2, pause = 3, success = 4, failure = 5
26
+ *
27
+ * Hardcoded so the Storage unit target does not need FirebaseStorage.
28
+ */
29
+ @objc(RNFBStorageTaskStatusMapper)
30
+ public final class RNFBStorageTaskStatusMapper: NSObject {
31
+ /// `FIRStorageTaskStatusResume`
32
+ private static let statusResume = 1
33
+ /// `FIRStorageTaskStatusProgress`
34
+ private static let statusProgress = 2
35
+ /// `FIRStorageTaskStatusPause`
36
+ private static let statusPause = 3
37
+ /// `FIRStorageTaskStatusSuccess`
38
+ private static let statusSuccess = 4
39
+ /// `FIRStorageTaskStatusFailure`
40
+ private static let statusFailure = 5
41
+
42
+ @objc(stringForTaskStatus:)
43
+ public static func string(forTaskStatus status: Int) -> String {
44
+ if status == statusResume || status == statusProgress {
45
+ return "running"
46
+ } else if status == statusPause {
47
+ return "paused"
48
+ } else if status == statusSuccess {
49
+ return "success"
50
+ } else if status == statusFailure {
51
+ return "error"
52
+ } else {
53
+ // `FIRStorageTaskStatusUnknown` (0) and any other raw value
54
+ return "unknown"
55
+ }
56
+ }
57
+ }
@@ -12,6 +12,11 @@
12
12
  27A35B652268E118005BE5A8 /* RNFBStorageDownloadTask.m in Sources */ = {isa = PBXBuildFile; fileRef = 27A35B642268E118005BE5A8 /* RNFBStorageDownloadTask.m */; };
13
13
  27A35B682268E138005BE5A8 /* RNFBStorageUploadTask.m in Sources */ = {isa = PBXBuildFile; fileRef = 27A35B672268E138005BE5A8 /* RNFBStorageUploadTask.m */; };
14
14
  27A35B6B2268E1BE005BE5A8 /* RNFBStorageCommon.m in Sources */ = {isa = PBXBuildFile; fileRef = 27A35B6A2268E1BE005BE5A8 /* RNFBStorageCommon.m */; };
15
+ RNFBSTOR0000000000000001 /* RNFBStorageTaskRegistry.m in Sources */ = {isa = PBXBuildFile; fileRef = RNFBSTOR0000000000000002 /* RNFBStorageTaskRegistry.m */; };
16
+ RNFBSTOR0000000000000003 /* RNFBStorageTaskRegistryStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = RNFBSTOR0000000000000004 /* RNFBStorageTaskRegistryStorage.swift */; };
17
+ RNFBSTOR0000000000000006 /* RNFBStorageTaskStatusMapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = RNFBSTOR0000000000000007 /* RNFBStorageTaskStatusMapper.swift */; };
18
+ RNFBSTOR0000000000000008 /* RNFBStorageErrorCodeMapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = RNFBSTOR0000000000000009 /* RNFBStorageErrorCodeMapper.swift */; };
19
+ RNFBSTOR000000000000000A /* RNFBStorageErrorSnapshotDictBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = RNFBSTOR000000000000000B /* RNFBStorageErrorSnapshotDictBuilder.swift */; };
15
20
  /* End PBXBuildFile section */
16
21
 
17
22
  /* Begin PBXCopyFilesBuildPhase section */
@@ -38,6 +43,12 @@
38
43
  27A35B692268E143005BE5A8 /* RNFBStorageUploadTask.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNFBStorageUploadTask.h; sourceTree = "<group>"; };
39
44
  27A35B6A2268E1BE005BE5A8 /* RNFBStorageCommon.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNFBStorageCommon.m; sourceTree = "<group>"; };
40
45
  27A35B6C2268E1C8005BE5A8 /* RNFBStorageCommon.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNFBStorageCommon.h; sourceTree = "<group>"; };
46
+ RNFBSTOR0000000000000005 /* RNFBStorageTaskRegistry.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = RNFBStorageTaskRegistry.h; path = RNFBStorage/RNFBStorageTaskRegistry.h; sourceTree = SOURCE_ROOT; };
47
+ RNFBSTOR0000000000000002 /* RNFBStorageTaskRegistry.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = RNFBStorageTaskRegistry.m; path = RNFBStorage/RNFBStorageTaskRegistry.m; sourceTree = SOURCE_ROOT; };
48
+ RNFBSTOR0000000000000004 /* RNFBStorageTaskRegistryStorage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = RNFBStorageTaskRegistryStorage.swift; path = RNFBStorage/RNFBStorageTaskRegistryStorage.swift; sourceTree = SOURCE_ROOT; };
49
+ RNFBSTOR0000000000000007 /* RNFBStorageTaskStatusMapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = RNFBStorageTaskStatusMapper.swift; path = RNFBStorage/RNFBStorageTaskStatusMapper.swift; sourceTree = SOURCE_ROOT; };
50
+ RNFBSTOR0000000000000009 /* RNFBStorageErrorCodeMapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = RNFBStorageErrorCodeMapper.swift; path = RNFBStorage/RNFBStorageErrorCodeMapper.swift; sourceTree = SOURCE_ROOT; };
51
+ RNFBSTOR000000000000000B /* RNFBStorageErrorSnapshotDictBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = RNFBStorageErrorSnapshotDictBuilder.swift; path = RNFBStorage/RNFBStorageErrorSnapshotDictBuilder.swift; sourceTree = SOURCE_ROOT; };
41
52
  /* End PBXFileReference section */
42
53
 
43
54
  /* Begin PBXFrameworksBuildPhase section */
@@ -64,6 +75,12 @@
64
75
  children = (
65
76
  2744B98421F45429004F8E3F /* RNFBStorageModule.h */,
66
77
  2744B98521F45429004F8E3F /* RNFBStorageModule.mm */,
78
+ RNFBSTOR0000000000000005 /* RNFBStorageTaskRegistry.h */,
79
+ RNFBSTOR0000000000000002 /* RNFBStorageTaskRegistry.m */,
80
+ RNFBSTOR0000000000000004 /* RNFBStorageTaskRegistryStorage.swift */,
81
+ RNFBSTOR0000000000000007 /* RNFBStorageTaskStatusMapper.swift */,
82
+ RNFBSTOR0000000000000009 /* RNFBStorageErrorCodeMapper.swift */,
83
+ RNFBSTOR000000000000000B /* RNFBStorageErrorSnapshotDictBuilder.swift */,
67
84
  27A35B612268E0AB005BE5A8 /* RNFBStorageTask.m */,
68
85
  27A35B632268E0CD005BE5A8 /* RNFBStorageTask.h */,
69
86
  27A35B642268E118005BE5A8 /* RNFBStorageDownloadTask.m */,
@@ -142,6 +159,11 @@
142
159
  isa = PBXSourcesBuildPhase;
143
160
  buildActionMask = 2147483647;
144
161
  files = (
162
+ RNFBSTOR0000000000000003 /* RNFBStorageTaskRegistryStorage.swift in Sources */,
163
+ RNFBSTOR0000000000000006 /* RNFBStorageTaskStatusMapper.swift in Sources */,
164
+ RNFBSTOR0000000000000008 /* RNFBStorageErrorCodeMapper.swift in Sources */,
165
+ RNFBSTOR000000000000000A /* RNFBStorageErrorSnapshotDictBuilder.swift in Sources */,
166
+ RNFBSTOR0000000000000001 /* RNFBStorageTaskRegistry.m in Sources */,
145
167
  27A35B622268E0AB005BE5A8 /* RNFBStorageTask.m in Sources */,
146
168
  27A35B6B2268E1BE005BE5A8 /* RNFBStorageCommon.m in Sources */,
147
169
  2744B98621F45429004F8E3F /* RNFBStorageModule.mm in Sources */,
@@ -172,6 +194,7 @@
172
194
  CODE_SIGN_STYLE = Automatic;
173
195
  COPY_PHASE_STRIP = NO;
174
196
  DEBUG_INFORMATION_FORMAT = dwarf;
197
+ DEFINES_MODULE = YES;
175
198
  GCC_C_LANGUAGE_STANDARD = gnu11;
176
199
  GCC_DYNAMIC_NO_PIC = NO;
177
200
  GCC_OPTIMIZATION_LEVEL = 0;
@@ -188,6 +211,7 @@
188
211
  PRODUCT_NAME = "$(TARGET_NAME)";
189
212
  SDKROOT = iphoneos;
190
213
  SKIP_INSTALL = YES;
214
+ SWIFT_VERSION = 5.10;
191
215
  TARGETED_DEVICE_FAMILY = "1,2";
192
216
  };
193
217
  name = Debug;
@@ -211,6 +235,7 @@
211
235
  CODE_SIGN_STYLE = Automatic;
212
236
  COPY_PHASE_STRIP = NO;
213
237
  DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
238
+ DEFINES_MODULE = YES;
214
239
  ENABLE_NS_ASSERTIONS = NO;
215
240
  GCC_C_LANGUAGE_STANDARD = gnu11;
216
241
  GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
@@ -222,6 +247,7 @@
222
247
  PRODUCT_NAME = "$(TARGET_NAME)";
223
248
  SDKROOT = iphoneos;
224
249
  SKIP_INSTALL = YES;
250
+ SWIFT_VERSION = 5.10;
225
251
  TARGETED_DEVICE_FAMILY = "1,2";
226
252
  VALIDATE_PRODUCT = YES;
227
253
  };
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Copyright (c) 2016-present Invertase Limited & Contributors
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this library except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ #import <XCTest/XCTest.h>
18
+
19
+ #import "RNFBHandleMapStorage-Swift.inc"
20
+
21
+ @interface RNFBStorageErrorCodeMapperFacadeTests : XCTestCase
22
+ @end
23
+
24
+ @implementation RNFBStorageErrorCodeMapperFacadeTests
25
+
26
+ - (NSError *)errorWithCode:(NSInteger)code description:(NSString *)description {
27
+ return [NSError errorWithDomain:@"FIRStorageErrorDomain"
28
+ code:code
29
+ userInfo:@{NSLocalizedDescriptionKey : description}];
30
+ }
31
+
32
+ - (void)testObjCSelectorNilAndKnownCodes {
33
+ NSArray *nilPair = [RNFBStorageErrorCodeMapper codeAndMessageForError:nil];
34
+ XCTAssertEqualObjects(nilPair[0], @"unknown");
35
+ XCTAssertEqualObjects(nilPair[1], @"An unknown error has occurred.");
36
+
37
+ // FIRStorageErrorCodeObjectNotFound
38
+ NSArray *notFound = [RNFBStorageErrorCodeMapper codeAndMessageForError:[self errorWithCode:-13010
39
+ description:@"x"]];
40
+ XCTAssertEqualObjects(notFound[0], @"object-not-found");
41
+ XCTAssertEqualObjects(notFound[1], @"No object exists at the desired reference.");
42
+
43
+ // FIRStorageErrorCodeCancelled
44
+ NSArray *cancelled = [RNFBStorageErrorCodeMapper
45
+ codeAndMessageForError:[self errorWithCode:-13040 description:@"x"]];
46
+ XCTAssertEqualObjects(cancelled[0], @"cancelled");
47
+ XCTAssertEqualObjects(cancelled[1], @"User cancelled the operation.");
48
+ }
49
+
50
+ - (void)testObjCSelectorUnknownPermissionAndResponseBody {
51
+ // Permission-denied underlying → invalid-device-file-path
52
+ NSError *underlying = [NSError
53
+ errorWithDomain:NSPOSIXErrorDomain
54
+ code:1
55
+ userInfo:@{
56
+ NSLocalizedDescriptionKey : @"The operation couldn’t be completed. Permission denied"
57
+ }];
58
+ NSError *permissionError = [NSError errorWithDomain:@"FIRStorageErrorDomain"
59
+ code:-13000
60
+ userInfo:@{NSUnderlyingErrorKey : underlying}];
61
+ NSArray *permissionPair = [RNFBStorageErrorCodeMapper codeAndMessageForError:permissionError];
62
+ XCTAssertEqualObjects(permissionPair[0], @"invalid-device-file-path");
63
+ XCTAssertEqualObjects(permissionPair[1],
64
+ @"The specified device file path is invalid or is restricted.");
65
+
66
+ // ResponseBody → formatted unknown message
67
+ NSError *bodyError = [NSError errorWithDomain:@"FIRStorageErrorDomain"
68
+ code:-13000
69
+ userInfo:@{@"ResponseBody" : @"backend detail"}];
70
+ NSArray *bodyPair = [RNFBStorageErrorCodeMapper codeAndMessageForError:bodyError];
71
+ XCTAssertEqualObjects(bodyPair[0], @"unknown");
72
+ XCTAssertEqualObjects(bodyPair[1],
73
+ @"An unknown error has occurred. (underlying reason 'backend detail')");
74
+ }
75
+
76
+ - (void)testObjCSelectorDefaultKeepsLocalizedDescription {
77
+ // FIRStorageErrorCodeInvalidArgument
78
+ NSArray *pair = [RNFBStorageErrorCodeMapper
79
+ codeAndMessageForError:[self errorWithCode:-13050 description:@"keep me"]];
80
+ XCTAssertEqualObjects(pair[0], @"unknown");
81
+ XCTAssertEqualObjects(pair[1], @"keep me");
82
+ }
83
+
84
+ - (void)testFacadePublicSelectorUnchanged {
85
+ XCTAssertTrue([RNFBStorageErrorCodeMapper respondsToSelector:@selector(codeAndMessageForError:)]);
86
+ NSMethodSignature *signature =
87
+ [RNFBStorageErrorCodeMapper methodSignatureForSelector:@selector(codeAndMessageForError:)];
88
+ XCTAssertEqual(strcmp(signature.methodReturnType, @encode(id)), 0);
89
+ }
90
+
91
+ @end