From 4de939a5248ca23c1f26fe8ad296f836b6a23f0b Mon Sep 17 00:00:00 2001 From: Mai Trung Duc Date: Tue, 27 Feb 2024 00:04:04 +0800 Subject: [PATCH] feat: add plugin for Expo project --- README.md | 148 +++++++++++- android/build.gradle | 4 +- example/app.config.js | 62 +++++ example/zalokitStrings.js | 213 +++++++++++++++++ package.json | 31 ++- src/expo/plugins/android/withAndroid.ts | 161 +++++++++++++ .../plugins/android/withMainActivityDebug.ts | 10 + .../android/withMainApplicationDebug.ts | 10 + src/expo/plugins/ios/withAppDelegateDebug.ts | 10 + src/expo/plugins/ios/withIOS.ts | 59 +++++ src/expo/plugins/withZaloKit.ts | 33 +++ yarn.lock | 222 +++++++++++++++++- 12 files changed, 952 insertions(+), 11 deletions(-) create mode 100644 example/app.config.js create mode 100644 example/zalokitStrings.js create mode 100644 src/expo/plugins/android/withAndroid.ts create mode 100644 src/expo/plugins/android/withMainActivityDebug.ts create mode 100644 src/expo/plugins/android/withMainApplicationDebug.ts create mode 100644 src/expo/plugins/ios/withAppDelegateDebug.ts create mode 100644 src/expo/plugins/ios/withIOS.ts create mode 100644 src/expo/plugins/withZaloKit.ts diff --git a/README.md b/README.md index 618c485..195eeed 100644 --- a/README.md +++ b/README.md @@ -76,7 +76,8 @@ After that you'll get your Zalo App Key, and you'll need to use it for next sect **Note 1**: you're recommended to turn your Zalo app to `Live Mode` in order to get full functionalities. -## iOS +## React Native CLI Project +### iOS Run the following command to setup for iOS: ``` npx pod-install ios @@ -160,7 +161,7 @@ Next, still under tab `Info` -> URL Types -> Click `+` to add new with identifie -## Android +### Android 1. Open `android/build.gradle`, and check the `minSdkVersion` if it's < 18 then make it 18 otherwise leave default: ``` buildscript { @@ -172,7 +173,11 @@ buildscript { ... ``` -2. Open `android/app/src/main/java//MainActivity.java`, and add the following: +2. Open `android/app/src/main/java//MainActivity.(java|kt)`, and add the following: + +
+Java + ```java import com.zing.zalo.zalosdk.oauth.ZaloSDK; import android.content.Intent; @@ -189,7 +194,33 @@ public class MainActivity extends ReactActivity { } ``` -3. After that, open `android/app/src/main/java//MainApplication.java`, and add the following: +
+ +
+Kotlin + +```kotlin +import com.zing.zalo.zalosdk.oauth.ZaloSDK; +import android.content.Intent; + +class MainActivity : ReactActivity() { + ... + + // override method below (create it if not exist) + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + super.onActivityResult(requestCode, resultCode, data) + ZaloSDK.Instance.onActivityResult(this, requestCode, resultCode, data) + } +} +``` + +
+ +3. After that, open `android/app/src/main/java//MainApplication.(java|kt)`, and add the following: + +
+Java + ```java import com.zing.zalo.zalosdk.oauth.ZaloSDKApplication; @@ -205,6 +236,26 @@ public class MainApplication extends Application implements ReactApplication { } ``` +
+ +
+Kotlin + +```kotlin +import com.zing.zalo.zalosdk.oauth.ZaloSDKApplication; + +class MainApplication : Application(), ReactApplication { + ... + + override fun onCreate() { + ... + ZaloSDKApplication.wrap(this); + } +} +``` + +
+ 4. Add `appID` to `android/app/src/main/res/values/strings.xml` ```xml @@ -247,6 +298,95 @@ public class MainApplication extends Application implements ReactApplication { -keep enum com.zing.zalo.**{ *; } -keep interface com.zing.zalo.**{ *; } ``` +## Expo project (managed workflow) +
+Expand to view + +If you're using `app.json` then you need to change to use `app.config.js`. For example: +```js +// app.config.js + +module.exports = { /* content of your app.json */} +``` + +Next to in order to safely update AppDelete, MainActivity and MainApplication so that it won't conflict with other plugins, we'll log the content of them out, then add custom code. Finally pass content of the files as strings to Zalo Kit Expo plugin. + +First in your `app.config.js` > `plugins`, let's log content of AppDelete, MainActivity and MainApplication. +```js +module.exports = { + expo: { + // ...other configs + plugins: [ + ['react-native-zalo-kit/expo/withAppDelegateDebug'], + ['react-native-zalo-kit/expo/withMainActivityDebug'], + ['react-native-zalo-kit/expo/withMainApplicationDebug'] + ], + }, +}; + +``` +Now run: +```shell +npx expo prebuild --clean +``` +You'll see actual content of the 3 files in console, copy each of them and store in a single file name `zalokitStrings.js` at root folder project, then you do update each file exactly same as with RN CLI project (remember to update the zalo app ID in `AppDelegate`) + +The final structure should look like this: + +```js +const appDelegateContent = `` +const mainActivityContent = `` +const mainApplicationContent = `` + +module.exports = { + appDelegateContent, + mainActivityContent, + mainApplicationContent +}; +``` +Next, import those content into `app.config.js` +```js +const { + appDelegateContent, + mainActivityContent, + mainApplicationContent, +} = require("./zalokitStrings"); + +module.exports = { + expo: { + // other configs + plugins: [ + [ + "expo-build-properties", // remember to install this package + { + android: { + extraProguardRules: ` + -keep class com.zing.zalo.**{ *; } + -keep enum com.zing.zalo.**{ *; } + -keep interface com.zing.zalo.**{ *; } + `, + }, + }, + ], + [ + "react-native-zalo-kit/expo", + { + appId: "2451745039837416278", + appDelegateContent, + mainActivityContent, + mainApplicationContent, + }, + ], + ], + }, +}; +``` +Finally, run `prebuild` again: +``` +npx expo prebuild --clean +``` +And you should get a fully configured Expo project with ZaloKit. You can view examples at: [app.config.js](./example/app.config.js) and [zalokitStrings.js](./example/zalokitStrings.js) +
# Usage You can import the whole library like: diff --git a/android/build.gradle b/android/build.gradle index a91f581..03fb0a0 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -19,10 +19,10 @@ def safeExtGet(prop, fallback) { } android { - compileSdkVersion safeExtGet('ZaloKit_compileSdkVersion', 29) + compileSdkVersion safeExtGet('ZaloKit_compileSdkVersion', 30) defaultConfig { minSdkVersion safeExtGet('ZaloKit_minSdkVersion', 16) - targetSdkVersion safeExtGet('ZaloKit_targetSdkVersion', 29) + targetSdkVersion safeExtGet('ZaloKit_targetSdkVersion', 30) } diff --git a/example/app.config.js b/example/app.config.js new file mode 100644 index 0000000..65f5ec1 --- /dev/null +++ b/example/app.config.js @@ -0,0 +1,62 @@ +const { + appDelegateContent, + mainActivityContent, + mainApplicationContent, +} = require('./zalokitStrings'); + +module.exports = { + expo: { + name: 'my-expo-app', + slug: 'my-expo-app', + version: '1.0.0', + orientation: 'portrait', + icon: './assets/icon.png', + userInterfaceStyle: 'light', + splash: { + image: './assets/splash.png', + resizeMode: 'contain', + backgroundColor: '#ffffff', + }, + assetBundlePatterns: ['**/*'], + ios: { + supportsTablet: true, + bundleIdentifier: 'com.anonymous.myexpoapp', + }, + android: { + adaptiveIcon: { + foregroundImage: './assets/adaptive-icon.png', + backgroundColor: '#ffffff', + }, + package: 'com.anonymous.myexpoapp', + }, + web: { + favicon: './assets/favicon.png', + }, + plugins: [ + [ + 'expo-build-properties', + { + android: { + extraProguardRules: ` + -keep class com.zing.zalo.**{ *; } + -keep enum com.zing.zalo.**{ *; } + -keep interface com.zing.zalo.**{ *; } + `, + }, + }, + ], + ['react-native-zalo-kit/expo/withAppDelegateDebug'], + ['react-native-zalo-kit/expo/withMainActivityDebug'], + ['react-native-zalo-kit/expo/withMainApplicationDebug'], + // [ + // "react-native-zalo-kit/expo", + // { + // appId: "2451745039837416278", + // appDelegateContent, + // mainActivityContent, + // mainApplicationContent, + // }, + // ], + ], + }, +}; diff --git a/example/zalokitStrings.js b/example/zalokitStrings.js new file mode 100644 index 0000000..de43019 --- /dev/null +++ b/example/zalokitStrings.js @@ -0,0 +1,213 @@ +const appDelegateContent = ` +#import "AppDelegate.h" + +#import +#import +#import + +@implementation AppDelegate + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions +{ + self.moduleName = @"main"; + + // You can add your custom initial props in the dictionary below. + // They will be passed down to the ViewController used by React Native. + self.initialProps = @{}; + [[ZaloSDK sharedInstance] initializeWithAppId:@"2451745039837416278"]; + + return [super application:application didFinishLaunchingWithOptions:launchOptions]; +} + +- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge +{ + return [self getBundleURL]; +} + +- (NSURL *)getBundleURL +{ +#if DEBUG + return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@".expo/.virtual-metro-entry"]; +#else + return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; +#endif +} + +// Linking API +- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url options:(NSDictionary *)options { + return [[ZDKApplicationDelegate sharedInstance] application:application openURL:url options:options] || [super application:application openURL:url options:options] || [RCTLinkingManager application:application openURL:url options:options]; +} + +// Universal Links +- (BOOL)application:(UIApplication *)application continueUserActivity:(nonnull NSUserActivity *)userActivity restorationHandler:(nonnull void (^)(NSArray> * _Nullable))restorationHandler { + BOOL result = [RCTLinkingManager application:application continueUserActivity:userActivity restorationHandler:restorationHandler]; + return [super application:application continueUserActivity:userActivity restorationHandler:restorationHandler] || result; +} + +// Explicitly define remote notification delegates to ensure compatibility with some third-party libraries +- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken +{ + return [super application:application didRegisterForRemoteNotificationsWithDeviceToken:deviceToken]; +} + +// Explicitly define remote notification delegates to ensure compatibility with some third-party libraries +- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error +{ + return [super application:application didFailToRegisterForRemoteNotificationsWithError:error]; +} + +// Explicitly define remote notification delegates to ensure compatibility with some third-party libraries +- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler +{ + return [super application:application didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler]; +} + +@end +`; + +const mainActivityContent = ` +package com.anonymous.myexpoapp + +import android.os.Build +import android.os.Bundle + +import com.facebook.react.ReactActivity +import com.facebook.react.ReactActivityDelegate +import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled +import com.facebook.react.defaults.DefaultReactActivityDelegate + +import expo.modules.ReactActivityDelegateWrapper +import com.zing.zalo.zalosdk.oauth.ZaloSDK; +import android.content.Intent; + +class MainActivity : ReactActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + // Set the theme to AppTheme BEFORE onCreate to support + // coloring the background, status bar, and navigation bar. + // This is required for expo-splash-screen. + setTheme(R.style.AppTheme); + super.onCreate(null) + } + + /** + * Returns the name of the main component registered from JavaScript. This is used to schedule + * rendering of the component. + */ + override fun getMainComponentName(): String = "main" + + /** + * Returns the instance of the [ReactActivityDelegate]. We use [DefaultReactActivityDelegate] + * which allows you to enable New Architecture with a single boolean flags [fabricEnabled] + */ + override fun createReactActivityDelegate(): ReactActivityDelegate { + return ReactActivityDelegateWrapper( + this, + BuildConfig.IS_NEW_ARCHITECTURE_ENABLED, + object : DefaultReactActivityDelegate( + this, + mainComponentName, + fabricEnabled + ){}) + } + + /** + * Align the back button behavior with Android S + * where moving root activities to background instead of finishing activities. + * @see onBackPressed + */ + override fun invokeDefaultOnBackPressed() { + if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.R) { + if (!moveTaskToBack(false)) { + // For non-root activities, use the default implementation to finish them. + super.invokeDefaultOnBackPressed() + } + return + } + + // Use the default back button implementation on Android S + // because it's doing more than [Activity.moveTaskToBack] in fact. + super.invokeDefaultOnBackPressed() + } + + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + super.onActivityResult(requestCode, resultCode, data) + ZaloSDK.Instance.onActivityResult(this, requestCode, resultCode, data) + } +} +`; + +const mainApplicationContent = ` +package com.anonymous.myexpoapp + +import android.app.Application +import android.content.res.Configuration +import androidx.annotation.NonNull + +import com.facebook.react.PackageList +import com.facebook.react.ReactApplication +import com.facebook.react.ReactNativeHost +import com.facebook.react.ReactPackage +import com.facebook.react.ReactHost +import com.facebook.react.config.ReactFeatureFlags +import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load +import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost +import com.facebook.react.defaults.DefaultReactNativeHost +import com.facebook.react.flipper.ReactNativeFlipper +import com.facebook.soloader.SoLoader + +import expo.modules.ApplicationLifecycleDispatcher +import expo.modules.ReactNativeHostWrapper +import com.zing.zalo.zalosdk.oauth.ZaloSDKApplication; + +class MainApplication : Application(), ReactApplication { + + override val reactNativeHost: ReactNativeHost = ReactNativeHostWrapper( + this, + object : DefaultReactNativeHost(this) { + override fun getPackages(): List { + // Packages that cannot be autolinked yet can be added manually here, for example: + // packages.add(new MyReactNativePackage()); + return PackageList(this).packages + } + + override fun getJSMainModuleName(): String = ".expo/.virtual-metro-entry" + + override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUG + + override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED + override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED + } + ) + + override val reactHost: ReactHost + get() = getDefaultReactHost(this.applicationContext, reactNativeHost) + + override fun onCreate() { + super.onCreate() + SoLoader.init(this, false) + if (!BuildConfig.REACT_NATIVE_UNSTABLE_USE_RUNTIME_SCHEDULER_ALWAYS) { + ReactFeatureFlags.unstable_useRuntimeSchedulerAlways = false + } + if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) { + // If you opted-in for the New Architecture, we load the native entry point for this app. + load() + } + if (BuildConfig.DEBUG) { + ReactNativeFlipper.initializeFlipper(this, reactNativeHost.reactInstanceManager) + } + ApplicationLifecycleDispatcher.onApplicationCreate(this) + ZaloSDKApplication.wrap(this); + } + + override fun onConfigurationChanged(newConfig: Configuration) { + super.onConfigurationChanged(newConfig) + ApplicationLifecycleDispatcher.onConfigurationChanged(this, newConfig) + } +} +`; + +module.exports = { + appDelegateContent, + mainActivityContent, + mainApplicationContent, +}; diff --git a/package.json b/package.json index 97693f7..ca8c11f 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,35 @@ { "name": "react-native-zalo-kit", - "version": "4.0.4", + "version": "4.0.5", "description": "Zalo SDK implementation for React Native", "main": "lib/commonjs/index", + "exports": { + ".": { + "import": "./lib/module/index.js", + "types": "./lib/typescript/index.d.ts", + "require": "./lib/commonjs/index.js" + }, + "./expo": { + "import": "./lib/module/expo/plugins/withZaloKit.js", + "types": "./lib/typescript/expo/plugins/withZaloKit.d.ts", + "require": "./lib/commonjs/expo/plugins/withZaloKit.js" + }, + "./expo/withAppDelegateDebug": { + "import": "./lib/module/expo/plugins/ios/withAppDelegateDebug.js", + "types": "./lib/typescript/expo/plugins/ios/withAppDelegateDebug.d.ts", + "require": "./lib/commonjs/expo/plugins/ios/withAppDelegateDebug.js" + }, + "./expo/withMainActivityDebug": { + "import": "./lib/module/expo/plugins/android/withMainActivityDebug.js", + "types": "./lib/typescript/expo/plugins/android/withMainActivityDebug.d.ts", + "require": "./lib/commonjs/expo/plugins/android/withMainActivityDebug.js" + }, + "./expo/withMainApplicationDebug": { + "import": "./lib/module/expo/plugins/android/withMainApplicationDebug.js", + "types": "./lib/typescript/expo/plugins/android/withMainApplicationDebug.d.ts", + "require": "./lib/commonjs/expo/plugins/android/withMainApplicationDebug.js" + } + }, "module": "lib/module/index", "types": "lib/typescript/index.d.ts", "react-native": "src/index", @@ -51,6 +78,8 @@ }, "devDependencies": { "@commitlint/config-conventional": "^11.0.0", + "@expo/config-plugins": "^7.8.4", + "@expo/config-types": "^50.0.0", "@react-native-community/eslint-config": "^2.0.0", "@release-it/conventional-changelog": "^2.0.0", "@types/jest": "^26.0.0", diff --git a/src/expo/plugins/android/withAndroid.ts b/src/expo/plugins/android/withAndroid.ts new file mode 100644 index 0000000..1da7eff --- /dev/null +++ b/src/expo/plugins/android/withAndroid.ts @@ -0,0 +1,161 @@ +import type { ExpoConfig } from '@expo/config-types'; +import { + withAndroidManifest, + withStringsXml, + withPlugins, + withMainActivity, + withMainApplication, +} from '@expo/config-plugins'; + +const withZaloAndroidManifest = (config: ExpoConfig, appId: string) => + withAndroidManifest(config, (manifestConfig) => { + const androidProject = manifestConfig.modResults; + // add queries + const queries = androidProject.manifest.queries; + + const exists = queries.find( + (q) => + q.package && + q.package.find((p) => p.$['android:name'] === 'com.zing.zalo') + ); + + if (!exists) { + queries.push({ + package: [ + { + $: { + 'android:name': 'com.zing.zalo', + }, + }, + ], + }); + } + + const application = androidProject.manifest.application?.find( + (item) => item.$['android:name'] === '.MainApplication' + ); + + if (!application) { + return manifestConfig; + } + + // add metadata + const zaloMetaExists = application['meta-data']?.find( + (item) => item.$['android:name'] === 'com.zing.zalo.zalosdk.appID' + ); + + if (!zaloMetaExists) { + application['meta-data']!.push({ + $: { + 'android:name': 'com.zing.zalo.zalosdk.appID', + 'android:value': '@string/appID', + }, + }); + } + + // add BrowserLoginActivity + const browserLoginActivityExists = application.activity?.find( + (item) => + item.$['android:name'] === + 'com.zing.zalo.zalosdk.oauth.BrowserLoginActivity' + ); + + if (!browserLoginActivityExists) { + application.activity!.push({ + '$': { + 'android:name': 'com.zing.zalo.zalosdk.oauth.BrowserLoginActivity', + 'android:exported': 'true', + }, + 'intent-filter': [ + { + action: [ + { + $: { + 'android:name': 'android.intent.action.VIEW', + }, + }, + ], + category: [ + { + $: { + 'android:name': 'android.intent.category.DEFAULT', + }, + }, + { + $: { + 'android:name': 'android.intent.category.BROWSABLE', + }, + }, + ], + data: [ + { + $: { + 'android:scheme': `zalo-${appId}`, + }, + }, + ], + }, + ], + }); + } + + return manifestConfig; + }); + +const withZaloAndroidStrings = (config: ExpoConfig, appId: string) => + withStringsXml(config, (stringsConfig) => { + let strings = stringsConfig.modResults.resources.string; + + if (!strings) { + stringsConfig.modResults.resources.string = []; + strings = stringsConfig.modResults.resources.string; + } + + const exists = strings.find((item) => item.$.name === 'appID'); + + if (!exists) { + strings.push({ + $: { + name: 'appID', + }, + _: appId, + }); + } + + return stringsConfig; + }); + +const withZaloAndroidMainActivity = (config: ExpoConfig, content: string) => + withMainActivity(config, (mainActivityConfig) => { + mainActivityConfig.modResults.contents = content; + return mainActivityConfig; + }); + +/** + * @typedef {import("expo/config-plugins").ConfigPlugin} ConfigPlugin + * @param {ConfigPlugin} config + * * @param {String} content + */ +const withZaloAndroidMainApplication = (config: ExpoConfig, content: string) => + withMainApplication(config, (mainApplicationConfig) => { + mainApplicationConfig.modResults.contents = content; + return mainApplicationConfig; + }); + +/** + * @typedef {import("expo/config-plugins").ConfigPlugin} ConfigPlugin + * @param {ConfigPlugin} config + * @param {String} appId + */ +const withAndroid = ( + config: ExpoConfig, + { appId, mainActivityContent, mainApplicationContent }: Record +) => + withPlugins(config, [ + [withZaloAndroidManifest, appId], + [withZaloAndroidStrings, appId], + [withZaloAndroidMainActivity, mainActivityContent], + [withZaloAndroidMainApplication, mainApplicationContent], + ]); + +export default withAndroid; diff --git a/src/expo/plugins/android/withMainActivityDebug.ts b/src/expo/plugins/android/withMainActivityDebug.ts new file mode 100644 index 0000000..e467eab --- /dev/null +++ b/src/expo/plugins/android/withMainActivityDebug.ts @@ -0,0 +1,10 @@ +import type { ExpoConfig } from '@expo/config-types'; +import { withMainActivity } from '@expo/config-plugins'; + +const withMainActivityDebug = (config: ExpoConfig) => + withMainActivity(config, (mainActivityConfig) => { + console.log(mainActivityConfig.modResults.contents); + return mainActivityConfig; + }); + +export default withMainActivityDebug; diff --git a/src/expo/plugins/android/withMainApplicationDebug.ts b/src/expo/plugins/android/withMainApplicationDebug.ts new file mode 100644 index 0000000..a404b77 --- /dev/null +++ b/src/expo/plugins/android/withMainApplicationDebug.ts @@ -0,0 +1,10 @@ +import { withMainApplication } from '@expo/config-plugins'; +import type { ExpoConfig } from '@expo/config-types'; + +const withMainApplicationDebug = (config: ExpoConfig) => + withMainApplication(config, (mainApplicationConfig) => { + console.log(mainApplicationConfig.modResults.contents); + return mainApplicationConfig; + }); + +export default withMainApplicationDebug; diff --git a/src/expo/plugins/ios/withAppDelegateDebug.ts b/src/expo/plugins/ios/withAppDelegateDebug.ts new file mode 100644 index 0000000..5c27b52 --- /dev/null +++ b/src/expo/plugins/ios/withAppDelegateDebug.ts @@ -0,0 +1,10 @@ +import { withAppDelegate } from '@expo/config-plugins'; +import type { ExpoConfig } from '@expo/config-types'; + +const withZaloAppDelegateDebug = (config: ExpoConfig) => + withAppDelegate(config, (appDelegateConfig) => { + console.log(appDelegateConfig.modResults.contents); + return appDelegateConfig; + }); + +export default withZaloAppDelegateDebug; diff --git a/src/expo/plugins/ios/withIOS.ts b/src/expo/plugins/ios/withIOS.ts new file mode 100644 index 0000000..8a78a14 --- /dev/null +++ b/src/expo/plugins/ios/withIOS.ts @@ -0,0 +1,59 @@ +import { + withPlugins, + withInfoPlist, + withAppDelegate, +} from '@expo/config-plugins'; +import type { ExpoConfig } from '@expo/config-types'; + +const withZaloIOSPlist = (config: ExpoConfig, appId: string) => + withInfoPlist(config, (infoConfig) => { + let queriesSchemes = infoConfig.modResults.LSApplicationQueriesSchemes; + if (!queriesSchemes) { + infoConfig.modResults.LSApplicationQueriesSchemes = []; + queriesSchemes = infoConfig.modResults.LSApplicationQueriesSchemes; + } + + if (!queriesSchemes.find((item) => item === 'zalosdk')) { + queriesSchemes.push('zalosdk'); + } + + if (!queriesSchemes.find((item) => item === 'zaloshareext')) { + queriesSchemes.push('zaloshareext'); + } + + let urlTypes = infoConfig.modResults.CFBundleURLTypes; + if (!urlTypes) { + infoConfig.modResults.CFBundleURLTypes = []; + urlTypes = infoConfig.modResults.CFBundleURLTypes; + } + + if (!urlTypes.find((item) => item.CFBundleURLName)) { + urlTypes.push({ + CFBundleURLName: 'zalo', + CFBundleURLSchemes: [`zalo-${appId}`], + }); + } + + return infoConfig; + }); + +const withZaloAppDelegate = (config: ExpoConfig, appDelegateContent: string) => + withAppDelegate(config, (appDelegateConfig) => { + appDelegateConfig.modResults.contents = appDelegateContent; + return appDelegateConfig; + }); + +/** + * @typedef {import("expo/config-plugins").ConfigPlugin} ConfigPlugin + * @param {ConfigPlugin} config + */ +const withIOS = ( + config: ExpoConfig, + { appId, appDelegateContent }: Record +) => + withPlugins(config, [ + [withZaloIOSPlist, appId], + [withZaloAppDelegate, appDelegateContent], + ]); + +export default withIOS; diff --git a/src/expo/plugins/withZaloKit.ts b/src/expo/plugins/withZaloKit.ts new file mode 100644 index 0000000..6e2dc49 --- /dev/null +++ b/src/expo/plugins/withZaloKit.ts @@ -0,0 +1,33 @@ +import { withPlugins } from '@expo/config-plugins'; +import withAndroid from './android/withAndroid'; +import withIOS from './ios/withIOS'; +import type { ExpoConfig } from '@expo/config-types'; + +const withZaloKit = ( + config: ExpoConfig, + { + appId, + appDelegateContent, + mainActivityContent, + mainApplicationContent, + }: Record +) => + withPlugins(config, [ + [ + withAndroid, + { + appId, + mainActivityContent, + mainApplicationContent, + }, + ], + [ + withIOS, + { + appId, + appDelegateContent, + }, + ], + ]); + +export default withZaloKit; diff --git a/yarn.lock b/yarn.lock index 07b651f..dfc3895 100644 --- a/yarn.lock +++ b/yarn.lock @@ -16,6 +16,13 @@ dependencies: "@babel/highlight" "^7.16.0" +"@babel/code-frame@~7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.4.tgz#168da1a36e90da68ae8d49c0f1b48c7c6249213a" + integrity sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg== + dependencies: + "@babel/highlight" "^7.10.4" + "@babel/compat-data@^7.13.11", "@babel/compat-data@^7.16.0", "@babel/compat-data@^7.16.4": version "7.16.4" resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.16.4.tgz#081d6bbc336ec5c2435c6346b2ae1fb98b5ac68e" @@ -1228,6 +1235,77 @@ minimatch "^3.0.4" strip-json-comments "^3.1.1" +"@expo/config-plugins@^7.8.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@expo/config-plugins/-/config-plugins-7.8.4.tgz#533b5d536c1dc8b5544d64878b51bda28f2e1a1f" + integrity sha512-hv03HYxb/5kX8Gxv/BTI8TLc9L06WzqAfHRRXdbar4zkLcP2oTzvsLEF4/L/TIpD3rsnYa0KU42d0gWRxzPCJg== + dependencies: + "@expo/config-types" "^50.0.0-alpha.1" + "@expo/fingerprint" "^0.6.0" + "@expo/json-file" "~8.3.0" + "@expo/plist" "^0.1.0" + "@expo/sdk-runtime-versions" "^1.0.0" + "@react-native/normalize-color" "^2.0.0" + chalk "^4.1.2" + debug "^4.3.1" + find-up "~5.0.0" + getenv "^1.0.0" + glob "7.1.6" + resolve-from "^5.0.0" + semver "^7.5.3" + slash "^3.0.0" + slugify "^1.6.6" + xcode "^3.0.1" + xml2js "0.6.0" + +"@expo/config-types@^50.0.0", "@expo/config-types@^50.0.0-alpha.1": + version "50.0.0" + resolved "https://registry.yarnpkg.com/@expo/config-types/-/config-types-50.0.0.tgz#b534d3ec997ec60f8af24f6ad56244c8afc71a0b" + integrity sha512-0kkhIwXRT6EdFDwn+zTg9R2MZIAEYGn1MVkyRohAd+C9cXOb5RA8WLQi7vuxKF9m1SMtNAUrf0pO+ENK0+/KSw== + +"@expo/fingerprint@^0.6.0": + version "0.6.0" + resolved "https://registry.yarnpkg.com/@expo/fingerprint/-/fingerprint-0.6.0.tgz#77366934673d4ecea37284109b4dd67f9e6a7487" + integrity sha512-KfpoVRTMwMNJ/Cf5o+Ou8M/Y0EGSTqK+rbi70M2Y0K2qgWNfMJ1gm6sYO9uc8lcTr7YSYM1Rme3dk7QXhpScNA== + dependencies: + "@expo/spawn-async" "^1.5.0" + chalk "^4.1.2" + debug "^4.3.4" + find-up "^5.0.0" + minimatch "^3.0.4" + p-limit "^3.1.0" + resolve-from "^5.0.0" + +"@expo/json-file@~8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@expo/json-file/-/json-file-8.3.0.tgz#fc84af77b532a4e9bfb5beafd0e3b7f692b6bd7e" + integrity sha512-yROUeXJXR5goagB8c3muFLCzLmdGOvoPpR5yDNaXrnTp4euNykr9yW0wWhJx4YVRTNOPtGBnEbbJBW+a9q+S6g== + dependencies: + "@babel/code-frame" "~7.10.4" + json5 "^2.2.2" + write-file-atomic "^2.3.0" + +"@expo/plist@^0.1.0": + version "0.1.0" + resolved "https://registry.yarnpkg.com/@expo/plist/-/plist-0.1.0.tgz#eabc95f951d14e10c87fd0443ee01d567371f058" + integrity sha512-xWD+8vIFif0wKyuqe3fmnmnSouXYucciZXFzS0ZD5OV9eSAS1RGQI5FaGGJ6zxJ4mpdy/4QzbLdBjnYE5vxA0g== + dependencies: + "@xmldom/xmldom" "~0.7.7" + base64-js "^1.2.3" + xmlbuilder "^14.0.0" + +"@expo/sdk-runtime-versions@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@expo/sdk-runtime-versions/-/sdk-runtime-versions-1.0.0.tgz#d7ebd21b19f1c6b0395e50d78da4416941c57f7c" + integrity sha512-Doz2bfiPndXYFPMRwPyGa1k5QaKDVpY806UJj570epIiMzWaYyCtobasyfC++qfIXVb5Ocy7r3tP9d62hAQ7IQ== + +"@expo/spawn-async@^1.5.0": + version "1.7.2" + resolved "https://registry.yarnpkg.com/@expo/spawn-async/-/spawn-async-1.7.2.tgz#fcfe66c3e387245e72154b1a7eae8cada6a47f58" + integrity sha512-QdWi16+CHB9JYP7gma19OVVg0BFkvU8zNj9GjWorYI8Iv8FUxjOCcYRuAmX4s/h91e4e7BPsskc8cSrZYho9Ew== + dependencies: + cross-spawn "^7.0.3" + "@hapi/address@2.x.x": version "2.1.4" resolved "https://registry.yarnpkg.com/@hapi/address/-/address-2.1.4.tgz#5d67ed43f3fd41a69d4b9ff7b56e7c0d1d0a81e5" @@ -1792,6 +1870,11 @@ resolved "https://registry.yarnpkg.com/@react-native-community/eslint-plugin/-/eslint-plugin-1.1.0.tgz#e42b1bef12d2415411519fd528e64b593b1363dc" integrity sha512-W/J0fNYVO01tioHjvYWQ9m6RgndVtbElzYozBq1ZPrHO/iCzlqoySHl4gO/fpCl9QEFjvJfjPgtPMTMlsoq5DQ== +"@react-native/normalize-color@^2.0.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@react-native/normalize-color/-/normalize-color-2.1.0.tgz#939b87a9849e81687d3640c5efa2a486ac266f91" + integrity sha512-Z1jQI2NpdFJCVgpY+8Dq/Bt3d+YUi1928Q+/CZm/oh66fzM0RUl54vvuXlPJKybH4pdCZey1eDTPaLHkMPNgWA== + "@release-it/conventional-changelog@^2.0.0": version "2.0.1" resolved "https://registry.yarnpkg.com/@release-it/conventional-changelog/-/conventional-changelog-2.0.1.tgz#bdd52ad3ecc0d6e39d637592d6ea2bd6d28e5ecb" @@ -2108,6 +2191,16 @@ dependencies: eslint-visitor-keys "^1.1.0" +"@xmldom/xmldom@^0.8.8": + version "0.8.10" + resolved "https://registry.yarnpkg.com/@xmldom/xmldom/-/xmldom-0.8.10.tgz#a1337ca426aa61cef9fe15b5b28e340a72f6fa99" + integrity sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw== + +"@xmldom/xmldom@~0.7.7": + version "0.7.13" + resolved "https://registry.yarnpkg.com/@xmldom/xmldom/-/xmldom-0.7.13.tgz#ff34942667a4e19a9f4a0996a76814daac364cf3" + integrity sha512-lm2GW5PkosIzccsaZIz7tp8cPADSIlIHWDFTR1N0SzfinhhYgeIQjFMz4rYzanCScr3DqQLeomUDArp6MWKm+g== + JSONStream@^1.0.4: version "1.3.5" resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.5.tgz#3208c1f08d3a4d99261ab64f92302bc15e111ca0" @@ -2616,7 +2709,7 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== -base64-js@^1.1.2, base64-js@^1.3.1, base64-js@^1.5.1: +base64-js@^1.1.2, base64-js@^1.2.3, base64-js@^1.3.1, base64-js@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== @@ -2688,6 +2781,13 @@ bplist-parser@0.3.0: dependencies: big-integer "1.6.x" +bplist-parser@0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/bplist-parser/-/bplist-parser-0.3.1.tgz#e1c90b2ca2a9f9474cc72f6862bbf3fee8341fd1" + integrity sha512-PyJxiNtA5T2PlLIeBot4lbp7rj4OadzjnMZD/G5zuBNt8ei/yCU7+wW0h2bag9vr8c+/WuRWmSxbqAl9hL1rBA== + dependencies: + big-integer "1.6.x" + brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -2882,7 +2982,7 @@ chalk@4.1.0: ansi-styles "^4.1.0" supports-color "^7.1.0" -chalk@4.1.2, chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.1: +chalk@4.1.2, chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.1, chalk@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== @@ -3508,6 +3608,13 @@ debug@4, debug@4.3.2, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1: dependencies: ms "2.1.2" +debug@^4.3.1, debug@^4.3.4: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + decamelize-keys@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.0.tgz#d171a87933252807eb3cb61dc1c1445d078df2d9" @@ -4395,7 +4502,7 @@ find-up@^4.0.0, find-up@^4.1.0: locate-path "^5.0.0" path-exists "^4.0.0" -find-up@^5.0.0: +find-up@^5.0.0, find-up@~5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== @@ -4588,6 +4695,11 @@ get-value@^2.0.3, get-value@^2.0.6: resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= +getenv@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/getenv/-/getenv-1.0.0.tgz#874f2e7544fbca53c7a4738f37de8605c3fcfc31" + integrity sha512-7yetJWqbS9sbn0vIfliPsFgoXMKn/YMF+Wuiog97x+urnSRRRZ7xB+uVkwGKzRgq9CDFfMQnE9ruL5DHv9c6Xg== + git-raw-commits@^2.0.0, git-raw-commits@^2.0.8: version "2.0.10" resolved "https://registry.yarnpkg.com/git-raw-commits/-/git-raw-commits-2.0.10.tgz#e2255ed9563b1c9c3ea6bd05806410290297bbc1" @@ -4644,6 +4756,18 @@ glob-parent@^5.1.2: dependencies: is-glob "^4.0.1" +glob@7.1.6: + version "7.1.6" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" + integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + glob@^7.0.0, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: version "7.2.0" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" @@ -4728,6 +4852,11 @@ got@^9.6.0: to-readable-stream "^1.0.0" url-parse-lax "^3.0.0" +graceful-fs@^4.1.11: + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== + graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0, graceful-fs@^4.2.4: version "4.2.8" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.8.tgz#e412b8d33f5e006593cbd3cee6df9f2cebbe802a" @@ -6116,6 +6245,11 @@ json5@^2.1.2, json5@^2.1.3: dependencies: minimist "^1.2.5" +json5@^2.2.2: + version "2.2.3" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" + integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== + jsonfile@^2.1.0: version "2.4.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8" @@ -7230,7 +7364,7 @@ p-limit@^2.0.0, p-limit@^2.2.0: dependencies: p-try "^2.0.0" -p-limit@^3.0.2: +p-limit@^3.0.2, p-limit@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== @@ -7453,6 +7587,15 @@ plist@^3.0.1, plist@^3.0.4: base64-js "^1.5.1" xmlbuilder "^9.0.7" +plist@^3.0.5: + version "3.1.0" + resolved "https://registry.yarnpkg.com/plist/-/plist-3.1.0.tgz#797a516a93e62f5bde55e0b9cc9c967f860893c9" + integrity sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ== + dependencies: + "@xmldom/xmldom" "^0.8.8" + base64-js "^1.5.1" + xmlbuilder "^15.1.1" + plugin-error@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/plugin-error/-/plugin-error-0.1.2.tgz#3b9bb3335ccf00f425e07437e19276967da47ace" @@ -8172,6 +8315,11 @@ sane@^4.0.3: minimist "^1.1.1" walker "~1.0.5" +sax@>=0.6.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.3.0.tgz#a5dbe77db3be05c9d1ee7785dbd3ea9de51593d0" + integrity sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA== + sax@^1.2.1: version "1.2.4" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" @@ -8226,6 +8374,13 @@ semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== +semver@^7.5.3: + version "7.6.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.0.tgz#1a46a4db4bffcccd97b743b5005c8325f23d4e2d" + integrity sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg== + dependencies: + lru-cache "^6.0.0" + send@0.17.1: version "0.17.1" resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8" @@ -8368,6 +8523,15 @@ simple-plist@^1.0.0: bplist-parser "0.3.0" plist "^3.0.4" +simple-plist@^1.1.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/simple-plist/-/simple-plist-1.3.1.tgz#16e1d8f62c6c9b691b8383127663d834112fb017" + integrity sha512-iMSw5i0XseMnrhtIzRb7XpQEXepa9xhWxGUojHBL43SIpQuDQkh3Wpy67ZbDzZVr6EKxvwVChnVpdl8hEVLDiw== + dependencies: + bplist-creator "0.1.0" + bplist-parser "0.3.1" + plist "^3.0.5" + sisteransi@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" @@ -8401,6 +8565,11 @@ slice-ansi@^4.0.0: astral-regex "^2.0.0" is-fullwidth-code-point "^3.0.0" +slugify@^1.6.6: + version "1.6.6" + resolved "https://registry.yarnpkg.com/slugify/-/slugify-1.6.6.tgz#2d4ac0eacb47add6af9e04d3be79319cbcc7924b" + integrity sha512-h+z7HKHYXj6wJU+AnS/+IH8Uh9fdcX1Lrhg1/VMdf9PwoBQXFcXiAdsy2tSK0P6gKwJLXp02r90ahUCqHk9rrw== + snapdragon-node@^2.0.1: version "2.1.1" resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" @@ -9203,6 +9372,11 @@ uuid@^3.3.2: resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== +uuid@^7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-7.0.3.tgz#c5c9f2c8cf25dc0a372c4df1441c41f5bd0c680b" + integrity sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg== + v8-compile-cache@^2.0.3: version "2.3.0" resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" @@ -9398,6 +9572,15 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= +write-file-atomic@^2.3.0: + version "2.4.3" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.4.3.tgz#1fd2e9ae1df3e75b8d8c367443c692d4ca81f481" + integrity sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ== + dependencies: + graceful-fs "^4.1.11" + imurmurhash "^0.1.4" + signal-exit "^3.0.2" + write-file-atomic@^3.0.0: version "3.0.3" resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8" @@ -9429,6 +9612,14 @@ xcode@^2.0.0: simple-plist "^1.0.0" uuid "^3.3.2" +xcode@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/xcode/-/xcode-3.0.1.tgz#3efb62aac641ab2c702458f9a0302696146aa53c" + integrity sha512-kCz5k7J7XbJtjABOvkc5lJmkiDh8VhjVCGNiqdKCscmVpdVUpEAyXv1xmCLkQJ5dsHqx3IPO4XW+NTDhU/fatA== + dependencies: + simple-plist "^1.1.0" + uuid "^7.0.3" + xdg-basedir@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-4.0.0.tgz#4bc8d9984403696225ef83a1573cbbcb4e79db13" @@ -9439,11 +9630,34 @@ xml-name-validator@^3.0.0: resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw== +xml2js@0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.6.0.tgz#07afc447a97d2bd6507a1f76eeadddb09f7a8282" + integrity sha512-eLTh0kA8uHceqesPqSE+VvO1CDDJWMwlQfB6LuN6T8w6MaDJ8Txm8P7s5cHD0miF0V+GGTZrDQfxPZQVsur33w== + dependencies: + sax ">=0.6.0" + xmlbuilder "~11.0.0" + +xmlbuilder@^14.0.0: + version "14.0.0" + resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-14.0.0.tgz#876b5aec4f05ffd5feb97b0a871c855d16fbeb8c" + integrity sha512-ts+B2rSe4fIckR6iquDjsKbQFK2NlUk6iG5nf14mDEyldgoc2nEKZ3jZWMPTxGQwVgToSjt6VGIho1H8/fNFTg== + +xmlbuilder@^15.1.1: + version "15.1.1" + resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-15.1.1.tgz#9dcdce49eea66d8d10b42cae94a79c3c8d0c2ec5" + integrity sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg== + xmlbuilder@^9.0.7: version "9.0.7" resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.7.tgz#132ee63d2ec5565c557e20f4c22df9aca686b10d" integrity sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0= +xmlbuilder@~11.0.0: + version "11.0.1" + resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3" + integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA== + xmlchars@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb"