@react-native-firebase/auth 21.6.1 → 21.7.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.
@@ -0,0 +1,150 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.multiline_appDelegateOpenUrlInsertionPointAfter = exports.appDelegateOpenUrlInsertionPointAfter = exports.withIosCaptchaOpenUrlFix = void 0;
4
+ exports.shouldApplyIosOpenUrlFix = shouldApplyIosOpenUrlFix;
5
+ exports.withOpenUrlFixForAppDelegate = withOpenUrlFixForAppDelegate;
6
+ exports.modifyObjcAppDelegate = modifyObjcAppDelegate;
7
+ exports.isFirebaseSwizzlingDisabled = isFirebaseSwizzlingDisabled;
8
+ exports.ensureFirebaseSwizzlingIsEnabled = ensureFirebaseSwizzlingIsEnabled;
9
+ const config_plugins_1 = require("@expo/config-plugins");
10
+ const generateCode_1 = require("@expo/config-plugins/build/utils/generateCode");
11
+ const withIosCaptchaOpenUrlFix = (config, props) => {
12
+ // check configuration
13
+ if (!shouldApplyIosOpenUrlFix({ config, props })) {
14
+ return config;
15
+ }
16
+ // check that swizzling is enabled; otherwise patch must be customized and applied manually
17
+ (0, config_plugins_1.withInfoPlist)(config, config => {
18
+ ensureFirebaseSwizzlingIsEnabled(config);
19
+ return config;
20
+ });
21
+ // apply patch
22
+ return (0, config_plugins_1.withAppDelegate)(config, config => {
23
+ return withOpenUrlFixForAppDelegate({ config, props });
24
+ });
25
+ };
26
+ exports.withIosCaptchaOpenUrlFix = withIosCaptchaOpenUrlFix;
27
+ // Interpret the plugin config to determine whether this fix should be applied
28
+ function shouldApplyIosOpenUrlFix({ config, props, }) {
29
+ const flag = props?.ios?.captchaOpenUrlFix;
30
+ if (flag === undefined || flag === 'default') {
31
+ // by default, apply the fix whenever 'expo-router' is detected in the same project
32
+ return isPluginEnabled(config, 'expo-router');
33
+ }
34
+ else if (flag === true || flag === false) {
35
+ const isEnabled = flag;
36
+ return isEnabled;
37
+ }
38
+ else {
39
+ throw new Error(`Unexpected value for 'captchaOpenUrlFix' config option`);
40
+ }
41
+ }
42
+ function withOpenUrlFixForAppDelegate({ config, props, }) {
43
+ const { language, contents } = config.modResults;
44
+ const configValue = props?.ios?.captchaOpenUrlFix || 'default';
45
+ if (['objc', 'objcpp'].includes(language)) {
46
+ const newContents = modifyObjcAppDelegate(contents);
47
+ if (newContents === null) {
48
+ if (configValue === true) {
49
+ throw new Error("Failed to apply iOS openURL fix because no 'openURL' method was found");
50
+ }
51
+ else {
52
+ config_plugins_1.WarningAggregator.addWarningIOS('@react-native-firebase/auth', "Skipping iOS openURL fix because no 'openURL' method was found");
53
+ return config;
54
+ }
55
+ }
56
+ else {
57
+ if (configValue === 'default') {
58
+ config_plugins_1.WarningAggregator.addWarningIOS('@react-native-firebase/auth', 'modifying iOS AppDelegate openURL method to ignore firebaseauth reCAPTCHA redirect URLs');
59
+ }
60
+ return {
61
+ ...config,
62
+ modResults: {
63
+ ...config.modResults,
64
+ contents: newContents,
65
+ },
66
+ };
67
+ }
68
+ }
69
+ else {
70
+ // TODO: Support Swift
71
+ throw new Error(`Don't know how to apply openUrlFix to AppDelegate of language "${language}"`);
72
+ }
73
+ }
74
+ const skipOpenUrlForFirebaseAuthBlock = `\
75
+ if ([url.host caseInsensitiveCompare:@"firebaseauth"] == NSOrderedSame) {
76
+ // invocations for Firebase Auth are handled elsewhere and should not be forwarded to Expo Router
77
+ return NO;
78
+ }\
79
+ `;
80
+ // NOTE: `mergeContents()` requires that this pattern not match newlines
81
+ exports.appDelegateOpenUrlInsertionPointAfter = /-\s*\(\s*BOOL\s*\)\s*application\s*:\s*\(\s*UIApplication\s*\*\s*\)\s*application\s+openURL\s*:\s*\(\s*NSURL\s*\*\s*\)\s*url\s+options\s*:\s*\(\s*NSDictionary\s*<\s*UIApplicationOpenURLOptionsKey\s*,\s*id\s*>\s*\*\s*\)\s*options\s*/; // 🙈
82
+ exports.multiline_appDelegateOpenUrlInsertionPointAfter = new RegExp(exports.appDelegateOpenUrlInsertionPointAfter.source + '\\s*{\\s*\\n');
83
+ // Returns contents of new AppDelegate with modification applied, or returns null if this patch is not applicable because the AppDelegate doesn't have an 'openURL' method to handle deep links.
84
+ function modifyObjcAppDelegate(contents) {
85
+ const pattern = exports.appDelegateOpenUrlInsertionPointAfter;
86
+ const multilinePattern = exports.multiline_appDelegateOpenUrlInsertionPointAfter;
87
+ const fullMatch = contents.match(multilinePattern);
88
+ if (!fullMatch) {
89
+ if (contents.match(pattern)) {
90
+ throw new Error("Failed to find insertion point; expected newline after '{'");
91
+ }
92
+ else if (contents.match(/openURL\s*:/)) {
93
+ throw new Error([
94
+ "Failed to apply 'captchaOpenUrlFix' but detected 'openURL' method.",
95
+ "Please manually apply the fix to your AppDelegate's openURL method,",
96
+ "then update your app.config.json by configuring the '@react-native-firebase/auth' plugin",
97
+ 'to set `captchaOpenUrlFix: false`.',
98
+ ].join(' '));
99
+ }
100
+ else {
101
+ // openURL method was not found in AppDelegate
102
+ return null;
103
+ }
104
+ }
105
+ const fullMatchNumLines = fullMatch[0].split('\n').length;
106
+ const offset = fullMatchNumLines - 1;
107
+ if (offset < 0) {
108
+ throw new Error(`Failed to find insertion point; fullMatchNumLines=${fullMatchNumLines}`);
109
+ }
110
+ return (0, generateCode_1.mergeContents)({
111
+ tag: '@react-native-firebase/auth-openURL',
112
+ src: contents,
113
+ newSrc: skipOpenUrlForFirebaseAuthBlock,
114
+ anchor: exports.appDelegateOpenUrlInsertionPointAfter,
115
+ offset,
116
+ comment: '//',
117
+ }).contents;
118
+ }
119
+ // Search the ExpoConfig plugins array to see if `pluginName` is present
120
+ function isPluginEnabled(config, pluginName) {
121
+ if (config.plugins === undefined) {
122
+ return false;
123
+ }
124
+ return config.plugins.some((plugin) => {
125
+ if (plugin === pluginName) {
126
+ return true;
127
+ }
128
+ else if (Array.isArray(plugin) && plugin.length >= 1 && plugin[0] === pluginName) {
129
+ return true;
130
+ }
131
+ else {
132
+ return false;
133
+ }
134
+ });
135
+ }
136
+ function isFirebaseSwizzlingDisabled(config) {
137
+ return config.ios?.infoPlist?.['FirebaseAppDelegateProxyEnabled'] === false;
138
+ }
139
+ function ensureFirebaseSwizzlingIsEnabled(config) {
140
+ if (isFirebaseSwizzlingDisabled(config)) {
141
+ throw new Error([
142
+ 'Your app has disabled swizzling by setting FirebaseAppDelegateProxyEnabled=false in its Info.plist.',
143
+ "Please update your app.config.json to configure the '@react-native-firebase/auth' plugin to set `captchaOpenUrlFix: false`",
144
+ 'and see https://firebase.google.com/docs/auth/ios/phone-auth#appendix:-using-phone-sign-in-without-swizzling for instructions.',
145
+ ].join(' '));
146
+ }
147
+ else {
148
+ return true;
149
+ }
150
+ }
@@ -1,5 +1,6 @@
1
1
  import { ConfigPlugin, IOSConfig, ExportedConfigWithProps } from '@expo/config-plugins';
