@react-native-firebase/auth 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 (47) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/RNFBAuth.podspec +8 -2
  3. package/android/build.gradle +3 -0
  4. package/android/src/main/java/io/invertase/firebase/auth/NativeRNFBTurboAuth.java +1 -3
  5. package/android/src/main/java/io/invertase/firebase/auth/RNFBAuthCacheRegistry.kt +77 -0
  6. package/android/src/main/java/io/invertase/firebase/auth/RNFBAuthListenerRegistry.kt +76 -0
  7. package/android/src/test/java/io/invertase/firebase/auth/RNFBAuthCacheRegistryTest.java +12 -0
  8. package/dist/module/index.js +1 -2
  9. package/dist/module/index.js.map +1 -1
  10. package/dist/module/version.js +1 -1
  11. package/dist/typescript/lib/types/internal.d.ts +2 -3
  12. package/dist/typescript/lib/types/internal.d.ts.map +1 -1
  13. package/dist/typescript/lib/version.d.ts +1 -1
  14. package/ios/RNFBAuth/RNFBAuthCacheRegistry.m +27 -8
  15. package/ios/RNFBAuth/RNFBAuthCacheRegistryStorage.swift +53 -0
  16. package/ios/RNFBAuth/RNFBAuthErrorCodeMapper.swift +333 -0
  17. package/ios/RNFBAuth/RNFBAuthHelper.m +24 -154
  18. package/ios/RNFBAuth/RNFBAuthListenerRegistry.m +26 -26
  19. package/ios/RNFBAuth/RNFBAuthListenerRegistryStorage.swift +76 -0
  20. package/ios/RNFBAuth/RNFBAuthNullSentinelDecoder.h +40 -0
  21. package/ios/RNFBAuth/RNFBAuthNullSentinelDecoder.m +49 -0
  22. package/ios/RNFBAuth.xcodeproj/project.pbxproj +22 -0
  23. package/ios/RNFBAuthUnitTests/RNFBAuthCacheRegistryStorageTests.swift +72 -0
  24. package/ios/RNFBAuthUnitTests/RNFBAuthErrorCodeMapperTests.swift +250 -0
  25. package/ios/RNFBAuthUnitTests/RNFBAuthListenerRegistryStorageTests.swift +122 -0
  26. package/ios/RNFBAuthUnitTests/RNFBAuthNullSentinelDecodeTests.m +78 -0
  27. package/ios/RNFBAuthUnitTests/RNFBAuthUnitTests.xcodeproj/project.pbxproj +50 -0
  28. package/lib/index.ts +1 -1
  29. package/lib/types/internal.ts +2 -2
  30. package/lib/version.ts +1 -1
  31. package/package.json +4 -4
  32. package/plugin/build/index.js +4 -0
  33. package/plugin/build/ios/index.d.ts +2 -1
  34. package/plugin/build/ios/index.js +3 -1
  35. package/plugin/build/ios/openUrlFix.js +12 -0
  36. package/plugin/build/ios/sceneDelegate.d.ts +34 -0
  37. package/plugin/build/ios/sceneDelegate.js +127 -0
  38. package/plugin/build/ios/sceneLifecycle.d.ts +32 -0
  39. package/plugin/build/ios/sceneLifecycle.js +115 -0
  40. package/plugin/src/index.ts +9 -1
  41. package/plugin/src/ios/index.ts +2 -1
  42. package/plugin/src/ios/openUrlFix.ts +15 -0
  43. package/plugin/src/ios/sceneDelegate.ts +159 -0
  44. package/plugin/src/ios/sceneLifecycle.ts +134 -0
  45. package/plugin/tsconfig.tsbuildinfo +1 -1
  46. package/android/src/main/java/io/invertase/firebase/auth/RNFBAuthCacheRegistry.java +0 -66
  47. package/android/src/main/java/io/invertase/firebase/auth/RNFBAuthListenerRegistry.java +0 -76
@@ -0,0 +1,134 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+
4
+ // Directories that never contain the app's own scene delegate but are expensive to walk.
5
+ const IGNORED_DIRECTORIES = new Set(['Pods', 'build', 'node_modules', 'DerivedData', '.git']);
6
+
7
+ const APP_DELEGATE_NAMES = new Set(['AppDelegate.swift', 'AppDelegate.m', 'AppDelegate.mm']);
8
+
9
+ export type SceneDelegateResolution =
10
+ | { kind: 'found'; path: string }
11
+ | { kind: 'missing' }
12
+ | { kind: 'ambiguous'; candidates: string[] };
13
+
14
+ /**
15
+ * Walk `platformProjectRoot` (typically `ios/`) and collect matching file paths, skipping
16
+ * CocoaPods / build / Xcode bundle trees.
17
+ */
18
+ function collectFilesNamed(
19
+ platformProjectRoot: string,
20
+ fileNamePredicate: (name: string) => boolean,
21
+ ): string[] {
22
+ if (!platformProjectRoot || !fs.existsSync(platformProjectRoot)) {
23
+ return [];
24
+ }
25
+
26
+ const matches: string[] = [];
27
+ const queue: string[] = [platformProjectRoot];
28
+ while (queue.length > 0) {
29
+ const directory = queue.shift() as string;
30
+
31
+ let entries: fs.Dirent[];
32
+ try {
33
+ entries = fs.readdirSync(directory, { withFileTypes: true });
34
+ } catch {
35
+ continue;
36
+ }
37
+
38
+ for (const entry of entries) {
39
+ const entryPath = path.join(directory, entry.name);
40
+ if (entry.isDirectory()) {
41
+ if (
42
+ !IGNORED_DIRECTORIES.has(entry.name) &&
43
+ !entry.name.endsWith('.xcodeproj') &&
44
+ !entry.name.endsWith('.xcworkspace')
45
+ ) {
46
+ queue.push(entryPath);
47
+ }
48
+ } else if (fileNamePredicate(entry.name)) {
49
+ matches.push(entryPath);
50
+ }
51
+ }
52
+ }
53
+
54
+ return matches.sort();
55
+ }
56
+
57
+ /**
58
+ * Resolve the application target's `SceneDelegate.swift` deterministically.
59
+ *
60
+ * - Zero candidates → missing.
61
+ * - Exactly one candidate → that file (Expo nested layout or bare-expo `ios/` root).
62
+ * - Multiple candidates → prefer the one co-located with an `AppDelegate.*`; if that is not
63
+ * unique, reject as ambiguous rather than patching a distractor (extension / secondary target).
64
+ */
65
+ export function resolveSceneDelegateFile(platformProjectRoot: string): SceneDelegateResolution {
66
+ const candidates = collectFilesNamed(platformProjectRoot, name => name === 'SceneDelegate.swift');
67
+ if (candidates.length === 0) {
68
+ return { kind: 'missing' };
69
+ }
70
+ if (candidates.length === 1) {
71
+ return { kind: 'found', path: candidates[0] };
72
+ }
73
+
74
+ const appDelegateDirs = new Set(
75
+ collectFilesNamed(platformProjectRoot, name => APP_DELEGATE_NAMES.has(name)).map(p =>
76
+ path.dirname(p),
77
+ ),
78
+ );
79
+ const coLocated = candidates.filter(candidate => appDelegateDirs.has(path.dirname(candidate)));
80
+ if (coLocated.length === 1) {
81
+ return { kind: 'found', path: coLocated[0] };
82
+ }
83
+
84
+ return { kind: 'ambiguous', candidates };
85
+ }
86
+
87
+ /**
88
+ * Locate the app's `SceneDelegate.swift`, or `null` when none exists or resolution is ambiguous.
89
+ *
90
+ * Expo SDK 58 writes it next to `AppDelegate.swift` (`ios/<ProjectName>/SceneDelegate.swift`), but
91
+ * `apps/bare-expo` keeps it at `ios/SceneDelegate.swift`, so search rather than assume a layout.
92
+ */
93
+ export function findSceneDelegateFile(platformProjectRoot: string): string | null {
94
+ const resolution = resolveSceneDelegateFile(platformProjectRoot);
95
+ return resolution.kind === 'found' ? resolution.path : null;
96
+ }
97
+
98
+ /**
99
+ * Detect a `UIApplicationSceneManifest` entry in the app's `Info.plist`.
100
+ *
101
+ * Independent of `findSceneDelegateFile`: a project can declare the scene life cycle without shipping
102
+ * a `SceneDelegate.swift` the plugin can patch, and callers need to tell the two cases apart.
103
+ */
104
+ export function infoPlistDeclaresSceneManifest(platformProjectRoot: string): boolean {
105
+ if (!platformProjectRoot) {
106
+ return false;
107
+ }
108
+
109
+ let entries: fs.Dirent[];
110
+ try {
111
+ entries = fs.readdirSync(platformProjectRoot, { withFileTypes: true });
112
+ } catch {
113
+ return false;
114
+ }
115
+
116
+ for (const entry of entries) {
117
+ if (!entry.isDirectory() || IGNORED_DIRECTORIES.has(entry.name)) {
118
+ continue;
119
+ }
120
+ const infoPlist = path.join(platformProjectRoot, entry.name, 'Info.plist');
121
+ try {
122
+ if (
123
+ fs.existsSync(infoPlist) &&
124
+ fs.readFileSync(infoPlist, 'utf-8').includes('UIApplicationSceneManifest')
125
+ ) {
126
+ return true;
127
+ }
128
+ } catch {
129
+ continue;
130
+ }
131
+ }
132
+
133
+ return false;
134
+ }
@@ -1 +1 @@
1
- {"root":["./src/app.plugin.ts","./src/index.ts","./src/pluginconfig.ts","./src/ios/index.ts","./src/ios/openurlfix.ts","./src/ios/urltypes.ts"],"version":"6.0.3"}
1
+ {"root":["./src/app.plugin.ts","./src/index.ts","./src/pluginconfig.ts","./src/ios/index.ts","./src/ios/openurlfix.ts","./src/ios/scenedelegate.ts","./src/ios/scenelifecycle.ts","./src/ios/urltypes.ts"],"version":"6.0.3"}
@@ -1,66 +0,0 @@
1
- package io.invertase.firebase.auth;
2
-
3
- /*
4
- * Copyright (c) 2016-present Invertase Limited & Contributors
5
- *
6
- * Licensed under the Apache License, Version 2.0 (the "License");
7
- * you may not use this library except in compliance with the License.
8
- * You may obtain a copy of the License at
9
- *
10
- * http://www.apache.org/licenses/LICENSE-2.0
11
- *
12
- * Unless required by applicable law or agreed to in writing, software
13
- * distributed under the License is distributed on an "AS IS" BASIS,
14
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
- * See the License for the specific language governing permissions and
16
- * limitations under the License.
17
- *
18
- */
19
-
20
- import io.invertase.firebase.common.RNFBHandleCollisionException;
21
- import io.invertase.firebase.common.RNFBHandleMap;
22
-
23
- /**
24
- * Credential / MFA cache map (data only — no SDK cancel). Unique {@link #put}; callers that
25
- * previously HashMap-upserted use {@link #putReplacing} (atomic last wins). Peek with {@link #get};
26
- * remove with {@link #take}; invalidate with {@link #clear}.
27
- *
28
- * <p><strong>Collision vs prior HashMap.put upsert:</strong> unique {@link #put} throws; replace at
29
- * call sites is {@link #putReplacing} (last wins). {@link #putOrDiscard} keeps the first mapping.
30
- */
31
- final class RNFBAuthCacheRegistry<V> {
32
- private final RNFBHandleMap<String, V> map = new RNFBHandleMap<>();
33
-
34
- void put(String key, V value) throws RNFBHandleCollisionException {
35
- map.put(key, value);
36
- }
37
-
38
- /**
39
- * Unique put. On collision, leave the existing mapping and discard the incoming value (data
40
- * only).
41
- *
42
- * @return true if stored
43
- */
44
- boolean putOrDiscard(String key, V value) {
45
- return map.putIfAbsent(key, value);
46
- }
47
-
48
- /**
49
- * Atomic replace (last wins). Preserves prior HashMap {@code put} upsert. Taken value discarded.
50
- */
51
- void putReplacing(String key, V value) {
52
- map.putReplacing(key, value);
53
- }
54
-
55
- V get(String key) {
56
- return map.get(key);
57
- }
58
-
59
- V take(String key) {
60
- return map.take(key);
61
- }
62
-
63
- void clear() {
64
- map.takeAll();
65
- }
66
- }
@@ -1,76 +0,0 @@
1
- package io.invertase.firebase.auth;
2
-
3
- /*
4
- * Copyright (c) 2016-present Invertase Limited & Contributors
5
- *
6
- * Licensed under the Apache License, Version 2.0 (the "License");
7
- * you may not use this library except in compliance with the License.
8
- * You may obtain a copy of the License at
9
- *
10
- * http://www.apache.org/licenses/LICENSE-2.0
11
- *
12
- * Unless required by applicable law or agreed to in writing, software
13
- * distributed under the License is distributed on an "AS IS" BASIS,
14
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
- * See the License for the specific language governing permissions and
16
- * limitations under the License.
17
- *
18
- */
19
-
20
- import io.invertase.firebase.common.RNFBHandleCollisionException;
21
- import io.invertase.firebase.common.RNFBHandleMap;
22
- import java.util.List;
23
-
24
- /**
25
- * Auth-state / id-token listener map. Unique {@link #put} / {@link #putOrDiscard}; callers {@link
26
- * #take} or {@link #takeAllAndRemove} then {@code remove()} outside the HandleMap lock.
27
- * Skip-if-registered is {@code get(appName) != null}.
28
- */
29
- final class RNFBAuthListenerRegistry {
30
- private final RNFBHandleMap<String, AuthListenerHandle> map = new RNFBHandleMap<>();
31
-
32
- void put(String appName, AuthListenerHandle handle) throws RNFBHandleCollisionException {
33
- map.put(appName, handle);
34
- }
35
-
36
- /**
37
- * Unique put. On collision, {@code remove()} the incoming handle and leave the existing mapping.
38
- *
39
- * @return true if stored
40
- */
41
- boolean putOrDiscard(String appName, AuthListenerHandle handle) {
42
- try {
43
- map.put(appName, handle);
44
- return true;
45
- } catch (RNFBHandleCollisionException collision) {
46
- if (handle != null) {
47
- handle.remove();
48
- }
49
- return false;
50
- }
51
- }
52
-
53
- AuthListenerHandle get(String appName) {
54
- return map.get(appName);
55
- }
56
-
57
- AuthListenerHandle take(String appName) {
58
- return map.take(appName);
59
- }
60
-
61
- void takeAndRemove(String appName) {
62
- AuthListenerHandle handle = map.take(appName);
63
- if (handle != null) {
64
- handle.remove();
65
- }
66
- }
67
-
68
- void takeAllAndRemove() {
69
- List<AuthListenerHandle> remaining = map.takeAll();
70
- for (AuthListenerHandle handle : remaining) {
71
- if (handle != null) {
72
- handle.remove();
73
- }
74
- }
75
- }
76
- }