2
- export declare const withIosCaptchaUrlTypes: ConfigPlugin;
2
+ import { PluginConfigType } from '../pluginConfig';
3
+ export declare const withIosCaptchaUrlTypes: ConfigPlugin<PluginConfigType>;
3
4
  export declare function setUrlTypesForCaptcha({ config, }: {
4
5
  config: ExportedConfigWithProps<IOSConfig.InfoPlist>;
5
6
  }): ExportedConfigWithProps<IOSConfig.InfoPlist>;
@@ -0,0 +1,6 @@
1
+ export interface PluginConfigType {
2
+ ios?: PluginConfigTypeIos;
3
+ }
4
+ export interface PluginConfigTypeIos {
5
+ captchaOpenUrlFix?: undefined | boolean | 'default';
6
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,14 +1,16 @@
1
1
  import { ConfigPlugin, withPlugins, createRunOncePlugin } from '@expo/config-plugins';
2
2
 
3
- import { withIosCaptchaUrlTypes } from './ios';
3
+ import { withIosCaptchaUrlTypes, withIosCaptchaOpenUrlFix } from './ios';
4
+ import { PluginConfigType } from './pluginConfig';
4
5
 
5
6
  /**
6
7
  * A config plugin for configuring `@react-native-firebase/auth`
7
8
  */
8
- const withRnFirebaseAuth: ConfigPlugin = config => {
9
+ const withRnFirebaseAuth: ConfigPlugin<PluginConfigType> = (config, props) => {
9
10
  return withPlugins(config, [
10
11
  // iOS
11
- withIosCaptchaUrlTypes,
12
+ [withIosCaptchaUrlTypes, props],
13
+ [withIosCaptchaOpenUrlFix, props],
12
14
  ]);
13
15
  };
14
16
 
@@ -1,3 +1,4 @@
1
1
  import { withIosCaptchaUrlTypes } from './urlTypes';
2
+ import { withIosCaptchaOpenUrlFix } from './openUrlFix';
2
3
 
3
- export { withIosCaptchaUrlTypes };
4
+ export { withIosCaptchaUrlTypes, withIosCaptchaOpenUrlFix };
@@ -0,0 +1,186 @@
1
+ import {
2
+ ConfigPlugin,
3
+ withAppDelegate,
4
+ withInfoPlist,
5
+ ExportedConfigWithProps,
6
+ WarningAggregator,
7
+ } from '@expo/config-plugins';
8
+ import type { ExpoConfig } from '@expo/config/build/Config.types';
9
+ import type { AppDelegateProjectFile } from '@expo/config-plugins/build/ios/Paths';
10
+ import type { InfoPlist } from '@expo/config-plugins/build/ios/IosConfig.types';
11
+ import { mergeContents } from '@expo/config-plugins/build/utils/generateCode';
12
+ import { PluginConfigType } from '../pluginConfig';
13
+
14
+ export const withIosCaptchaOpenUrlFix: ConfigPlugin<PluginConfigType> = (
15
+ config: ExpoConfig,
16
+ props?: PluginConfigType,
17
+ ) => {
18
+ // check configuration
19
+ if (!shouldApplyIosOpenUrlFix({ config, props })) {
20
+ return config;
21
+ }
22
+
23
+ // check that swizzling is enabled; otherwise patch must be customized and applied manually
24
+ withInfoPlist(config, config => {
25
+ ensureFirebaseSwizzlingIsEnabled(config);
26
+ return config;
27
+ });
28
+
29
+ // apply patch
30
+ return withAppDelegate(config, config => {
31
+ return withOpenUrlFixForAppDelegate({ config, props });
32
+ });
33
+ };
34
+
35
+ // Interpret the plugin config to determine whether this fix should be applied
36
+ export function shouldApplyIosOpenUrlFix({
37
+ config,
38
+ props,
39
+ }: {
40
+ config: ExpoConfig;
41
+ props?: PluginConfigType;
42
+ }): boolean {
43
+ const flag = props?.ios?.captchaOpenUrlFix;
44
+ if (flag === undefined || flag === 'default') {
45
+ // by default, apply the fix whenever 'expo-router' is detected in the same project
46
+ return isPluginEnabled(config, 'expo-router');
47
+ } else if (flag === true || flag === false) {
48
+ const isEnabled: boolean = flag;
49
+ return isEnabled;
50
+ } else {
51
+ throw new Error(`Unexpected value for 'captchaOpenUrlFix' config option`);
52
+ }
53
+ }
54
+
55
+ export function withOpenUrlFixForAppDelegate({
56
+ config,
57
+ props,
58
+ }: {
59
+ config: ExportedConfigWithProps<AppDelegateProjectFile>;
60
+ props?: PluginConfigType;
61
+ }) {
62
+ const { language, contents } = config.modResults;
63
+ const configValue = props?.ios?.captchaOpenUrlFix || 'default';
64
+
65
+ if (['objc', 'objcpp'].includes(language)) {
66
+ const newContents = modifyObjcAppDelegate(contents);
67
+ if (newContents === null) {
68
+ if (configValue === true) {
69
+ throw new Error("Failed to apply iOS openURL fix because no 'openURL' method was found");
70
+ } else {
71
+ WarningAggregator.addWarningIOS(
72
+ '@react-native-firebase/auth',
73
+ "Skipping iOS openURL fix because no 'openURL' method was found",
74
+ );
75
+ return config;
76
+ }
77
+ } else {
78
+ if (configValue === 'default') {
79
+ WarningAggregator.addWarningIOS(
80
+ '@react-native-firebase/auth',
81
+ 'modifying iOS AppDelegate openURL method to ignore firebaseauth reCAPTCHA redirect URLs',
82
+ );
83
+ }
84
+ return {
85
+ ...config,
86
+ modResults: {
87
+ ...config.modResults,
88
+ contents: newContents,
89
+ },
90
+ };
91
+ }
92
+ } else {
93
+ // TODO: Support Swift
94
+ throw new Error(`Don't know how to apply openUrlFix to AppDelegate of language "${language}"`);
95
+ }
96
+ }
97
+
98
+ const skipOpenUrlForFirebaseAuthBlock: string = `\
99
+ if ([url.host caseInsensitiveCompare:@"firebaseauth"] == NSOrderedSame) {
100
+ // invocations for Firebase Auth are handled elsewhere and should not be forwarded to Expo Router
101
+ return NO;
102
+ }\
103
+ `;
104
+
105
+ // NOTE: `mergeContents()` requires that this pattern not match newlines
106
+ export const appDelegateOpenUrlInsertionPointAfter: RegExp =
107
+ /-\s*\(\s*BOOL\s*\)\s*application\s*:\s*\(\s*UIApplication\s*\*\s*\)\s*application\s+openURL\s*:\s*\(\s*NSURL\s*\*\s*\)\s*url\s+options\s*:\s*\(\s*NSDictionary\s*<\s*UIApplicationOpenURLOptionsKey\s*,\s*id\s*>\s*\*\s*\)\s*options\s*/; // 🙈
108
+
109
+ export const multiline_appDelegateOpenUrlInsertionPointAfter = new RegExp(
110
+ appDelegateOpenUrlInsertionPointAfter.source + '\\s*{\\s*\\n',
111
+ );
112
+
113
+ // Returns contents of new AppDelegate with modification applied, or returns null if this patch is not applicable because the AppDelegate doesn't have an 'openURL' method to handle deep links.
114
+ export function modifyObjcAppDelegate(contents: string): string | null {
115
+ const pattern = appDelegateOpenUrlInsertionPointAfter;
116
+ const multilinePattern = multiline_appDelegateOpenUrlInsertionPointAfter;
117
+ const fullMatch = contents.match(multilinePattern);
118
+ if (!fullMatch) {
119
+ if (contents.match(pattern)) {
120
+ throw new Error("Failed to find insertion point; expected newline after '{'");
121
+ } else if (contents.match(/openURL\s*:/)) {
122
+ throw new Error(
123
+ [
124
+ "Failed to apply 'captchaOpenUrlFix' but detected 'openURL' method.",
125
+ "Please manually apply the fix to your AppDelegate's openURL method,",
126
+ "then update your app.config.json by configuring the '@react-native-firebase/auth' plugin",
127
+ 'to set `captchaOpenUrlFix: false`.',
128
+ ].join(' '),
129
+ );
130
+ } else {
131
+ // openURL method was not found in AppDelegate
132
+ return null;
133
+ }
134
+ }
135
+ const fullMatchNumLines = fullMatch[0].split('\n').length;
136
+ const offset = fullMatchNumLines - 1;
137
+ if (offset < 0) {
138
+ throw new Error(`Failed to find insertion point; fullMatchNumLines=${fullMatchNumLines}`);
139
+ }
140
+ return mergeContents({
141
+ tag: '@react-native-firebase/auth-openURL',
142
+ src: contents,
143
+ newSrc: skipOpenUrlForFirebaseAuthBlock,
144
+ anchor: appDelegateOpenUrlInsertionPointAfter,
145
+ offset,
146
+ comment: '//',
147
+ }).contents;
148
+ }
149
+
150
+ export type ExpoConfigPluginEntry = string | [] | [string] | [string, any];
151
+
152
+ // Search the ExpoConfig plugins array to see if `pluginName` is present
153
+ function isPluginEnabled(config: ExpoConfig, pluginName: string): boolean {
154
+ if (config.plugins === undefined) {
155
+ return false;
156
+ }
157
+ return config.plugins.some((plugin: ExpoConfigPluginEntry) => {
158
+ if (plugin === pluginName) {
159
+ return true;
160
+ } else if (Array.isArray(plugin) && plugin.length >= 1 && plugin[0] === pluginName) {
161
+ return true;
162
+ } else {
163
+ return false;
164
+ }
165
+ });
166
+ }
167
+
168
+ export function isFirebaseSwizzlingDisabled(config: ExportedConfigWithProps<InfoPlist>): boolean {
169
+ return config.ios?.infoPlist?.['FirebaseAppDelegateProxyEnabled'] === false;
170
+ }
171
+
172
+ export function ensureFirebaseSwizzlingIsEnabled(
173
+ config: ExportedConfigWithProps<InfoPlist>,
174
+ ): boolean {
175
+ if (isFirebaseSwizzlingDisabled(config)) {
176
+ throw new Error(
177
+ [
178
+ 'Your app has disabled swizzling by setting FirebaseAppDelegateProxyEnabled=false in its Info.plist.',
179
+ "Please update your app.config.json to configure the '@react-native-firebase/auth' plugin to set `captchaOpenUrlFix: false`",
180
+ 'and see https://firebase.google.com/docs/auth/ios/phone-auth#appendix:-using-phone-sign-in-without-swizzling for instructions.',
181
+ ].join(' '),
182
+ );
183
+ } else {
184
+ return true;
185
+ }
186
+ }
@@ -7,9 +7,10 @@ import {
7
7
  import fs from 'fs';
8
8
  import path from 'path';
9
9
  import plist from 'plist';
10
+ import { PluginConfigType } from '../pluginConfig';
10
11
 
11
12
  // does this for you: https://firebase.google.com/docs/auth/ios/phone-auth#enable-phone-number-sign-in-for-your-firebase-project
12
- export const withIosCaptchaUrlTypes: ConfigPlugin = config => {
13
+ export const withIosCaptchaUrlTypes: ConfigPlugin<PluginConfigType> = config => {
13
14
  return withInfoPlist(config, config => {
14
15
  return setUrlTypesForCaptcha({ config });
15
16
  });
@@ -0,0 +1,7 @@
1
+ export interface PluginConfigType {
2
+ ios?: PluginConfigTypeIos;
3
+ }
4
+
5
+ export interface PluginConfigTypeIos {
6
+ captchaOpenUrlFix?: undefined | boolean | 'default';
7
+ }
@@ -1 +1 @@
1
- {"root":["./src/index.ts","./src/ios/index.ts","./src/ios/urlTypes.ts"],"version":"5.6.2"}
1
+ {"root":["./src/index.ts","./src/pluginConfig.ts","./src/ios/index.ts","./src/ios/openUrlFix.ts","./src/ios/urlTypes.ts"],"version":"5.6.2"}