Repository: microsoft/react-native-code-push Branch: master Commit: 50a7ed5bc0f1 Files: 389 Total size: 2.2 MB Directory structure: gitextract_eag1d8bl/ ├── .azurepipelines/ │ ├── build-rn-code-push-1es.yml │ └── test-rn-code-push.yml ├── .config/ │ └── CredScanSuppressions.json ├── .github/ │ ├── CODEOWNERS │ ├── ISSUE_TEMPLATE.md │ └── policies/ │ └── resourceManagement.yml ├── .gitignore ├── .npmignore ├── .vscode/ │ ├── launch.json │ ├── settings.json │ └── tasks.json ├── .watchmanconfig ├── AlertAdapter.js ├── CONTRIBUTING.md ├── CodePush.js ├── CodePush.podspec ├── Examples/ │ ├── CodePushDemoApp/ │ │ ├── .buckconfig │ │ ├── .editorconfig │ │ ├── .eslintrc.js │ │ ├── .flowconfig │ │ ├── .gitattributes │ │ ├── .gitignore │ │ ├── .prettierrc.js │ │ ├── .watchmanconfig │ │ ├── App.js │ │ ├── __tests__/ │ │ │ └── App-test.js │ │ ├── android/ │ │ │ ├── app/ │ │ │ │ ├── BUCK │ │ │ │ ├── build.gradle │ │ │ │ ├── build_defs.bzl │ │ │ │ ├── debug.keystore │ │ │ │ ├── proguard-rules.pro │ │ │ │ └── src/ │ │ │ │ └── main/ │ │ │ │ ├── AndroidManifest.xml │ │ │ │ ├── java/ │ │ │ │ │ └── com/ │ │ │ │ │ └── codepushdemoapp/ │ │ │ │ │ ├── MainActivity.java │ │ │ │ │ └── MainApplication.java │ │ │ │ └── res/ │ │ │ │ └── values/ │ │ │ │ ├── strings.xml │ │ │ │ └── styles.xml │ │ │ ├── build.gradle │ │ │ ├── gradle/ │ │ │ │ └── wrapper/ │ │ │ │ ├── gradle-wrapper.jar │ │ │ │ └── gradle-wrapper.properties │ │ │ ├── gradle.properties │ │ │ ├── gradlew │ │ │ ├── gradlew.bat │ │ │ └── settings.gradle │ │ ├── app.json │ │ ├── babel.config.js │ │ ├── index.js │ │ ├── ios/ │ │ │ ├── CodePushDemoApp/ │ │ │ │ ├── AppDelegate.h │ │ │ │ ├── AppDelegate.m │ │ │ │ ├── Images.xcassets/ │ │ │ │ │ ├── AppIcon.appiconset/ │ │ │ │ │ │ └── Contents.json │ │ │ │ │ └── Contents.json │ │ │ │ ├── Info.plist │ │ │ │ ├── LaunchScreen.storyboard │ │ │ │ └── main.m │ │ │ ├── CodePushDemoApp.xcodeproj/ │ │ │ │ ├── project.pbxproj │ │ │ │ └── xcshareddata/ │ │ │ │ └── xcschemes/ │ │ │ │ └── CodePushDemoApp.xcscheme │ │ │ ├── CodePushDemoApp.xcworkspace/ │ │ │ │ ├── contents.xcworkspacedata │ │ │ │ └── xcshareddata/ │ │ │ │ └── IDEWorkspaceChecks.plist │ │ │ ├── CodePushDemoAppTests/ │ │ │ │ ├── CodePushDemoAppTests.m │ │ │ │ └── Info.plist │ │ │ └── Podfile │ │ ├── metro.config.js │ │ └── package.json │ ├── CodePushDemoAppCpp/ │ │ ├── .buckconfig │ │ ├── .eslintrc.js │ │ ├── .flowconfig │ │ ├── .gitattributes │ │ ├── .gitignore │ │ ├── .prettierrc.js │ │ ├── .watchmanconfig │ │ ├── App.js │ │ ├── app.json │ │ ├── babel.config.js │ │ ├── index.js │ │ ├── metro.config.js │ │ ├── package.json │ │ └── windows/ │ │ ├── .gitignore │ │ ├── CodePushDemoAppCpp/ │ │ │ ├── .gitignore │ │ │ ├── App.cpp │ │ │ ├── App.h │ │ │ ├── App.idl │ │ │ ├── App.xaml │ │ │ ├── AutolinkedNativeModules.g.cpp │ │ │ ├── AutolinkedNativeModules.g.h │ │ │ ├── AutolinkedNativeModules.g.targets │ │ │ ├── CodePushDemoAppCpp.vcxproj │ │ │ ├── CodePushDemoAppCpp.vcxproj.filters │ │ │ ├── CodePushDemoAppCpp_TemporaryKey.pfx │ │ │ ├── MainPage.cpp │ │ │ ├── MainPage.h │ │ │ ├── MainPage.idl │ │ │ ├── MainPage.xaml │ │ │ ├── Package.appxmanifest │ │ │ ├── PropertySheet.props │ │ │ ├── ReactPackageProvider.cpp │ │ │ ├── ReactPackageProvider.h │ │ │ ├── packages.config │ │ │ ├── pch.cpp │ │ │ └── pch.h │ │ └── CodePushDemoAppCpp.sln │ ├── create-app.js │ └── nexpect.js ├── LICENSE.md ├── README.md ├── Recipes/ │ ├── UpdateButton.ios.js │ └── UpdateOnStart.ios.js ├── SECURITY.md ├── android/ │ ├── app/ │ │ ├── build.gradle │ │ ├── proguard-rules.pro │ │ └── src/ │ │ ├── debug/ │ │ │ └── AndroidManifest.xml │ │ └── main/ │ │ ├── AndroidManifest.xml │ │ └── java/ │ │ └── com/ │ │ └── microsoft/ │ │ └── codepush/ │ │ └── react/ │ │ ├── CodePush.java │ │ ├── CodePushBuilder.java │ │ ├── CodePushConstants.java │ │ ├── CodePushDialog.java │ │ ├── CodePushInstallMode.java │ │ ├── CodePushInvalidPublicKeyException.java │ │ ├── CodePushInvalidUpdateException.java │ │ ├── CodePushMalformedDataException.java │ │ ├── CodePushNativeModule.java │ │ ├── CodePushNotInitializedException.java │ │ ├── CodePushTelemetryManager.java │ │ ├── CodePushUnknownException.java │ │ ├── CodePushUpdateManager.java │ │ ├── CodePushUpdateState.java │ │ ├── CodePushUpdateUtils.java │ │ ├── CodePushUtils.java │ │ ├── DownloadProgress.java │ │ ├── DownloadProgressCallback.java │ │ ├── FileUtils.java │ │ ├── ReactInstanceHolder.java │ │ ├── SettingsManager.java │ │ └── TLSSocketFactory.java │ ├── build.gradle │ ├── codepush.gradle │ ├── gradle/ │ │ └── wrapper/ │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties │ ├── gradle.properties │ ├── gradlew │ ├── gradlew.bat │ └── settings.gradle ├── code-push-plugin-testing-framework/ │ ├── package.json │ ├── script/ │ │ ├── index.js │ │ ├── platform.js │ │ ├── projectManager.js │ │ ├── serverUtil.js │ │ ├── test.js │ │ ├── testBuilder.js │ │ ├── testConfig.js │ │ └── testUtil.js │ └── typings/ │ └── code-push-plugin-testing-framework.d.ts ├── docs/ │ ├── api-android.md │ ├── api-ios.md │ ├── api-js.md │ ├── multi-deployment-testing-android.md │ ├── multi-deployment-testing-ios.md │ ├── setup-android.md │ ├── setup-ios.md │ └── setup-windows.md ├── ios/ │ ├── CodePush/ │ │ ├── Base64/ │ │ │ ├── Base64/ │ │ │ │ ├── MF_Base64Additions.h │ │ │ │ └── MF_Base64Additions.m │ │ │ └── README.md │ │ ├── CodePush.h │ │ ├── CodePush.m │ │ ├── CodePushConfig.m │ │ ├── CodePushDownloadHandler.m │ │ ├── CodePushErrorUtils.m │ │ ├── CodePushPackage.m │ │ ├── CodePushTelemetryManager.m │ │ ├── CodePushUpdateUtils.m │ │ ├── CodePushUtils.m │ │ ├── JWT/ │ │ │ ├── Core/ │ │ │ │ ├── Algorithms/ │ │ │ │ │ ├── Base/ │ │ │ │ │ │ ├── JWTAlgorithm.h │ │ │ │ │ │ ├── JWTAlgorithmFactory.h │ │ │ │ │ │ ├── JWTAlgorithmFactory.m │ │ │ │ │ │ ├── JWTAlgorithmNone.h │ │ │ │ │ │ └── JWTAlgorithmNone.m │ │ │ │ │ ├── ESFamily/ │ │ │ │ │ │ ├── JWTAlgorithmESBase.h │ │ │ │ │ │ └── JWTAlgorithmESBase.m │ │ │ │ │ ├── HSFamily/ │ │ │ │ │ │ ├── JWTAlgorithmHSBase.h │ │ │ │ │ │ └── JWTAlgorithmHSBase.m │ │ │ │ │ ├── Holders/ │ │ │ │ │ │ ├── JWTAlgorithmDataHolder.h │ │ │ │ │ │ ├── JWTAlgorithmDataHolder.m │ │ │ │ │ │ ├── JWTAlgorithmDataHolderChain.h │ │ │ │ │ │ └── JWTAlgorithmDataHolderChain.m │ │ │ │ │ └── RSFamily/ │ │ │ │ │ ├── JWTAlgorithmRSBase.h │ │ │ │ │ ├── JWTAlgorithmRSBase.m │ │ │ │ │ ├── JWTRSAlgorithm.h │ │ │ │ │ └── RSKeys/ │ │ │ │ │ ├── JWTCryptoKey.h │ │ │ │ │ ├── JWTCryptoKey.m │ │ │ │ │ ├── JWTCryptoKeyExtractor.h │ │ │ │ │ ├── JWTCryptoKeyExtractor.m │ │ │ │ │ ├── JWTCryptoSecurity.h │ │ │ │ │ └── JWTCryptoSecurity.m │ │ │ │ ├── ClaimSet/ │ │ │ │ │ ├── JWTClaim.h │ │ │ │ │ ├── JWTClaim.m │ │ │ │ │ ├── JWTClaimsSet.h │ │ │ │ │ ├── JWTClaimsSet.m │ │ │ │ │ ├── JWTClaimsSetSerializer.h │ │ │ │ │ ├── JWTClaimsSetSerializer.m │ │ │ │ │ ├── JWTClaimsSetVerifier.h │ │ │ │ │ └── JWTClaimsSetVerifier.m │ │ │ │ ├── Coding/ │ │ │ │ │ ├── JWTCoding+ResultTypes.h │ │ │ │ │ ├── JWTCoding+ResultTypes.m │ │ │ │ │ ├── JWTCoding+VersionOne.h │ │ │ │ │ ├── JWTCoding+VersionOne.m │ │ │ │ │ ├── JWTCoding+VersionThree.h │ │ │ │ │ ├── JWTCoding+VersionThree.m │ │ │ │ │ ├── JWTCoding+VersionTwo.h │ │ │ │ │ ├── JWTCoding+VersionTwo.m │ │ │ │ │ ├── JWTCoding.h │ │ │ │ │ └── JWTCoding.m │ │ │ │ ├── FrameworkSupplement/ │ │ │ │ │ ├── JWT.h │ │ │ │ │ └── Map.modulemap │ │ │ │ └── Supplement/ │ │ │ │ ├── JWTBase64Coder.h │ │ │ │ ├── JWTBase64Coder.m │ │ │ │ ├── JWTDeprecations.h │ │ │ │ ├── JWTErrorDescription.h │ │ │ │ └── JWTErrorDescription.m │ │ │ ├── LICENSE │ │ │ └── README.md │ │ ├── RCTConvert+CodePushInstallMode.m │ │ ├── RCTConvert+CodePushUpdateState.m │ │ └── SSZipArchive/ │ │ ├── Info.plist │ │ ├── README.md │ │ ├── SSZipArchive.h │ │ ├── SSZipArchive.m │ │ ├── SSZipCommon.h │ │ ├── Supporting Files/ │ │ │ └── PrivacyInfo.xcprivacy │ │ ├── include/ │ │ │ └── ZipArchive.h │ │ └── minizip/ │ │ ├── LICENSE │ │ ├── mz.h │ │ ├── mz_compat.c │ │ ├── mz_compat.h │ │ ├── mz_crypt.c │ │ ├── mz_crypt.h │ │ ├── mz_crypt_apple.c │ │ ├── mz_os.c │ │ ├── mz_os.h │ │ ├── mz_os_posix.c │ │ ├── mz_strm.c │ │ ├── mz_strm.h │ │ ├── mz_strm_buf.c │ │ ├── mz_strm_buf.h │ │ ├── mz_strm_mem.c │ │ ├── mz_strm_mem.h │ │ ├── mz_strm_os.h │ │ ├── mz_strm_os_posix.c │ │ ├── mz_strm_pkcrypt.c │ │ ├── mz_strm_pkcrypt.h │ │ ├── mz_strm_split.c │ │ ├── mz_strm_split.h │ │ ├── mz_strm_wzaes.c │ │ ├── mz_strm_wzaes.h │ │ ├── mz_strm_zlib.c │ │ ├── mz_strm_zlib.h │ │ ├── mz_zip.c │ │ ├── mz_zip.h │ │ ├── mz_zip_rw.c │ │ └── mz_zip_rw.h │ ├── CodePush.xcodeproj/ │ │ ├── project.pbxproj │ │ └── project.xcworkspace/ │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata/ │ │ └── IDEWorkspaceChecks.plist │ └── PrivacyInfo.xcprivacy ├── logging.js ├── package-mixins.js ├── package.json ├── react-native.config.js ├── request-fetch-adapter.js ├── scripts/ │ ├── generateBundledResourcesHash.js │ ├── getFilesInFolder.js │ ├── postlink/ │ │ ├── android/ │ │ │ └── postlink.js │ │ ├── ios/ │ │ │ └── postlink.js │ │ └── run.js │ ├── postunlink/ │ │ ├── android/ │ │ │ └── postunlink.js │ │ ├── ios/ │ │ │ └── postunlink.js │ │ └── run.js │ ├── recordFilesBeforeBundleCommand.js │ └── tools/ │ ├── linkToolsAndroid.js │ └── linkToolsIos.js ├── test/ │ ├── template/ │ │ ├── android/ │ │ │ └── app/ │ │ │ └── src/ │ │ │ └── main/ │ │ │ ├── java/ │ │ │ │ └── com/ │ │ │ │ └── testcodepush/ │ │ │ │ └── MainApplication.java │ │ │ └── res/ │ │ │ └── values/ │ │ │ └── strings.xml │ │ ├── codePushWrapper.js │ │ ├── index.js │ │ ├── ios/ │ │ │ └── TestCodePush/ │ │ │ └── AppDelegate.mm │ │ └── scenarios/ │ │ ├── scenarioCheckForUpdate.js │ │ ├── scenarioCheckForUpdateCustomKey.js │ │ ├── scenarioDisallowRestartImmediate.js │ │ ├── scenarioDisallowRestartOnResume.js │ │ ├── scenarioDisallowRestartOnSuspend.js │ │ ├── scenarioDownloadUpdate.js │ │ ├── scenarioInstall.js │ │ ├── scenarioInstallOnRestartWithRevert.js │ │ ├── scenarioInstallOnResumeWithRevert.js │ │ ├── scenarioInstallOnSuspendWithRevert.js │ │ ├── scenarioInstallRestart2x.js │ │ ├── scenarioInstallWithRevert.js │ │ ├── scenarioRestart.js │ │ ├── scenarioRestart2x.js │ │ ├── scenarioSync.js │ │ ├── scenarioSync2x.js │ │ ├── scenarioSyncMandatoryDefault.js │ │ ├── scenarioSyncMandatoryRestart.js │ │ ├── scenarioSyncMandatoryResume.js │ │ ├── scenarioSyncMandatorySuspend.js │ │ ├── scenarioSyncRestartDelay.js │ │ ├── scenarioSyncResume.js │ │ ├── scenarioSyncResumeDelay.js │ │ ├── scenarioSyncSuspend.js │ │ ├── scenarioSyncSuspendDelay.js │ │ ├── updateDeviceReady.js │ │ ├── updateNARConditional.js │ │ ├── updateNotifyApplicationReady.js │ │ ├── updateSync.js │ │ └── updateSync2x.js │ └── test.ts ├── tsconfig.json ├── tslint.json ├── typings/ │ └── react-native-code-push.d.ts ├── windows/ │ ├── .gitignore │ ├── .npmignore │ ├── CodePush/ │ │ ├── .npmignore │ │ ├── CodePush.def │ │ ├── CodePush.vcxproj │ │ ├── CodePush.vcxproj.filters │ │ ├── CodePushConfig.cpp │ │ ├── CodePushConfig.h │ │ ├── CodePushConfig.idl │ │ ├── CodePushDownloadHandler.cpp │ │ ├── CodePushDownloadHandler.h │ │ ├── CodePushNativeModule.cpp │ │ ├── CodePushNativeModule.h │ │ ├── CodePushPackage.cpp │ │ ├── CodePushPackage.h │ │ ├── CodePushTelemetryManager.cpp │ │ ├── CodePushTelemetryManager.h │ │ ├── CodePushUpdateUtils.cpp │ │ ├── CodePushUpdateUtils.h │ │ ├── CodePushUtils.cpp │ │ ├── CodePushUtils.h │ │ ├── FileUtils.cpp │ │ ├── FileUtils.h │ │ ├── PropertySheet.props │ │ ├── ReactPackageProvider.cpp │ │ ├── ReactPackageProvider.h │ │ ├── ReactPackageProvider.idl │ │ ├── miniz/ │ │ │ ├── LICENSE │ │ │ ├── miniz.c │ │ │ ├── miniz.h │ │ │ └── readme.md │ │ ├── packages.config │ │ ├── pch.cpp │ │ └── pch.h │ └── Directory.Build.props └── windows-legacy/ ├── .gitignore ├── .npmignore ├── CodePush/ │ ├── .gitignore │ ├── CodePush.csproj │ ├── CodePushUtils.cs │ ├── FileUtils.cs │ ├── Properties/ │ │ ├── AssemblyInfo.cs │ │ └── CodePush.rd.xml │ ├── UpdateManager.cs │ └── UpdateUtils.cs ├── CodePush.Net46/ │ ├── .gitignore │ ├── Adapters/ │ │ ├── Http/ │ │ │ └── HttpProgress.cs │ │ └── Storage/ │ │ └── ApplicationDataContainer.cs │ ├── CodePush.Net46.csproj │ ├── CodePushUtils.cs │ ├── FileUtils.cs │ ├── Properties/ │ │ └── AssemblyInfo.cs │ ├── UpdateManager.cs │ ├── UpdateUtils.cs │ └── packages.config ├── CodePush.Net46.Test/ │ ├── ApplicationDataContainerTest.cs │ ├── CodePush.Net46.Test.csproj │ ├── Properties/ │ │ └── AssemblyInfo.cs │ ├── TelemetryManagerTest.cs │ ├── app.config │ └── packages.config └── CodePush.Shared/ ├── CodePush.Shared.projitems ├── CodePush.Shared.shproj ├── CodePushConstants.cs ├── CodePushNativeModule.cs ├── CodePushReactPackage.cs ├── CodePushUtils.cs ├── InstallMode.cs ├── MinimumBackgroundListener.cs ├── SettingsManager.cs ├── TelemetryManager.cs └── UpdateState.cs ================================================ FILE CONTENTS ================================================ ================================================ FILE: .azurepipelines/build-rn-code-push-1es.yml ================================================ trigger: - master pr: - master resources: repositories: - repository: 1ESPipelineTemplates type: git name: 1ESPipelineTemplates/1ESPipelineTemplates ref: refs/tags/release name: $(Build.SourceBranchName)_$(date:yyyyMMdd)$(rev:.r) extends: ${{ if eq(variables['Build.SourceBranch'], 'refs/heads/master') }}: template: v1/1ES.Official.PipelineTemplate.yml@1ESPipelineTemplates ${{ else }}: template: v1/1ES.Unofficial.PipelineTemplate.yml@1ESPipelineTemplates parameters: pool: name: 1ES-PT-CBL-Mariner-2.0-Gen2 os: linux customBuildTags: - ES365AIMigrationTooling-BulkMigrated sdl: sourceAnalysisPool: 1ES-PT-Windows-2022 credscan: suppressionsFile: $(Build.SourcesDirectory)/.config/CredScanSuppressions.json stages: - stage: Stage jobs: - job: HostJob templateContext: outputs: - output: pipelineArtifact displayName: "Publish Artifact: artifacts" path: '$(Build.ArtifactStagingDirectory)/npm' artifactName: npm steps: - task: NodeTool@0 inputs: versionSpec: '14.x' displayName: 'Install Node.js' - script: | npm pack npm install -g react-native-code-push*.tgz displayName: 'Package react-native-code-push' workingDirectory: $(Build.SourcesDirectory) - task: DeleteFiles@1 inputs: contents: node_modules displayName: 'Delete node_modules' - task: ArchiveFiles@2 inputs: rootFolderOrFile: '$(Build.SourcesDirectory)' includeRootFolder: false archiveType: 'tar' archiveFile: '$(Build.ArtifactStagingDirectory)/npm/$(Build.BuildId).tgz' replaceExistingArchive: true verbose: true displayName: 'Prepare npm artifact' - stage: APIScan dependsOn: Stage pool: name: 1ES-PT-Windows-2022 os: windows variables: "agent.source.skip": true jobs: - job: APIScan steps: - task: DownloadPipelineArtifact@2 displayName: Download Build Artifacts for APIScan inputs: artifactName: npm targetPath: '$(Agent.BuildDirectory)/npm' - task: ExtractFiles@1 inputs: archiveFilePatterns: '$(Agent.BuildDirectory)/npm/*.tgz' destinationFolder: '$(Agent.BuildDirectory)/npm_extracted' - task: AzureKeyVault@2 inputs: azureSubscription: 'AC - Dev Infra & Build Pool' KeyVaultName: 'mobile-center-sdk' SecretsFilter: 'appcenter-sdk-managed-identity-clientid' RunAsPreJob: false - task: APIScan@2 displayName: 'Run APIScan' inputs: softwareFolder: '$(Agent.BuildDirectory)\npm_extracted' softwareName: 'react-native-code-push' softwareVersionNum: '$(Build.BuildId)' isLargeApp: false toolVersion: 'Latest' verbosityLevel: verbose condition: and(succeeded(), ne(variables['DisableAPIScan'], 'true')) env: AzureServicesAuthConnectionString: 'runAs=App;AppId=$(appcenter-sdk-managed-identity-clientid)' ================================================ FILE: .azurepipelines/test-rn-code-push.yml ================================================ trigger: - master pr: - master variables: - name: api-level value: '27' pool: vmImage: 'macOS-12' stages: - stage: RunTests displayName: 'Run Android & IOS tests' jobs: - job: TestAndroid timeoutInMinutes: 120 displayName: 'Test android' steps: - script: | adb devices displayName: 'Start adb server' - script: | $ANDROID_HOME/tools/bin/sdkmanager "system-images;android-$(api-level);google_apis;x86" displayName: 'Download system image' - script: | $ANDROID_HOME/tools/bin/avdmanager create avd --force --name TestEmulator --abi google_apis/x86 --package 'system-images;android-$(api-level);google_apis;x86' --device "Nexus 6P" displayName: 'Creating Android emulator' - script: | $ANDROID_HOME/emulator/emulator -avd TestEmulator -noaudio -no-window -no-snapshot-save -no-boot-anim -memory 6144 & displayName: 'Start Android emulator' - script: | $ANDROID_HOME/platform-tools/adb wait-for-device shell 'while [[ -z $(getprop sys.boot_completed | tr -d '\r') ]]; do sleep 1; done' displayName: 'Wait for emulator to boot' - script: | adb shell settings put global window_animation_scale 0.0 displayName: 'Disable animations and transitions' - script: | adb shell settings put global transition_animation_scale 0.0 displayName: 'Disable animations and transitions' - script: | adb shell settings put global animator_duration_scale 0.0 displayName: 'Disable animations and transitions' - task: JavaToolInstaller@0 inputs: versionSpec: '11' jdkArchitectureOption: 'x64' jdkSourceOption: 'PreInstalled' displayName: 'Change Java version' - script: | npm install displayName: 'Package Installation' - script: | npm run build:tests && npm run test:setup:android displayName: 'Setup Android tests' - script: | npm run test:fast:android displayName: 'Run Android test' - job: TestIOS timeoutInMinutes: 120 displayName: 'Test IOS' steps: - script: | npm install displayName: 'Install dependencies' - script: | npm run build:tests && npm run test:setup:ios displayName: 'Setup iOS tests' - script: | npm run test:fast:ios displayName: 'Run tests' ================================================ FILE: .config/CredScanSuppressions.json ================================================ { "tool": "Credential Scanner", "suppressions": [ { "file": "/Examples/CodePushDemoApp/android/app/debug.keystore", "_justification": "Used only in DemoApp" }, { "file": "/Examples/CodePushDemoAppCpp/windows/CodePushDemoAppCpp/CodePushDemoAppCpp_TemporaryKey.pfx", "_justification": "Used only in DemoApp" } ] } ================================================ FILE: .github/CODEOWNERS ================================================ * @microsoft/appcenter-fte ================================================ FILE: .github/ISSUE_TEMPLATE.md ================================================ Thanks so much for filing an issue or feature request! Please fill out the following (wherever relevant): ### Steps to Reproduce 1. 2. 3. ### Expected Behavior What you expected to happen? ### Actual Behavior What actually happens? ``` STACK TRACE AND/OR SCREENSHOTS ``` ### Reproducible Demo * Download https://github.com/microsoft/react-native-code-push/archive/master.zip and unzip. From `Examples` folder run `node create-app.js appName react-native@0.71.19 react-native-code-push@9.0.1` command to generate plain CodePushified React Native app. Please see description on top of `create-app.js` file content if needed * If you can't reproduce the bug on it, provide us as much info as possible about your project ### Environment * react-native-code-push version: * react-native version: * iOS/Android/Windows version: * Does this reproduce on a debug build or release build? * Does this reproduce on a simulator, or only on a physical device? (The more info the faster we will be able to address it!) ================================================ FILE: .github/policies/resourceManagement.yml ================================================ id: name: GitOps.PullRequestIssueManagement description: GitOps.PullRequestIssueManagement primitive owner: resource: repository disabled: false where: configuration: resourceManagementConfiguration: scheduledSearches: - description: frequencies: - hourly: hour: 4 filters: - isOpen - isNotLabeledWith: label: bug - isNotLabeledWith: label: security - isNotLabeledWith: label: stale - isNotLabeledWith: label: do not close - noActivitySince: days: 60 - isIssue - isNotAssigned actions: - addLabel: label: stale - addReply: reply: This issue has been automatically marked as stale because it has not had any activity for 60 days. It will be closed if no further activity occurs within 15 days of this comment. - description: frequencies: - hourly: hour: 6 filters: - isOpen - isIssue - hasLabel: label: stale - isNotLabeledWith: label: bug - isNotLabeledWith: label: do not close - isNotAssigned - noActivitySince: days: 15 actions: - addReply: reply: This issue will now be closed because it hasn't had any activity for 15 days after stale. Please feel free to open a new issue if you still have a question/issue or suggestion. - closeIssue eventResponderTasks: - if: - payloadType: Issue_Comment - hasLabel: label: stale then: - removeLabel: label: stale description: onFailure: onSuccess: ================================================ FILE: .gitignore ================================================ # gitignore contributors: remember to update .npmignore # OSX # .DS_Store # Xcode # # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore ## Build generated build/ DerivedData ## Various settings *.pbxuser !default.pbxuser *.mode1v3 !default.mode1v3 *.mode2v3 !default.mode2v3 *.perspectivev3 !default.perspectivev3 xcuserdata ## Other *.xccheckout *.moved-aside *.xcuserstate ## Obj-C/Swift specific *.hmap *.ipa # CocoaPods # # We recommend against adding the Pods directory to your .gitignore. However # you should judge for yourself, the pros and cons are mentioned at: # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control # #Pods/ # Carthage # # Add this line if you want to avoid checking in source code from Carthage dependencies. # Carthage/Checkouts Carthage/Build ### Node # Logs logs *.log # Runtime data pids *.pid *.seed # Directory for instrumented libs generated by jscoverage/JSCover lib-cov # Coverage directory used by tools like istanbul coverage # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) .grunt # node-waf configuration .lock-wscript # Compiled binary addons (http://nodejs.org/api/addons.html) build/Release # Dependency directory # https://docs.npmjs.com/misc/faq#should-i-check-my-node-modules-folder-into-git node_modules # Xcode # # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore ## Build generated build/ DerivedData ## Various settings *.pbxuser !default.pbxuser *.mode1v3 !default.mode1v3 *.mode2v3 !default.mode2v3 *.perspectivev3 !default.perspectivev3 xcuserdata ## OSX .DS_Store ## Other *.xccheckout *.moved-aside *.xcuserstate # Intellij project files *.iml *.ipr *.iws .idea/ #Gradle .gradletasknamecache .gradle/ build/ bin/ # Built application files *.apk *.ap_ # Files for the Dalvik VM *.dex # Java class files *.class # Generated files bin/ gen/ # Gradle files .gradle/ build/ */build/ # Local configuration file (sdk path, etc) local.properties # Proguard folder generated by Eclipse proguard/ # Log Files *.log # Android Studio Navigation editor temp files .navigation/ # Android Studio captures folder captures/ # Remove after this framework is published on NPM code-push-plugin-testing-framework/node_modules # Windows windows/.vs/ windows/obj/ #Visual Studio files *.[Oo]bj *.user *.aps *.pch *.vspscc *.vssscc *_i.c *_p.c *.ncb *.suo *.tlb *.tlh *.bak *.[Cc]ache *.ilk *.log *.lib *.sbr *.sdf *.opensdf *.opendb *.unsuccessfulbuild ipch/ [Oo]bj/ [Bb]in [Dd]ebug*/ [Rr]elease*/ Ankh.NoLoad # RN New Version App Generation Examples/testapp_rn # Android debug build files (conflict ignoring #Visual Studio files) !android/app/src/debug/ ================================================ FILE: .npmignore ================================================ # OSX # .DS_Store # Xcode # build/ *.pbxuser !default.pbxuser *.mode1v3 !default.mode1v3 *.mode2v3 !default.mode2v3 *.perspectivev3 !default.perspectivev3 xcuserdata *.xccheckout *.moved-aside DerivedData *.hmap *.ipa *.xcuserstate # node.js # node_modules/ npm-debug.log # Don't publish example apps Examples/ Recipes/ # Don't publish testing code bin/ test/ # Remove after this framework is published on NPM code-push-plugin-testing-framework/ # Android build artifacts and Android Studio bits android/app/build android/local.properties android/.gradle android/**/*.iml android/.idea # Windows windows/.vs/ windows/obj/ #Tests windows/CodePush.Net46.Test #Visual Studio files *.[Oo]bj *.user *.aps *.pch *.vspscc *.vssscc *_i.c *_p.c *.ncb *.suo *.tlb *.tlh *.bak *.[Cc]ache *.ilk *.log *.lib *.sbr *.sdf *.opensdf *.opendb *.unsuccessfulbuild ipch/ [Oo]bj/ [Bb]in [Dd]ebug*/ [Rr]elease*/ Ankh.NoLoad #NuGet packages/ *.nupkg # VSCode .vscode/ # IntelliJIDEA .idea/ # Github .github/ # Git .git/ .watchmanconfig ================================================ FILE: .vscode/launch.json ================================================ { "version": "0.2.0", "configurations": [ { "name": "Tests-android", "type": "node", "request": "launch", "preLaunchTask": "Setup-android", "runtimeExecutable": "npm", "runtimeArgs": [ "run", "test:debugger:android" ], "port": 9229, "stopOnEntry": false, "sourceMaps": true, "console": "internalConsole", "internalConsoleOptions": "openOnSessionStart", "autoAttachChildProcesses": true, "timeout": 100000 }, { "name": "Tests-ios", "type": "node", "request": "launch", "preLaunchTask": "Setup-ios", "runtimeExecutable": "npm", "runtimeArgs": [ "run", "test:debugger:ios" ], "port": 9229, "stopOnEntry": false, "sourceMaps": true, "console": "internalConsole", "internalConsoleOptions": "openOnSessionStart", "autoAttachChildProcesses": true, "timeout": 100000 } ] } ================================================ FILE: .vscode/settings.json ================================================ { "typescript.tsdk": "node_modules/typescript/lib" } ================================================ FILE: .vscode/tasks.json ================================================ { "version": "2.0.0", "tasks": [ { "type": "shell", "label": "Build", "command": "npm", "args": [ "run", "build:tests" ], "presentation": { "echo": false, "focus": false }, "problemMatcher": [ "$tsc" ] }, { "type": "shell", "label": "Setup-android", "dependsOn": "Build", "command": "npm", "args": [ "run", "test:setup:android" ], "presentation": { "echo": false, "focus": false }, "problemMatcher": [ "$tsc" ] }, { "type": "shell", "label": "Setup-ios", "dependsOn": "Build", "command": "npm", "args": [ "run", "test:setup:ios" ], "presentation": { "echo": false, "focus": false }, "problemMatcher": [ "$tsc" ] } ] } ================================================ FILE: .watchmanconfig ================================================ {} ================================================ FILE: AlertAdapter.js ================================================ import React, { Platform } from "react-native"; let { Alert } = React; if (Platform.OS === "android") { const { NativeModules: { CodePushDialog } } = React; Alert = { alert(title, message, buttons) { if (buttons.length > 2) { throw "Can only show 2 buttons for Android dialog."; } const button1Text = buttons[0] ? buttons[0].text : null, button2Text = buttons[1] ? buttons[1].text : null; CodePushDialog.showDialog( title, message, button1Text, button2Text, (buttonId) => { buttons[buttonId].onPress && buttons[buttonId].onPress(); }, (error) => { throw error; }); } }; } module.exports = { Alert }; ================================================ FILE: CONTRIBUTING.md ================================================ # Contributing ## Using the plugin ### Environment setup `node.js` and `npm` are needed for using this project. `npm` comes bundled with the `node.js` installer. You can download the `node.js` installer here: https://nodejs.org/download/. Once you have installed `node.js` and `npm`, install the dev dependencies for the project. ``` npm install ``` ### Using the plugin manually Follow these steps to test your modifications to the plugin manually: - clone this repository - install the dependencies Navigate to the root folder from your command line console and run: ``` npm install ``` - install the plugin in a React-Native project Navigate to the root folder of your React-Native project from your command line console and run: ``` npm install local_path_to_your_clone_of_this_repo ``` - configure the plugin using the steps in the README.md - build and run your app on an emulator or device ## Test ### Environment setup First, make sure you have installed the dependencies for the plugin by following the steps above. Then, make sure you have installed `react-native`. ``` npm install -g react-native ``` To run Android tests, make sure you have `sdk\tools`, `sdk\emulator` and `sdk\platform-tools` in your PATH. To run iOS tests, make sure you've installed CocoaPods and have `.gem/bin` in your PATH. ### Supported platforms The plugin has end to end tests for Android and iOS. Depending on your development machine OS, you can run some or all the tests. OS | Supported tests ------------- | ------------- OS X | Android, iOS Windows | Android ### Test descriptions The tests first build the app. They then check if the required emulators are currently running. If an Android emulator is not running, it attempts to boot the latest Android emulator. You can specify an emulator by adding env variable `ANDROID_EMU=yourEmulatorNameHere` to the npm command. For example: `ANDROID_EMU=yourEmulatorNameHere npm run test:android`. If an iOS simulator is not running, it attempts to boot the latest iOS iPhone simulator. You can specify a simulator by adding env variable `IOS_EMU=yourSimulatorNameHere` to the npm command. For example: `IOS_EMU="iPhone 8 (0567DFF8-329E-41A3-BD6D-E48E9DD5EF39)" npm run test:ios`. If all the required emulators are not running and the tests fail to boot them, the tests will fail. If you would like the tests to always restart the necessary emulators (killing them if they are currently running), setup a env variable `CLEAN=true` to the command. For example: `CLEAN=true npm run test`. The desired unit tests are then run. If you would like to skip building, add a `:fast` in the command you'd like to run. For example, `npm run test:ios` becomes `npm run test:fast:ios` or `npm run test:android` becomes `npm run test:fast:android`. There is a both a full unit test suite and a "core" set of unit tests that you may run. If you would like to run only the core tests, setup a env variable `CORE=true` to the command. For example: `CORE=true npm run test:android`. If you would like to pull the plugin from NPM rather than running the tests on the local version, setup a env variable `NPM=true` to the command. For example: `NPM=true npm run test:ios`. #### Default To run all of the unit tests on Android and iOS: ``` npm run test ``` #### iOS To run all of the unit tests on iOS: ``` npm run test:ios ``` #### Android To run all of the unit tests on Android: ``` npm run test:android ``` #### More examples All possible testing configurations have tasks! The platforms are ordered as follows, and ran in that order: android, ios To run the core unit tests on Android: ``` CORE=true npm run test:android ``` To run all of the unit tests on iOS and pull the plugin from NPM: ``` NPM=true npm run test:ios ``` To run all of the unit tests on Android and iOS without building first: ``` npm run test:fast ``` To run all of the unit tests on iOS and restart the emulators: ``` CLEAN=true npm run test:ios ``` To run the core unit tests on Android and pull the plugin from NPM: ``` NPM=true CORE=true npm run test:android ``` ...and so on! ================================================ FILE: CodePush.js ================================================ import { AcquisitionManager as Sdk } from "code-push/script/acquisition-sdk"; import { Alert } from "./AlertAdapter"; import requestFetchAdapter from "./request-fetch-adapter"; import { AppState, Platform } from "react-native"; import log from "./logging"; import hoistStatics from 'hoist-non-react-statics'; let NativeCodePush = require("react-native").NativeModules.CodePush; const PackageMixins = require("./package-mixins")(NativeCodePush); async function checkForUpdate(deploymentKey = null, handleBinaryVersionMismatchCallback = null) { /* * Before we ask the server if an update exists, we * need to retrieve three pieces of information from the * native side: deployment key, app version (e.g. 1.0.1) * and the hash of the currently running update (if there is one). * This allows the client to only receive updates which are targetted * for their specific deployment and version and which are actually * different from the CodePush update they have already installed. */ const nativeConfig = await getConfiguration(); /* * If a deployment key was explicitly provided, * then let's override the one we retrieved * from the native-side of the app. This allows * dynamically "redirecting" end-users at different * deployments (e.g. an early access deployment for insiders). */ const config = deploymentKey ? { ...nativeConfig, ...{ deploymentKey } } : nativeConfig; const sdk = getPromisifiedSdk(requestFetchAdapter, config); // Use dynamically overridden getCurrentPackage() during tests. const localPackage = await module.exports.getCurrentPackage(); /* * If the app has a previously installed update, and that update * was targetted at the same app version that is currently running, * then we want to use its package hash to determine whether a new * release has been made on the server. Otherwise, we only need * to send the app version to the server, since we are interested * in any updates for current binary version, regardless of hash. */ let queryPackage; if (localPackage) { queryPackage = localPackage; } else { queryPackage = { appVersion: config.appVersion }; if (Platform.OS === "ios" && config.packageHash) { queryPackage.packageHash = config.packageHash; } } const update = await sdk.queryUpdateWithCurrentPackage(queryPackage); /* * There are four cases where checkForUpdate will resolve to null: * ---------------------------------------------------------------- * 1) The server said there isn't an update. This is the most common case. * 2) The server said there is an update but it requires a newer binary version. * This would occur when end-users are running an older binary version than * is available, and CodePush is making sure they don't get an update that * potentially wouldn't be compatible with what they are running. * 3) The server said there is an update, but the update's hash is the same as * the currently running update. This should _never_ happen, unless there is a * bug in the server, but we're adding this check just to double-check that the * client app is resilient to a potential issue with the update check. * 4) The server said there is an update, but the update's hash is the same as that * of the binary's currently running version. This should only happen in Android - * unlike iOS, we don't attach the binary's hash to the updateCheck request * because we want to avoid having to install diff updates against the binary's * version, which we can't do yet on Android. */ if (!update || update.updateAppVersion || localPackage && (update.packageHash === localPackage.packageHash) || (!localPackage || localPackage._isDebugOnly) && config.packageHash === update.packageHash) { if (update && update.updateAppVersion) { log("An update is available but it is not targeting the binary version of your app."); if (handleBinaryVersionMismatchCallback && typeof handleBinaryVersionMismatchCallback === "function") { handleBinaryVersionMismatchCallback(update) } } return null; } else { const remotePackage = { ...update, ...PackageMixins.remote(sdk.reportStatusDownload) }; remotePackage.failedInstall = await NativeCodePush.isFailedUpdate(remotePackage.packageHash); remotePackage.deploymentKey = deploymentKey || nativeConfig.deploymentKey; return remotePackage; } } const getConfiguration = (() => { let config; return async function getConfiguration() { if (config) { return config; } else if (testConfig) { return testConfig; } else { config = await NativeCodePush.getConfiguration(); return config; } } })(); async function getCurrentPackage() { return await getUpdateMetadata(CodePush.UpdateState.LATEST); } async function getUpdateMetadata(updateState) { let updateMetadata = await NativeCodePush.getUpdateMetadata(updateState || CodePush.UpdateState.RUNNING); if (updateMetadata) { updateMetadata = {...PackageMixins.local, ...updateMetadata}; updateMetadata.failedInstall = await NativeCodePush.isFailedUpdate(updateMetadata.packageHash); updateMetadata.isFirstRun = await NativeCodePush.isFirstRun(updateMetadata.packageHash); } return updateMetadata; } function getPromisifiedSdk(requestFetchAdapter, config) { // Use dynamically overridden AcquisitionSdk during tests. const sdk = new module.exports.AcquisitionSdk(requestFetchAdapter, config); sdk.queryUpdateWithCurrentPackage = (queryPackage) => { return new Promise((resolve, reject) => { module.exports.AcquisitionSdk.prototype.queryUpdateWithCurrentPackage.call(sdk, queryPackage, (err, update) => { if (err) { reject(err); } else { resolve(update); } }); }); }; sdk.reportStatusDeploy = (deployedPackage, status, previousLabelOrAppVersion, previousDeploymentKey) => { return new Promise((resolve, reject) => { module.exports.AcquisitionSdk.prototype.reportStatusDeploy.call(sdk, deployedPackage, status, previousLabelOrAppVersion, previousDeploymentKey, (err) => { if (err) { reject(err); } else { resolve(); } }); }); }; sdk.reportStatusDownload = (downloadedPackage) => { return new Promise((resolve, reject) => { module.exports.AcquisitionSdk.prototype.reportStatusDownload.call(sdk, downloadedPackage, (err) => { if (err) { reject(err); } else { resolve(); } }); }); }; return sdk; } // This ensures that notifyApplicationReadyInternal is only called once // in the lifetime of this module instance. const notifyApplicationReady = (() => { let notifyApplicationReadyPromise; return () => { if (!notifyApplicationReadyPromise) { notifyApplicationReadyPromise = notifyApplicationReadyInternal(); } return notifyApplicationReadyPromise; }; })(); async function notifyApplicationReadyInternal() { await NativeCodePush.notifyApplicationReady(); const statusReport = await NativeCodePush.getNewStatusReport(); statusReport && tryReportStatus(statusReport); // Don't wait for this to complete. return statusReport; } async function tryReportStatus(statusReport, retryOnAppResume) { const config = await getConfiguration(); const previousLabelOrAppVersion = statusReport.previousLabelOrAppVersion; const previousDeploymentKey = statusReport.previousDeploymentKey || config.deploymentKey; try { if (statusReport.appVersion) { log(`Reporting binary update (${statusReport.appVersion})`); if (!config.deploymentKey) { throw new Error("Deployment key is missed"); } const sdk = getPromisifiedSdk(requestFetchAdapter, config); await sdk.reportStatusDeploy(/* deployedPackage */ null, /* status */ null, previousLabelOrAppVersion, previousDeploymentKey); } else { const label = statusReport.package.label; if (statusReport.status === "DeploymentSucceeded") { log(`Reporting CodePush update success (${label})`); } else { log(`Reporting CodePush update rollback (${label})`); await NativeCodePush.setLatestRollbackInfo(statusReport.package.packageHash); } config.deploymentKey = statusReport.package.deploymentKey; const sdk = getPromisifiedSdk(requestFetchAdapter, config); await sdk.reportStatusDeploy(statusReport.package, statusReport.status, previousLabelOrAppVersion, previousDeploymentKey); } NativeCodePush.recordStatusReported(statusReport); retryOnAppResume && retryOnAppResume.remove(); } catch (e) { log(`Report status failed: ${JSON.stringify(statusReport)}`); NativeCodePush.saveStatusReportForRetry(statusReport); // Try again when the app resumes if (!retryOnAppResume) { const resumeListener = AppState.addEventListener("change", async (newState) => { if (newState !== "active") return; const refreshedStatusReport = await NativeCodePush.getNewStatusReport(); if (refreshedStatusReport) { tryReportStatus(refreshedStatusReport, resumeListener); } else { resumeListener && resumeListener.remove(); } }); } } } async function shouldUpdateBeIgnored(remotePackage, syncOptions) { let { rollbackRetryOptions } = syncOptions; const isFailedPackage = remotePackage && remotePackage.failedInstall; if (!isFailedPackage || !syncOptions.ignoreFailedUpdates) { return false; } if (!rollbackRetryOptions) { return true; } if (typeof rollbackRetryOptions !== "object") { rollbackRetryOptions = CodePush.DEFAULT_ROLLBACK_RETRY_OPTIONS; } else { rollbackRetryOptions = { ...CodePush.DEFAULT_ROLLBACK_RETRY_OPTIONS, ...rollbackRetryOptions }; } if (!validateRollbackRetryOptions(rollbackRetryOptions)) { return true; } const latestRollbackInfo = await NativeCodePush.getLatestRollbackInfo(); if (!validateLatestRollbackInfo(latestRollbackInfo, remotePackage.packageHash)) { log("The latest rollback info is not valid."); return true; } const { delayInHours, maxRetryAttempts } = rollbackRetryOptions; const hoursSinceLatestRollback = (Date.now() - latestRollbackInfo.time) / (1000 * 60 * 60); if (hoursSinceLatestRollback >= delayInHours && maxRetryAttempts >= latestRollbackInfo.count) { log("Previous rollback should be ignored due to rollback retry options."); return false; } return true; } function validateLatestRollbackInfo(latestRollbackInfo, packageHash) { return latestRollbackInfo && latestRollbackInfo.time && latestRollbackInfo.count && latestRollbackInfo.packageHash && latestRollbackInfo.packageHash === packageHash; } function validateRollbackRetryOptions(rollbackRetryOptions) { if (typeof rollbackRetryOptions.delayInHours !== "number") { log("The 'delayInHours' rollback retry parameter must be a number."); return false; } if (typeof rollbackRetryOptions.maxRetryAttempts !== "number") { log("The 'maxRetryAttempts' rollback retry parameter must be a number."); return false; } if (rollbackRetryOptions.maxRetryAttempts < 1) { log("The 'maxRetryAttempts' rollback retry parameter cannot be less then 1."); return false; } return true; } var testConfig; // This function is only used for tests. Replaces the default SDK, configuration and native bridge function setUpTestDependencies(testSdk, providedTestConfig, testNativeBridge) { if (testSdk) module.exports.AcquisitionSdk = testSdk; if (providedTestConfig) testConfig = providedTestConfig; if (testNativeBridge) NativeCodePush = testNativeBridge; } async function restartApp(onlyIfUpdateIsPending = false) { NativeCodePush.restartApp(onlyIfUpdateIsPending); } // This function allows only one syncInternal operation to proceed at any given time. // Parallel calls to sync() while one is ongoing yields CodePush.SyncStatus.SYNC_IN_PROGRESS. const sync = (() => { let syncInProgress = false; const setSyncCompleted = () => { syncInProgress = false; }; return (options = {}, syncStatusChangeCallback, downloadProgressCallback, handleBinaryVersionMismatchCallback) => { let syncStatusCallbackWithTryCatch, downloadProgressCallbackWithTryCatch; if (typeof syncStatusChangeCallback === "function") { syncStatusCallbackWithTryCatch = (...args) => { try { syncStatusChangeCallback(...args); } catch (error) { log(`An error has occurred : ${error.stack}`); } } } if (typeof downloadProgressCallback === "function") { downloadProgressCallbackWithTryCatch = (...args) => { try { downloadProgressCallback(...args); } catch (error) { log(`An error has occurred: ${error.stack}`); } } } if (syncInProgress) { typeof syncStatusCallbackWithTryCatch === "function" ? syncStatusCallbackWithTryCatch(CodePush.SyncStatus.SYNC_IN_PROGRESS) : log("Sync already in progress."); return Promise.resolve(CodePush.SyncStatus.SYNC_IN_PROGRESS); } syncInProgress = true; const syncPromise = syncInternal(options, syncStatusCallbackWithTryCatch, downloadProgressCallbackWithTryCatch, handleBinaryVersionMismatchCallback); syncPromise .then(setSyncCompleted) .catch(setSyncCompleted); return syncPromise; }; })(); /* * The syncInternal method provides a simple, one-line experience for * incorporating the check, download and installation of an update. * * It simply composes the existing API methods together and adds additional * support for respecting mandatory updates, ignoring previously failed * releases, and displaying a standard confirmation UI to the end-user * when an update is available. */ async function syncInternal(options = {}, syncStatusChangeCallback, downloadProgressCallback, handleBinaryVersionMismatchCallback) { let resolvedInstallMode; const syncOptions = { deploymentKey: null, ignoreFailedUpdates: true, rollbackRetryOptions: null, installMode: CodePush.InstallMode.ON_NEXT_RESTART, mandatoryInstallMode: CodePush.InstallMode.IMMEDIATE, minimumBackgroundDuration: 0, updateDialog: null, ...options }; syncStatusChangeCallback = typeof syncStatusChangeCallback === "function" ? syncStatusChangeCallback : (syncStatus) => { switch(syncStatus) { case CodePush.SyncStatus.CHECKING_FOR_UPDATE: log("Checking for update."); break; case CodePush.SyncStatus.AWAITING_USER_ACTION: log("Awaiting user action."); break; case CodePush.SyncStatus.DOWNLOADING_PACKAGE: log("Downloading package."); break; case CodePush.SyncStatus.INSTALLING_UPDATE: log("Installing update."); break; case CodePush.SyncStatus.UP_TO_DATE: log("App is up to date."); break; case CodePush.SyncStatus.UPDATE_IGNORED: log("User cancelled the update."); break; case CodePush.SyncStatus.UPDATE_INSTALLED: if (resolvedInstallMode == CodePush.InstallMode.ON_NEXT_RESTART) { log("Update is installed and will be run on the next app restart."); } else if (resolvedInstallMode == CodePush.InstallMode.ON_NEXT_RESUME) { if (syncOptions.minimumBackgroundDuration > 0) { log(`Update is installed and will be run after the app has been in the background for at least ${syncOptions.minimumBackgroundDuration} seconds.`); } else { log("Update is installed and will be run when the app next resumes."); } } break; case CodePush.SyncStatus.UNKNOWN_ERROR: log("An unknown error occurred."); break; } }; try { await CodePush.notifyApplicationReady(); syncStatusChangeCallback(CodePush.SyncStatus.CHECKING_FOR_UPDATE); const remotePackage = await checkForUpdate(syncOptions.deploymentKey, handleBinaryVersionMismatchCallback); const doDownloadAndInstall = async () => { syncStatusChangeCallback(CodePush.SyncStatus.DOWNLOADING_PACKAGE); const localPackage = await remotePackage.download(downloadProgressCallback); // Determine the correct install mode based on whether the update is mandatory or not. resolvedInstallMode = localPackage.isMandatory ? syncOptions.mandatoryInstallMode : syncOptions.installMode; syncStatusChangeCallback(CodePush.SyncStatus.INSTALLING_UPDATE); await localPackage.install(resolvedInstallMode, syncOptions.minimumBackgroundDuration, () => { syncStatusChangeCallback(CodePush.SyncStatus.UPDATE_INSTALLED); }); return CodePush.SyncStatus.UPDATE_INSTALLED; }; const updateShouldBeIgnored = await shouldUpdateBeIgnored(remotePackage, syncOptions); if (!remotePackage || updateShouldBeIgnored) { if (updateShouldBeIgnored) { log("An update is available, but it is being ignored due to having been previously rolled back."); } const currentPackage = await CodePush.getCurrentPackage(); if (currentPackage && currentPackage.isPending) { syncStatusChangeCallback(CodePush.SyncStatus.UPDATE_INSTALLED); return CodePush.SyncStatus.UPDATE_INSTALLED; } else { syncStatusChangeCallback(CodePush.SyncStatus.UP_TO_DATE); return CodePush.SyncStatus.UP_TO_DATE; } } else if (syncOptions.updateDialog) { // updateDialog supports any truthy value (e.g. true, "goo", 12), // but we should treat a non-object value as just the default dialog if (typeof syncOptions.updateDialog !== "object") { syncOptions.updateDialog = CodePush.DEFAULT_UPDATE_DIALOG; } else { syncOptions.updateDialog = { ...CodePush.DEFAULT_UPDATE_DIALOG, ...syncOptions.updateDialog }; } return await new Promise((resolve, reject) => { let message = null; let installButtonText = null; const dialogButtons = []; if (remotePackage.isMandatory) { message = syncOptions.updateDialog.mandatoryUpdateMessage; installButtonText = syncOptions.updateDialog.mandatoryContinueButtonLabel; } else { message = syncOptions.updateDialog.optionalUpdateMessage; installButtonText = syncOptions.updateDialog.optionalInstallButtonLabel; // Since this is an optional update, add a button // to allow the end-user to ignore it dialogButtons.push({ text: syncOptions.updateDialog.optionalIgnoreButtonLabel, onPress: () => { syncStatusChangeCallback(CodePush.SyncStatus.UPDATE_IGNORED); resolve(CodePush.SyncStatus.UPDATE_IGNORED); } }); } // Since the install button should be placed to the // right of any other button, add it last dialogButtons.push({ text: installButtonText, onPress:() => { doDownloadAndInstall() .then(resolve, reject); } }) // If the update has a description, and the developer // explicitly chose to display it, then set that as the message if (syncOptions.updateDialog.appendReleaseDescription && remotePackage.description) { message += `${syncOptions.updateDialog.descriptionPrefix} ${remotePackage.description}`; } syncStatusChangeCallback(CodePush.SyncStatus.AWAITING_USER_ACTION); Alert.alert(syncOptions.updateDialog.title, message, dialogButtons); }); } else { return await doDownloadAndInstall(); } } catch (error) { syncStatusChangeCallback(CodePush.SyncStatus.UNKNOWN_ERROR); log(error.message); throw error; } }; let CodePush; function codePushify(options = {}) { let React; let ReactNative = require("react-native"); try { React = require("react"); } catch (e) { } if (!React) { try { React = ReactNative.React; } catch (e) { } if (!React) { throw new Error("Unable to find the 'React' module."); } } if (!React.Component) { throw new Error( `Unable to find the "Component" class, please either: 1. Upgrade to a newer version of React Native that supports it, or 2. Call the codePush.sync API in your component instead of using the @codePush decorator` ); } const decorator = (RootComponent) => { class CodePushComponent extends React.Component { constructor(props) { super(props); this.rootComponentRef = React.createRef(); } componentDidMount() { if (options.checkFrequency === CodePush.CheckFrequency.MANUAL) { CodePush.notifyAppReady(); } else { const rootComponentInstance = this.rootComponentRef.current; let syncStatusCallback; if (rootComponentInstance && rootComponentInstance.codePushStatusDidChange) { syncStatusCallback = rootComponentInstance.codePushStatusDidChange.bind(rootComponentInstance); } let downloadProgressCallback; if (rootComponentInstance && rootComponentInstance.codePushDownloadDidProgress) { downloadProgressCallback = rootComponentInstance.codePushDownloadDidProgress.bind(rootComponentInstance); } let handleBinaryVersionMismatchCallback; if (rootComponentInstance && rootComponentInstance.codePushOnBinaryVersionMismatch) { handleBinaryVersionMismatchCallback = rootComponentInstance.codePushOnBinaryVersionMismatch.bind(rootComponentInstance); } CodePush.sync(options, syncStatusCallback, downloadProgressCallback, handleBinaryVersionMismatchCallback); if (options.checkFrequency === CodePush.CheckFrequency.ON_APP_RESUME) { ReactNative.AppState.addEventListener("change", (newState) => { if (newState === "active") { CodePush.sync(options, syncStatusCallback, downloadProgressCallback); } }); } } } render() { const props = {...this.props}; // We can set ref property on class components only (not stateless) // Check it by render method if (RootComponent.prototype && RootComponent.prototype.render) { props.ref = this.rootComponentRef; } return } } return hoistStatics(CodePushComponent, RootComponent); } if (typeof options === "function") { // Infer that the root component was directly passed to us. return decorator(options); } else { return decorator; } } // If the "NativeCodePush" variable isn't defined, then // the app didn't properly install the native module, // and therefore, it doesn't make sense initializing // the JS interface when it wouldn't work anyways. if (NativeCodePush) { CodePush = codePushify; Object.assign(CodePush, { AcquisitionSdk: Sdk, checkForUpdate, getConfiguration, getCurrentPackage, getUpdateMetadata, log, notifyAppReady: notifyApplicationReady, notifyApplicationReady, restartApp, setUpTestDependencies, sync, disallowRestart: NativeCodePush.disallow, allowRestart: NativeCodePush.allow, clearUpdates: NativeCodePush.clearUpdates, InstallMode: { IMMEDIATE: NativeCodePush.codePushInstallModeImmediate, // Restart the app immediately ON_NEXT_RESTART: NativeCodePush.codePushInstallModeOnNextRestart, // Don't artificially restart the app. Allow the update to be "picked up" on the next app restart ON_NEXT_RESUME: NativeCodePush.codePushInstallModeOnNextResume, // Restart the app the next time it is resumed from the background ON_NEXT_SUSPEND: NativeCodePush.codePushInstallModeOnNextSuspend // Restart the app _while_ it is in the background, // but only after it has been in the background for "minimumBackgroundDuration" seconds (0 by default), // so that user context isn't lost unless the app suspension is long enough to not matter }, SyncStatus: { UP_TO_DATE: 0, // The running app is up-to-date UPDATE_INSTALLED: 1, // The app had an optional/mandatory update that was successfully downloaded and is about to be installed. UPDATE_IGNORED: 2, // The app had an optional update and the end-user chose to ignore it UNKNOWN_ERROR: 3, SYNC_IN_PROGRESS: 4, // There is an ongoing "sync" operation in progress. CHECKING_FOR_UPDATE: 5, AWAITING_USER_ACTION: 6, DOWNLOADING_PACKAGE: 7, INSTALLING_UPDATE: 8 }, CheckFrequency: { ON_APP_START: 0, ON_APP_RESUME: 1, MANUAL: 2 }, UpdateState: { RUNNING: NativeCodePush.codePushUpdateStateRunning, PENDING: NativeCodePush.codePushUpdateStatePending, LATEST: NativeCodePush.codePushUpdateStateLatest }, DeploymentStatus: { FAILED: "DeploymentFailed", SUCCEEDED: "DeploymentSucceeded", }, DEFAULT_UPDATE_DIALOG: { appendReleaseDescription: false, descriptionPrefix: " Description: ", mandatoryContinueButtonLabel: "Continue", mandatoryUpdateMessage: "An update is available that must be installed.", optionalIgnoreButtonLabel: "Ignore", optionalInstallButtonLabel: "Install", optionalUpdateMessage: "An update is available. Would you like to install it?", title: "Update available" }, DEFAULT_ROLLBACK_RETRY_OPTIONS: { delayInHours: 24, maxRetryAttempts: 1 } }); } else { log("The CodePush module doesn't appear to be properly installed. Please double-check that everything is setup correctly."); } module.exports = CodePush; ================================================ FILE: CodePush.podspec ================================================ require 'json' package = JSON.parse(File.read(File.join(__dir__, 'package.json'))) Pod::Spec.new do |s| s.name = 'CodePush' s.version = package['version'].gsub(/v|-beta/, '') s.summary = package['description'] s.author = package['author'] s.license = package['license'] s.homepage = package['homepage'] s.source = { :git => 'https://github.com/microsoft/react-native-code-push.git', :tag => "v#{s.version}"} s.ios.deployment_target = '15.5' s.tvos.deployment_target = '15.5' s.preserve_paths = '*.js' s.library = 'z' s.source_files = 'ios/CodePush/*.{h,m}' s.public_header_files = ['ios/CodePush/CodePush.h'] # Note: Even though there are copy/pasted versions of some of these dependencies in the repo, # we explicitly let CocoaPods pull in the versions below so all dependencies are resolved and # linked properly at a parent workspace level. s.dependency 'React-Core' s.dependency 'SSZipArchive', '~> 2.5.5' s.dependency 'JWT', '~> 3.0.0-beta.12' s.dependency 'Base64', '~> 1.1' end ================================================ FILE: Examples/CodePushDemoApp/.buckconfig ================================================ [android] target = Google Inc.:Google APIs:23 [maven_repositories] central = https://repo1.maven.org/maven2 ================================================ FILE: Examples/CodePushDemoApp/.editorconfig ================================================ # Windows files [*.bat] end_of_line = crlf ================================================ FILE: Examples/CodePushDemoApp/.eslintrc.js ================================================ module.exports = { root: true, extends: '@react-native-community', }; ================================================ FILE: Examples/CodePushDemoApp/.flowconfig ================================================ [ignore] ; We fork some components by platform .*/*[.]android.js ; Ignore "BUCK" generated dirs /\.buckd/ ; Ignore polyfills node_modules/react-native/Libraries/polyfills/.* ; Flow doesn't support platforms .*/Libraries/Utilities/LoadingView.js [untyped] .*/node_modules/@react-native-community/cli/.*/.* [include] [libs] node_modules/react-native/interface.js node_modules/react-native/flow/ [options] emoji=true exact_by_default=true format.bracket_spacing=false module.file_ext=.js module.file_ext=.json module.file_ext=.ios.js munge_underscores=true module.name_mapper='^react-native/\(.*\)$' -> '/node_modules/react-native/\1' module.name_mapper='^@?[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> '/node_modules/react-native/Libraries/Image/RelativeImageStub' suppress_type=$FlowIssue suppress_type=$FlowFixMe suppress_type=$FlowFixMeProps suppress_type=$FlowFixMeState [lints] sketchy-null-number=warn sketchy-null-mixed=warn sketchy-number=warn untyped-type-import=warn nonstrict-import=warn deprecated-type=warn unsafe-getters-setters=warn unnecessary-invariant=warn signature-verification-failure=warn [strict] deprecated-type nonstrict-import sketchy-null unclear-type unsafe-getters-setters untyped-import untyped-type-import [version] ^0.158.0 ================================================ FILE: Examples/CodePushDemoApp/.gitattributes ================================================ # Windows files should use crlf line endings # https://help.github.com/articles/dealing-with-line-endings/ *.bat text eol=crlf ================================================ FILE: Examples/CodePushDemoApp/.gitignore ================================================ # OSX # .DS_Store # Xcode # build/ *.pbxuser !default.pbxuser *.mode1v3 !default.mode1v3 *.mode2v3 !default.mode2v3 *.perspectivev3 !default.perspectivev3 xcuserdata *.xccheckout *.moved-aside DerivedData *.hmap *.ipa *.xcuserstate # Android/IntelliJ # build/ .idea .gradle local.properties *.iml *.hprof # node.js # node_modules/ npm-debug.log yarn-error.log # BUCK buck-out/ \.buckd/ *.keystore !debug.keystore # fastlane # # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the # screenshots whenever they are needed. # For more information about the recommended setup visit: # https://docs.fastlane.tools/best-practices/source-control/ */fastlane/report.xml */fastlane/Preview.html */fastlane/screenshots # Bundle artifact *.jsbundle # CocoaPods /ios/Pods/ ================================================ FILE: Examples/CodePushDemoApp/.prettierrc.js ================================================ module.exports = { bracketSpacing: false, jsxBracketSameLine: true, singleQuote: true, trailingComma: 'all', arrowParens: 'avoid', }; ================================================ FILE: Examples/CodePushDemoApp/.watchmanconfig ================================================ {} ================================================ FILE: Examples/CodePushDemoApp/App.js ================================================ import React, { Component } from 'react'; import { AppRegistry, Dimensions, Image, StyleSheet, Text, TouchableOpacity, View, } from 'react-native'; import CodePush from "react-native-code-push"; class App extends Component<{}> { constructor() { super(); this.state = { restartAllowed: true }; } codePushStatusDidChange(syncStatus) { switch(syncStatus) { case CodePush.SyncStatus.CHECKING_FOR_UPDATE: this.setState({ syncMessage: "Checking for update." }); break; case CodePush.SyncStatus.DOWNLOADING_PACKAGE: this.setState({ syncMessage: "Downloading package." }); break; case CodePush.SyncStatus.AWAITING_USER_ACTION: this.setState({ syncMessage: "Awaiting user action." }); break; case CodePush.SyncStatus.INSTALLING_UPDATE: this.setState({ syncMessage: "Installing update." }); break; case CodePush.SyncStatus.UP_TO_DATE: this.setState({ syncMessage: "App up to date.", progress: false }); break; case CodePush.SyncStatus.UPDATE_IGNORED: this.setState({ syncMessage: "Update cancelled by user.", progress: false }); break; case CodePush.SyncStatus.UPDATE_INSTALLED: this.setState({ syncMessage: "Update installed and will be applied on restart.", progress: false }); break; case CodePush.SyncStatus.UNKNOWN_ERROR: this.setState({ syncMessage: "An unknown error occurred.", progress: false }); break; } } codePushDownloadDidProgress(progress) { this.setState({ progress }); } toggleAllowRestart() { this.state.restartAllowed ? CodePush.disallowRestart() : CodePush.allowRestart(); this.setState({ restartAllowed: !this.state.restartAllowed }); } getUpdateMetadata() { CodePush.getUpdateMetadata(CodePush.UpdateState.RUNNING) .then((metadata: LocalPackage) => { this.setState({ syncMessage: metadata ? JSON.stringify(metadata) : "Running binary version", progress: false }); }, (error: any) => { this.setState({ syncMessage: "Error: " + error, progress: false }); }); } /** Update is downloaded silently, and applied on restart (recommended) */ sync() { CodePush.sync( {}, this.codePushStatusDidChange.bind(this), this.codePushDownloadDidProgress.bind(this) ); } /** Update pops a confirmation dialog, and then immediately reboots the app */ syncImmediate() { CodePush.sync( { installMode: CodePush.InstallMode.IMMEDIATE, updateDialog: true }, this.codePushStatusDidChange.bind(this), this.codePushDownloadDidProgress.bind(this) ); } render() { let progressView; if (this.state.progress) { progressView = ( {this.state.progress.receivedBytes} of {this.state.progress.totalBytes} bytes received ); } return ( Welcome to CodePush! Press for background sync Press for dialog-driven sync {progressView} Restart { this.state.restartAllowed ? "allowed" : "forbidden"} Press for Update Metadata {this.state.syncMessage || ""} ); } } const styles = StyleSheet.create({ container: { flex: 1, alignItems: "center", backgroundColor: "#F5FCFF", paddingTop: 50 }, image: { margin: 30, width: Dimensions.get("window").width - 100, height: 365 * (Dimensions.get("window").width - 100) / 651, }, messages: { marginTop: 30, textAlign: "center", }, restartToggleButton: { color: "blue", fontSize: 17 }, syncButton: { color: "green", fontSize: 17 }, welcome: { fontSize: 20, textAlign: "center", margin: 20 }, }); /** * Configured with a MANUAL check frequency for easy testing. For production apps, it is recommended to configure a * different check frequency, such as ON_APP_START, for a 'hands-off' approach where CodePush.sync() does not * need to be explicitly called. All options of CodePush.sync() are also available in this decorator. */ let codePushOptions = { checkFrequency: CodePush.CheckFrequency.MANUAL }; App = CodePush(codePushOptions)(App); export default App; ================================================ FILE: Examples/CodePushDemoApp/__tests__/App-test.js ================================================ /** * @format */ import 'react-native'; import React from 'react'; import App from '../App'; // Note: test renderer must be required after react-native. import renderer from 'react-test-renderer'; it('renders correctly', () => { renderer.create(); }); ================================================ FILE: Examples/CodePushDemoApp/android/app/BUCK ================================================ # To learn about Buck see [Docs](https://buckbuild.com/). # To run your application with Buck: # - install Buck # - `npm start` - to start the packager # - `cd android` # - `keytool -genkey -v -keystore keystores/debug.keystore -storepass android -alias androiddebugkey -keypass android -dname "CN=Android Debug,O=Android,C=US"` # - `./gradlew :app:copyDownloadableDepsToLibs` - make all Gradle compile dependencies available to Buck # - `buck install -r android/app` - compile, install and run application # load(":build_defs.bzl", "create_aar_targets", "create_jar_targets") lib_deps = [] create_aar_targets(glob(["libs/*.aar"])) create_jar_targets(glob(["libs/*.jar"])) android_library( name = "all-libs", exported_deps = lib_deps, ) android_library( name = "app-code", srcs = glob([ "src/main/java/**/*.java", ]), deps = [ ":all-libs", ":build_config", ":res", ], ) android_build_config( name = "build_config", package = "com.codepushdemoapp", ) android_resource( name = "res", package = "com.codepushdemoapp", res = "src/main/res", ) android_binary( name = "app", keystore = "//android/keystores:debug", manifest = "src/main/AndroidManifest.xml", package_type = "debug", deps = [ ":app-code", ], ) ================================================ FILE: Examples/CodePushDemoApp/android/app/build.gradle ================================================ apply plugin: "com.android.application" import com.android.build.OutputFile /** * The react.gradle file registers a task for each build variant (e.g. bundleDebugJsAndAssets * and bundleReleaseJsAndAssets). * These basically call `react-native bundle` with the correct arguments during the Android build * cycle. By default, bundleDebugJsAndAssets is skipped, as in debug/dev mode we prefer to load the * bundle directly from the development server. Below you can see all the possible configurations * and their defaults. If you decide to add a configuration block, make sure to add it before the * `apply from: "../../node_modules/react-native/react.gradle"` line. * * project.ext.react = [ * // the name of the generated asset file containing your JS bundle * bundleAssetName: "index.android.bundle", * * // the entry file for bundle generation. If none specified and * // "index.android.js" exists, it will be used. Otherwise "index.js" is * // default. Can be overridden with ENTRY_FILE environment variable. * entryFile: "index.android.js", * * // https://reactnative.dev/docs/performance#enable-the-ram-format * bundleCommand: "ram-bundle", * * // whether to bundle JS and assets in debug mode * bundleInDebug: false, * * // whether to bundle JS and assets in release mode * bundleInRelease: true, * * // whether to bundle JS and assets in another build variant (if configured). * // See http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants * // The configuration property can be in the following formats * // 'bundleIn${productFlavor}${buildType}' * // 'bundleIn${buildType}' * // bundleInFreeDebug: true, * // bundleInPaidRelease: true, * // bundleInBeta: true, * * // whether to disable dev mode in custom build variants (by default only disabled in release) * // for example: to disable dev mode in the staging build type (if configured) * devDisabledInStaging: true, * // The configuration property can be in the following formats * // 'devDisabledIn${productFlavor}${buildType}' * // 'devDisabledIn${buildType}' * * // the root of your project, i.e. where "package.json" lives * root: "../../", * * // where to put the JS bundle asset in debug mode * jsBundleDirDebug: "$buildDir/intermediates/assets/debug", * * // where to put the JS bundle asset in release mode * jsBundleDirRelease: "$buildDir/intermediates/assets/release", * * // where to put drawable resources / React Native assets, e.g. the ones you use via * // require('./image.png')), in debug mode * resourcesDirDebug: "$buildDir/intermediates/res/merged/debug", * * // where to put drawable resources / React Native assets, e.g. the ones you use via * // require('./image.png')), in release mode * resourcesDirRelease: "$buildDir/intermediates/res/merged/release", * * // by default the gradle tasks are skipped if none of the JS files or assets change; this means * // that we don't look at files in android/ or ios/ to determine whether the tasks are up to * // date; if you have any other folders that you want to ignore for performance reasons (gradle * // indexes the entire tree), add them here. Alternatively, if you have JS files in android/ * // for example, you might want to remove it from here. * inputExcludes: ["android/**", "ios/**"], * * // override which node gets called and with what additional arguments * nodeExecutableAndArgs: ["node"], * * // supply additional arguments to the packager * extraPackagerArgs: [] * ] */ project.ext.react = [ enableHermes: false, // clean and rebuild if changing ] apply from: "../../node_modules/react-native/react.gradle" apply from: "../../node_modules/react-native-code-push/android/codepush.gradle" /** * Set this to true to create two separate APKs instead of one: * - An APK that only works on ARM devices * - An APK that only works on x86 devices * The advantage is the size of the APK is reduced by about 4MB. * Upload all the APKs to the Play Store and people will download * the correct one based on the CPU architecture of their device. */ def enableSeparateBuildPerCPUArchitecture = false /** * Run Proguard to shrink the Java bytecode in release builds. */ def enableProguardInReleaseBuilds = false /** * The preferred build flavor of JavaScriptCore. * * For example, to use the international variant, you can use: * `def jscFlavor = 'org.webkit:android-jsc-intl:+'` * * The international variant includes ICU i18n library and necessary data * allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that * give correct results when using with locales other than en-US. Note that * this variant is about 6MiB larger per architecture than default. */ def jscFlavor = 'org.webkit:android-jsc:+' /** * Whether to enable the Hermes VM. * * This should be set on project.ext.react and mirrored here. If it is not set * on project.ext.react, JavaScript will not be compiled to Hermes Bytecode * and the benefits of using Hermes will therefore be sharply reduced. */ def enableHermes = project.ext.react.get("enableHermes", false); /** * Architectures to build native code for in debug. */ def nativeArchitectures = project.getProperties().get("reactNativeDebugArchitectures") android { ndkVersion rootProject.ext.ndkVersion compileSdkVersion rootProject.ext.compileSdkVersion defaultConfig { applicationId "com.codepushdemoapp" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion versionCode 1 versionName "1.0" } splits { abi { reset() enable enableSeparateBuildPerCPUArchitecture universalApk false // If true, also generate a universal APK include "armeabi-v7a", "x86", "arm64-v8a", "x86_64" } } signingConfigs { debug { storeFile file('debug.keystore') storePassword 'android' keyAlias 'androiddebugkey' keyPassword 'android' } } buildTypes { debug { signingConfig signingConfigs.debug if (nativeArchitectures) { ndk { abiFilters nativeArchitectures.split(',') } } } release { // Caution! In production, you need to generate your own keystore file. // see https://reactnative.dev/docs/signed-apk-android. signingConfig signingConfigs.debug minifyEnabled enableProguardInReleaseBuilds proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" } } // applicationVariants are e.g. debug, release applicationVariants.all { variant -> variant.outputs.each { output -> // For each separate APK per architecture, set a unique version code as described here: // https://developer.android.com/studio/build/configure-apk-splits.html // Example: versionCode 1 will generate 1001 for armeabi-v7a, 1002 for x86, etc. def versionCodes = ["armeabi-v7a": 1, "x86": 2, "arm64-v8a": 3, "x86_64": 4] def abi = output.getFilter(OutputFile.ABI) if (abi != null) { // null for the universal-debug, universal-release variants output.versionCodeOverride = defaultConfig.versionCode * 1000 + versionCodes.get(abi) } } } } dependencies { implementation fileTree(dir: "libs", include: ["*.jar"]) //noinspection GradleDynamicVersion implementation "com.facebook.react:react-native:+" // From node_modules implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0" debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") { exclude group:'com.facebook.fbjni' } debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") { exclude group:'com.facebook.flipper' exclude group:'com.squareup.okhttp3', module:'okhttp' } debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}") { exclude group:'com.facebook.flipper' } if (enableHermes) { def hermesPath = "../../node_modules/hermes-engine/android/"; debugImplementation files(hermesPath + "hermes-debug.aar") releaseImplementation files(hermesPath + "hermes-release.aar") } else { implementation jscFlavor } } // Run this once to be able to run the application with BUCK // puts all compile dependencies into folder libs for BUCK to use task copyDownloadableDepsToLibs(type: Copy) { from configurations.implementation into 'libs' } apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project) ================================================ FILE: Examples/CodePushDemoApp/android/app/build_defs.bzl ================================================ """Helper definitions to glob .aar and .jar targets""" def create_aar_targets(aarfiles): for aarfile in aarfiles: name = "aars__" + aarfile[aarfile.rindex("/") + 1:aarfile.rindex(".aar")] lib_deps.append(":" + name) android_prebuilt_aar( name = name, aar = aarfile, ) def create_jar_targets(jarfiles): for jarfile in jarfiles: name = "jars__" + jarfile[jarfile.rindex("/") + 1:jarfile.rindex(".jar")] lib_deps.append(":" + name) prebuilt_jar( name = name, binary_jar = jarfile, ) ================================================ FILE: Examples/CodePushDemoApp/android/app/proguard-rules.pro ================================================ # Add project specific ProGuard rules here. # By default, the flags in this file are appended to flags specified # in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt # You can edit the include path and order by changing the proguardFiles # directive in build.gradle. # # For more details, see # http://developer.android.com/guide/developing/tools/proguard.html # Add any project specific keep options here: ================================================ FILE: Examples/CodePushDemoApp/android/app/src/main/AndroidManifest.xml ================================================ ================================================ FILE: Examples/CodePushDemoApp/android/app/src/main/java/com/codepushdemoapp/MainActivity.java ================================================ package com.codepushdemoapp; import com.facebook.react.ReactActivity; public class MainActivity extends ReactActivity { /** * Returns the name of the main component registered from JavaScript. This is used to schedule * rendering of the component. */ @Override protected String getMainComponentName() { return "CodePushDemoApp"; } } ================================================ FILE: Examples/CodePushDemoApp/android/app/src/main/java/com/codepushdemoapp/MainApplication.java ================================================ package com.codepushdemoapp; import android.app.Application; import com.microsoft.codepush.react.CodePush; import android.content.Context; import com.facebook.react.PackageList; import com.facebook.react.ReactApplication; import com.facebook.react.ReactInstanceManager; import com.facebook.react.ReactNativeHost; import com.facebook.react.ReactPackage; import com.facebook.soloader.SoLoader; import java.lang.reflect.InvocationTargetException; import java.util.List; public class MainApplication extends Application implements ReactApplication { private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) { @Override protected String getJSBundleFile(){ return CodePush.getJSBundleFile(); } @Override public boolean getUseDeveloperSupport() { return BuildConfig.DEBUG; } @Override protected List getPackages() { @SuppressWarnings("UnnecessaryLocalVariable") List packages = new PackageList(this).getPackages(); // Packages that cannot be autolinked yet can be added manually here, for example: // packages.add(new MyReactNativePackage()); return packages; } @Override protected String getJSMainModuleName() { return "index"; } }; @Override public ReactNativeHost getReactNativeHost() { return mReactNativeHost; } @Override public void onCreate() { super.onCreate(); SoLoader.init(this, /* native exopackage */ false); initializeFlipper(this, getReactNativeHost().getReactInstanceManager()); } /** * Loads Flipper in React Native templates. Call this in the onCreate method with something like * initializeFlipper(this, getReactNativeHost().getReactInstanceManager()); * * @param context * @param reactInstanceManager */ private static void initializeFlipper( Context context, ReactInstanceManager reactInstanceManager) { if (BuildConfig.DEBUG) { try { /* We use reflection here to pick up the class that initializes Flipper, since Flipper library is not available in release mode */ Class aClass = Class.forName("com.codepushdemoapp.ReactNativeFlipper"); aClass .getMethod("initializeFlipper", Context.class, ReactInstanceManager.class) .invoke(null, context, reactInstanceManager); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } } } ================================================ FILE: Examples/CodePushDemoApp/android/app/src/main/res/values/strings.xml ================================================ deployment-key-here CodePushDemoApp ================================================ FILE: Examples/CodePushDemoApp/android/app/src/main/res/values/styles.xml ================================================ ================================================ FILE: Examples/CodePushDemoApp/android/build.gradle ================================================ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { ext { buildToolsVersion = "30.0.2" minSdkVersion = 21 compileSdkVersion = 30 targetSdkVersion = 30 ndkVersion = "21.4.7075529" } repositories { google() mavenCentral() } dependencies { classpath("com.android.tools.build:gradle:4.2.2") // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } } allprojects { repositories { mavenCentral() mavenLocal() maven { // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm url("$rootDir/../node_modules/react-native/android") } maven { // Android JSC is installed from npm url("$rootDir/../node_modules/jsc-android/dist") } google() maven { url 'https://www.jitpack.io' } } } ================================================ FILE: Examples/CodePushDemoApp/android/gradle/wrapper/gradle-wrapper.properties ================================================ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists distributionUrl=https\://services.gradle.org/distributions/gradle-6.9-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists ================================================ FILE: Examples/CodePushDemoApp/android/gradle.properties ================================================ # Project-wide Gradle settings. # IDE (e.g. Android Studio) users: # Gradle settings configured through the IDE *will override* # any settings specified in this file. # For more details on how to configure your build environment visit # http://www.gradle.org/docs/current/userguide/build_environment.html # Specifies the JVM arguments used for the daemon process. # The setting is particularly useful for tweaking memory settings. # Default value: -Xmx10248m -XX:MaxPermSize=256m # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 # When configured, Gradle will run in incubating parallel mode. # This option should only be used with decoupled projects. More details, visit # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects # org.gradle.parallel=true # AndroidX package structure to make it clearer which packages are bundled with the # Android operating system, and which are packaged with your app's APK # https://developer.android.com/topic/libraries/support-library/androidx-rn android.useAndroidX=true # Automatically convert third-party libraries to use AndroidX android.enableJetifier=true # Version of flipper SDK to use with React Native FLIPPER_VERSION=0.99.0 ================================================ FILE: Examples/CodePushDemoApp/android/gradlew ================================================ #!/usr/bin/env sh # # Copyright 2015 the original author or authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ############################################################################## ## ## Gradle start up script for UN*X ## ############################################################################## # Attempt to set APP_HOME # Resolve links: $0 may be a link PRG="$0" # Need this for relative symlinks. while [ -h "$PRG" ] ; do ls=`ls -ld "$PRG"` link=`expr "$ls" : '.*-> \(.*\)$'` if expr "$link" : '/.*' > /dev/null; then PRG="$link" else PRG=`dirname "$PRG"`"/$link" fi done SAVED="`pwd`" cd "`dirname \"$PRG\"`/" >/dev/null APP_HOME="`pwd -P`" cd "$SAVED" >/dev/null APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" warn () { echo "$*" } die () { echo echo "$*" echo exit 1 } # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false case "`uname`" in CYGWIN* ) cygwin=true ;; Darwin* ) darwin=true ;; MINGW* ) msys=true ;; NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables JAVACMD="$JAVA_HOME/jre/sh/java" else JAVACMD="$JAVA_HOME/bin/java" fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else JAVACMD="java" which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi # Increase the maximum file descriptors if we can. if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then MAX_FD_LIMIT=`ulimit -H -n` if [ $? -eq 0 ] ; then if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then MAX_FD="$MAX_FD_LIMIT" fi ulimit -n $MAX_FD if [ $? -ne 0 ] ; then warn "Could not set maximum file descriptor limit: $MAX_FD" fi else warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" fi fi # For Darwin, add options to specify how the application appears in the dock if $darwin; then GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" fi # For Cygwin or MSYS, switch paths to Windows format before running java if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` JAVACMD=`cygpath --unix "$JAVACMD"` # We build the pattern for arguments to be converted via cygpath ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` SEP="" for dir in $ROOTDIRSRAW ; do ROOTDIRS="$ROOTDIRS$SEP$dir" SEP="|" done OURCYGPATTERN="(^($ROOTDIRS))" # Add a user-defined pattern to the cygpath arguments if [ "$GRADLE_CYGPATTERN" != "" ] ; then OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" fi # Now convert the arguments - kludge to limit ourselves to /bin/sh i=0 for arg in "$@" ; do CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` else eval `echo args$i`="\"$arg\"" fi i=`expr $i + 1` done case $i in 0) set -- ;; 1) set -- "$args0" ;; 2) set -- "$args0" "$args1" ;; 3) set -- "$args0" "$args1" "$args2" ;; 4) set -- "$args0" "$args1" "$args2" "$args3" ;; 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; esac fi # Escape application args save () { for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done echo " " } APP_ARGS=`save "$@"` # Collect all arguments for the java command, following the shell quoting and substitution rules eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" exec "$JAVACMD" "$@" ================================================ FILE: Examples/CodePushDemoApp/android/gradlew.bat ================================================ @rem @rem Copyright 2015 the original author or authors. @rem @rem Licensed under the Apache License, Version 2.0 (the "License"); @rem you may not use this file except in compliance with the License. @rem You may obtain a copy of the License at @rem @rem https://www.apache.org/licenses/LICENSE-2.0 @rem @rem Unless required by applicable law or agreed to in writing, software @rem distributed under the License is distributed on an "AS IS" BASIS, @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem @if "%DEBUG%" == "" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @rem @rem ########################################################################## @rem Set local scope for the variables with windows NT shell if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @rem Resolve any "." and ".." in APP_HOME to make it shorter. for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if "%ERRORLEVEL%" == "0" goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. echo. echo Please set the JAVA_HOME variable in your environment to match the echo location of your Java installation. goto fail :findJavaFromJavaHome set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% echo. echo Please set the JAVA_HOME variable in your environment to match the echo location of your Java installation. goto fail :execute @rem Setup the command line set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar @rem Execute Gradle "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* :end @rem End local scope for the variables with windows NT shell if "%ERRORLEVEL%"=="0" goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 exit /b 1 :mainEnd if "%OS%"=="Windows_NT" endlocal :omega ================================================ FILE: Examples/CodePushDemoApp/android/settings.gradle ================================================ rootProject.name = 'CodePushDemoApp' apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings) include ':app', ':react-native-code-push' project(':react-native-code-push').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-code-push/android/app') ================================================ FILE: Examples/CodePushDemoApp/app.json ================================================ { "name": "CodePushDemoApp", "displayName": "CodePushDemoApp" } ================================================ FILE: Examples/CodePushDemoApp/babel.config.js ================================================ module.exports = { presets: ['module:metro-react-native-babel-preset'], }; ================================================ FILE: Examples/CodePushDemoApp/index.js ================================================ import { AppRegistry } from 'react-native'; import App from './App'; AppRegistry.registerComponent('CodePushDemoApp', () => App); ================================================ FILE: Examples/CodePushDemoApp/ios/CodePushDemoApp/AppDelegate.h ================================================ #import #import @interface AppDelegate : UIResponder @property (nonatomic, strong) UIWindow *window; @end ================================================ FILE: Examples/CodePushDemoApp/ios/CodePushDemoApp/AppDelegate.m ================================================ #import "AppDelegate.h" #import #import #import #import #ifdef FB_SONARKIT_ENABLED #import #import #import #import #import #import static void InitializeFlipper(UIApplication *application) { FlipperClient *client = [FlipperClient sharedClient]; SKDescriptorMapper *layoutDescriptorMapper = [[SKDescriptorMapper alloc] initWithDefaults]; [client addPlugin:[[FlipperKitLayoutPlugin alloc] initWithRootNode:application withDescriptorMapper:layoutDescriptorMapper]]; [client addPlugin:[[FKUserDefaultsPlugin alloc] initWithSuiteName:nil]]; [client addPlugin:[FlipperKitReactPlugin new]]; [client addPlugin:[[FlipperKitNetworkPlugin alloc] initWithNetworkAdapter:[SKIOSNetworkAdapter new]]]; [client start]; } #endif @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { #ifdef FB_SONARKIT_ENABLED InitializeFlipper(application); #endif RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions]; RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge moduleName:@"CodePushDemoApp" initialProperties:nil]; if (@available(iOS 13.0, *)) { rootView.backgroundColor = [UIColor systemBackgroundColor]; } else { rootView.backgroundColor = [UIColor whiteColor]; } self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; UIViewController *rootViewController = [UIViewController new]; rootViewController.view = rootView; self.window.rootViewController = rootViewController; [self.window makeKeyAndVisible]; return YES; } - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge { #if DEBUG return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil]; #else return [CodePush bundleURL]; #endif } @end ================================================ FILE: Examples/CodePushDemoApp/ios/CodePushDemoApp/Images.xcassets/AppIcon.appiconset/Contents.json ================================================ { "images" : [ { "idiom" : "iphone", "size" : "29x29", "scale" : "2x" }, { "idiom" : "iphone", "size" : "29x29", "scale" : "3x" }, { "idiom" : "iphone", "size" : "40x40", "scale" : "2x" }, { "idiom" : "iphone", "size" : "40x40", "scale" : "3x" }, { "idiom" : "iphone", "size" : "60x60", "scale" : "2x" }, { "idiom" : "iphone", "size" : "60x60", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: Examples/CodePushDemoApp/ios/CodePushDemoApp/Images.xcassets/Contents.json ================================================ { "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: Examples/CodePushDemoApp/ios/CodePushDemoApp/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleDisplayName CodePushDemoApp CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType APPL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 LSRequiresIPhoneOS NSAppTransportSecurity NSExceptionDomains localhost NSExceptionAllowsInsecureHTTPLoads NSLocationWhenInUseUsageDescription UILaunchStoryboardName LaunchScreen UIRequiredDeviceCapabilities armv7 UISupportedInterfaceOrientations UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIViewControllerBasedStatusBarAppearance CodePushDeploymentKey deployment-key-here ================================================ FILE: Examples/CodePushDemoApp/ios/CodePushDemoApp/LaunchScreen.storyboard ================================================ ================================================ FILE: Examples/CodePushDemoApp/ios/CodePushDemoApp/main.m ================================================ #import #import "AppDelegate.h" int main(int argc, char * argv[]) { @autoreleasepool { return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); } } ================================================ FILE: Examples/CodePushDemoApp/ios/CodePushDemoApp.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 54; objects = { /* Begin PBXBuildFile section */ 00E356F31AD99517003FC87E /* CodePushDemoAppTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* CodePushDemoAppTests.m */; }; 13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; }; 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; 13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; }; 7209CF15AFD1B1A1154ADDC3 /* libPods-CodePushDemoApp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F822409B61CE9E11C825CB2E /* libPods-CodePushDemoApp.a */; }; 81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; }; 873543544E84903AB9AC764D /* libPods-CodePushDemoApp-CodePushDemoAppTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0684492BF481E6EAA4A6624A /* libPods-CodePushDemoApp-CodePushDemoAppTests.a */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ 00E356F41AD99517003FC87E /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */; proxyType = 1; remoteGlobalIDString = 13B07F861A680F5B00A75B9A; remoteInfo = CodePushDemoApp; }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ 00E356EE1AD99517003FC87E /* CodePushDemoAppTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CodePushDemoAppTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 00E356F11AD99517003FC87E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 00E356F21AD99517003FC87E /* CodePushDemoAppTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CodePushDemoAppTests.m; sourceTree = ""; }; 0684492BF481E6EAA4A6624A /* libPods-CodePushDemoApp-CodePushDemoAppTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-CodePushDemoApp-CodePushDemoAppTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 13B07F961A680F5B00A75B9A /* CodePushDemoApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = CodePushDemoApp.app; sourceTree = BUILT_PRODUCTS_DIR; }; 13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = CodePushDemoApp/AppDelegate.h; sourceTree = ""; }; 13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = CodePushDemoApp/AppDelegate.m; sourceTree = ""; }; 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = CodePushDemoApp/Images.xcassets; sourceTree = ""; }; 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = CodePushDemoApp/Info.plist; sourceTree = ""; }; 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = CodePushDemoApp/main.m; sourceTree = ""; }; 3A1AC7C53CE0CC5BA2B85E4E /* Pods-CodePushDemoApp.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CodePushDemoApp.debug.xcconfig"; path = "Target Support Files/Pods-CodePushDemoApp/Pods-CodePushDemoApp.debug.xcconfig"; sourceTree = ""; }; 3FF5216EA67271BFA35BE5DD /* Pods-CodePushDemoApp-CodePushDemoAppTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CodePushDemoApp-CodePushDemoAppTests.debug.xcconfig"; path = "Target Support Files/Pods-CodePushDemoApp-CodePushDemoAppTests/Pods-CodePushDemoApp-CodePushDemoAppTests.debug.xcconfig"; sourceTree = ""; }; 4B6E53AD2EAAA824D962A672 /* Pods-CodePushDemoApp.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CodePushDemoApp.release.xcconfig"; path = "Target Support Files/Pods-CodePushDemoApp/Pods-CodePushDemoApp.release.xcconfig"; sourceTree = ""; }; 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = CodePushDemoApp/LaunchScreen.storyboard; sourceTree = ""; }; 9E42C477F1442EBF73599739 /* Pods-CodePushDemoApp-CodePushDemoAppTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CodePushDemoApp-CodePushDemoAppTests.release.xcconfig"; path = "Target Support Files/Pods-CodePushDemoApp-CodePushDemoAppTests/Pods-CodePushDemoApp-CodePushDemoAppTests.release.xcconfig"; sourceTree = ""; }; ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; }; F822409B61CE9E11C825CB2E /* libPods-CodePushDemoApp.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-CodePushDemoApp.a"; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 00E356EB1AD99517003FC87E /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 873543544E84903AB9AC764D /* libPods-CodePushDemoApp-CodePushDemoAppTests.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; 13B07F8C1A680F5B00A75B9A /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 7209CF15AFD1B1A1154ADDC3 /* libPods-CodePushDemoApp.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 00E356EF1AD99517003FC87E /* CodePushDemoAppTests */ = { isa = PBXGroup; children = ( 00E356F21AD99517003FC87E /* CodePushDemoAppTests.m */, 00E356F01AD99517003FC87E /* Supporting Files */, ); path = CodePushDemoAppTests; sourceTree = ""; }; 00E356F01AD99517003FC87E /* Supporting Files */ = { isa = PBXGroup; children = ( 00E356F11AD99517003FC87E /* Info.plist */, ); name = "Supporting Files"; sourceTree = ""; }; 13B07FAE1A68108700A75B9A /* CodePushDemoApp */ = { isa = PBXGroup; children = ( 13B07FAF1A68108700A75B9A /* AppDelegate.h */, 13B07FB01A68108700A75B9A /* AppDelegate.m */, 13B07FB51A68108700A75B9A /* Images.xcassets */, 13B07FB61A68108700A75B9A /* Info.plist */, 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */, 13B07FB71A68108700A75B9A /* main.m */, ); name = CodePushDemoApp; sourceTree = ""; }; 2D16E6871FA4F8E400B85C8A /* Frameworks */ = { isa = PBXGroup; children = ( ED297162215061F000B7C4FE /* JavaScriptCore.framework */, F822409B61CE9E11C825CB2E /* libPods-CodePushDemoApp.a */, 0684492BF481E6EAA4A6624A /* libPods-CodePushDemoApp-CodePushDemoAppTests.a */, ); name = Frameworks; sourceTree = ""; }; 69F6BBD5C7690E30A982EAEE /* Pods */ = { isa = PBXGroup; children = ( 3A1AC7C53CE0CC5BA2B85E4E /* Pods-CodePushDemoApp.debug.xcconfig */, 4B6E53AD2EAAA824D962A672 /* Pods-CodePushDemoApp.release.xcconfig */, 3FF5216EA67271BFA35BE5DD /* Pods-CodePushDemoApp-CodePushDemoAppTests.debug.xcconfig */, 9E42C477F1442EBF73599739 /* Pods-CodePushDemoApp-CodePushDemoAppTests.release.xcconfig */, ); name = Pods; path = Pods; sourceTree = ""; }; 832341AE1AAA6A7D00B99B32 /* Libraries */ = { isa = PBXGroup; children = ( ); name = Libraries; sourceTree = ""; }; 83CBB9F61A601CBA00E9B192 = { isa = PBXGroup; children = ( 13B07FAE1A68108700A75B9A /* CodePushDemoApp */, 832341AE1AAA6A7D00B99B32 /* Libraries */, 00E356EF1AD99517003FC87E /* CodePushDemoAppTests */, 83CBBA001A601CBA00E9B192 /* Products */, 2D16E6871FA4F8E400B85C8A /* Frameworks */, 69F6BBD5C7690E30A982EAEE /* Pods */, ); indentWidth = 2; sourceTree = ""; tabWidth = 2; usesTabs = 0; }; 83CBBA001A601CBA00E9B192 /* Products */ = { isa = PBXGroup; children = ( 13B07F961A680F5B00A75B9A /* CodePushDemoApp.app */, 00E356EE1AD99517003FC87E /* CodePushDemoAppTests.xctest */, ); name = Products; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 00E356ED1AD99517003FC87E /* CodePushDemoAppTests */ = { isa = PBXNativeTarget; buildConfigurationList = 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "CodePushDemoAppTests" */; buildPhases = ( E0C08DC1172810CC2B651913 /* [CP] Check Pods Manifest.lock */, 00E356EA1AD99517003FC87E /* Sources */, 00E356EB1AD99517003FC87E /* Frameworks */, 00E356EC1AD99517003FC87E /* Resources */, 96DA1F0133CE6AECB818D1F3 /* [CP] Embed Pods Frameworks */, 8FCA0FCABC69767E741BB8F2 /* [CP] Copy Pods Resources */, ); buildRules = ( ); dependencies = ( 00E356F51AD99517003FC87E /* PBXTargetDependency */, ); name = CodePushDemoAppTests; productName = CodePushDemoAppTests; productReference = 00E356EE1AD99517003FC87E /* CodePushDemoAppTests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; 13B07F861A680F5B00A75B9A /* CodePushDemoApp */ = { isa = PBXNativeTarget; buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "CodePushDemoApp" */; buildPhases = ( FAE53E3C42A14CE48C4E62D3 /* [CP] Check Pods Manifest.lock */, FD10A7F022414F080027D42C /* Start Packager */, 13B07F871A680F5B00A75B9A /* Sources */, 13B07F8C1A680F5B00A75B9A /* Frameworks */, 13B07F8E1A680F5B00A75B9A /* Resources */, 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */, 3FB4CE61D43BB948153CCAD2 /* [CP] Embed Pods Frameworks */, E64717738EB438ACC77F81BB /* [CP] Copy Pods Resources */, ); buildRules = ( ); dependencies = ( ); name = CodePushDemoApp; productName = CodePushDemoApp; productReference = 13B07F961A680F5B00A75B9A /* CodePushDemoApp.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 83CBB9F71A601CBA00E9B192 /* Project object */ = { isa = PBXProject; attributes = { LastUpgradeCheck = 1210; TargetAttributes = { 00E356ED1AD99517003FC87E = { CreatedOnToolsVersion = 6.2; TestTargetID = 13B07F861A680F5B00A75B9A; }; 13B07F861A680F5B00A75B9A = { LastSwiftMigration = 1120; }; }; }; buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "CodePushDemoApp" */; compatibilityVersion = "Xcode 12.0"; developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = 83CBB9F61A601CBA00E9B192; productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 13B07F861A680F5B00A75B9A /* CodePushDemoApp */, 00E356ED1AD99517003FC87E /* CodePushDemoAppTests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 00E356EC1AD99517003FC87E /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; 13B07F8E1A680F5B00A75B9A /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( 81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */, 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "Bundle React Native code and images"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "set -e\n\nexport NODE_BINARY=node\n../node_modules/react-native/scripts/react-native-xcode.sh\n"; }; 3FB4CE61D43BB948153CCAD2 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputFileListPaths = ( "${PODS_ROOT}/Target Support Files/Pods-CodePushDemoApp/Pods-CodePushDemoApp-frameworks-${CONFIGURATION}-input-files.xcfilelist", ); name = "[CP] Embed Pods Frameworks"; outputFileListPaths = ( "${PODS_ROOT}/Target Support Files/Pods-CodePushDemoApp/Pods-CodePushDemoApp-frameworks-${CONFIGURATION}-output-files.xcfilelist", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-CodePushDemoApp/Pods-CodePushDemoApp-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; 8FCA0FCABC69767E741BB8F2 /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputFileListPaths = ( "${PODS_ROOT}/Target Support Files/Pods-CodePushDemoApp-CodePushDemoAppTests/Pods-CodePushDemoApp-CodePushDemoAppTests-resources-${CONFIGURATION}-input-files.xcfilelist", ); name = "[CP] Copy Pods Resources"; outputFileListPaths = ( "${PODS_ROOT}/Target Support Files/Pods-CodePushDemoApp-CodePushDemoAppTests/Pods-CodePushDemoApp-CodePushDemoAppTests-resources-${CONFIGURATION}-output-files.xcfilelist", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-CodePushDemoApp-CodePushDemoAppTests/Pods-CodePushDemoApp-CodePushDemoAppTests-resources.sh\"\n"; showEnvVarsInLog = 0; }; 96DA1F0133CE6AECB818D1F3 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputFileListPaths = ( "${PODS_ROOT}/Target Support Files/Pods-CodePushDemoApp-CodePushDemoAppTests/Pods-CodePushDemoApp-CodePushDemoAppTests-frameworks-${CONFIGURATION}-input-files.xcfilelist", ); name = "[CP] Embed Pods Frameworks"; outputFileListPaths = ( "${PODS_ROOT}/Target Support Files/Pods-CodePushDemoApp-CodePushDemoAppTests/Pods-CodePushDemoApp-CodePushDemoAppTests-frameworks-${CONFIGURATION}-output-files.xcfilelist", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-CodePushDemoApp-CodePushDemoAppTests/Pods-CodePushDemoApp-CodePushDemoAppTests-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; E0C08DC1172810CC2B651913 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputFileListPaths = ( ); inputPaths = ( "${PODS_PODFILE_DIR_PATH}/Podfile.lock", "${PODS_ROOT}/Manifest.lock", ); name = "[CP] Check Pods Manifest.lock"; outputFileListPaths = ( ); outputPaths = ( "$(DERIVED_FILE_DIR)/Pods-CodePushDemoApp-CodePushDemoAppTests-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; E64717738EB438ACC77F81BB /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputFileListPaths = ( "${PODS_ROOT}/Target Support Files/Pods-CodePushDemoApp/Pods-CodePushDemoApp-resources-${CONFIGURATION}-input-files.xcfilelist", ); name = "[CP] Copy Pods Resources"; outputFileListPaths = ( "${PODS_ROOT}/Target Support Files/Pods-CodePushDemoApp/Pods-CodePushDemoApp-resources-${CONFIGURATION}-output-files.xcfilelist", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-CodePushDemoApp/Pods-CodePushDemoApp-resources.sh\"\n"; showEnvVarsInLog = 0; }; FAE53E3C42A14CE48C4E62D3 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputFileListPaths = ( ); inputPaths = ( "${PODS_PODFILE_DIR_PATH}/Podfile.lock", "${PODS_ROOT}/Manifest.lock", ); name = "[CP] Check Pods Manifest.lock"; outputFileListPaths = ( ); outputPaths = ( "$(DERIVED_FILE_DIR)/Pods-CodePushDemoApp-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; FD10A7F022414F080027D42C /* Start Packager */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputFileListPaths = ( ); inputPaths = ( ); name = "Start Packager"; outputFileListPaths = ( ); outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "export RCT_METRO_PORT=\"${RCT_METRO_PORT:=8081}\"\necho \"export RCT_METRO_PORT=${RCT_METRO_PORT}\" > \"${SRCROOT}/../node_modules/react-native/scripts/.packager.env\"\nif [ -z \"${RCT_NO_LAUNCH_PACKAGER+xxx}\" ] ; then\n if nc -w 5 -z localhost ${RCT_METRO_PORT} ; then\n if ! curl -s \"http://localhost:${RCT_METRO_PORT}/status\" | grep -q \"packager-status:running\" ; then\n echo \"Port ${RCT_METRO_PORT} already in use, packager is either not running or not running correctly\"\n exit 2\n fi\n else\n open \"$SRCROOT/../node_modules/react-native/scripts/launchPackager.command\" || echo \"Can't start packager automatically\"\n fi\nfi\n"; showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 00E356EA1AD99517003FC87E /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 00E356F31AD99517003FC87E /* CodePushDemoAppTests.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; 13B07F871A680F5B00A75B9A /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */, 13B07FC11A68108700A75B9A /* main.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ 00E356F51AD99517003FC87E /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 13B07F861A680F5B00A75B9A /* CodePushDemoApp */; targetProxy = 00E356F41AD99517003FC87E /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ 00E356F61AD99517003FC87E /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = 3FF5216EA67271BFA35BE5DD /* Pods-CodePushDemoApp-CodePushDemoAppTests.debug.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); INFOPLIST_FILE = CodePushDemoAppTests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", "@loader_path/Frameworks", ); OTHER_LDFLAGS = ( "-ObjC", "-lc++", "$(inherited)", ); PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/CodePushDemoApp.app/CodePushDemoApp"; }; name = Debug; }; 00E356F71AD99517003FC87E /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = 9E42C477F1442EBF73599739 /* Pods-CodePushDemoApp-CodePushDemoAppTests.release.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; COPY_PHASE_STRIP = NO; INFOPLIST_FILE = CodePushDemoAppTests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", "@loader_path/Frameworks", ); OTHER_LDFLAGS = ( "-ObjC", "-lc++", "$(inherited)", ); PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/CodePushDemoApp.app/CodePushDemoApp"; }; name = Release; }; 13B07F941A680F5B00A75B9A /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = 3A1AC7C53CE0CC5BA2B85E4E /* Pods-CodePushDemoApp.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CURRENT_PROJECT_VERSION = 1; ENABLE_BITCODE = NO; INFOPLIST_FILE = CodePushDemoApp/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", ); OTHER_LDFLAGS = ( "$(inherited)", "-ObjC", "-lc++", ); PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = CodePushDemoApp; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; VERSIONING_SYSTEM = "apple-generic"; }; name = Debug; }; 13B07F951A680F5B00A75B9A /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = 4B6E53AD2EAAA824D962A672 /* Pods-CodePushDemoApp.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CURRENT_PROJECT_VERSION = 1; INFOPLIST_FILE = CodePushDemoApp/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", ); OTHER_LDFLAGS = ( "$(inherited)", "-ObjC", "-lc++", ); PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = CodePushDemoApp; SWIFT_VERSION = 5.0; VERSIONING_SYSTEM = "apple-generic"; }; name = Release; }; 83CBBA201A601CBA00E9B192 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "arm64 "; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = ( /usr/lib/swift, "$(inherited)", ); LIBRARY_SEARCH_PATHS = ( "\"$(SDKROOT)/usr/lib/swift\"", "\"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)\"", "\"$(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)\"", "\"$(inherited)\"", ); MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; }; name = Debug; }; 83CBBA211A601CBA00E9B192 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = YES; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "arm64 "; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = ( /usr/lib/swift, "$(inherited)", ); LIBRARY_SEARCH_PATHS = ( "\"$(SDKROOT)/usr/lib/swift\"", "\"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)\"", "\"$(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)\"", "\"$(inherited)\"", ); MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; VALIDATE_PRODUCT = YES; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "CodePushDemoAppTests" */ = { isa = XCConfigurationList; buildConfigurations = ( 00E356F61AD99517003FC87E /* Debug */, 00E356F71AD99517003FC87E /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "CodePushDemoApp" */ = { isa = XCConfigurationList; buildConfigurations = ( 13B07F941A680F5B00A75B9A /* Debug */, 13B07F951A680F5B00A75B9A /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "CodePushDemoApp" */ = { isa = XCConfigurationList; buildConfigurations = ( 83CBBA201A601CBA00E9B192 /* Debug */, 83CBBA211A601CBA00E9B192 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 83CBB9F71A601CBA00E9B192 /* Project object */; } ================================================ FILE: Examples/CodePushDemoApp/ios/CodePushDemoApp.xcodeproj/xcshareddata/xcschemes/CodePushDemoApp.xcscheme ================================================ ================================================ FILE: Examples/CodePushDemoApp/ios/CodePushDemoApp.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Examples/CodePushDemoApp/ios/CodePushDemoApp.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: Examples/CodePushDemoApp/ios/CodePushDemoAppTests/CodePushDemoAppTests.m ================================================ #import #import #import #import #define TIMEOUT_SECONDS 600 #define TEXT_TO_LOOK_FOR @"Welcome to React" @interface CodePushDemoAppTests : XCTestCase @end @implementation CodePushDemoAppTests - (BOOL)findSubviewInView:(UIView *)view matching:(BOOL(^)(UIView *view))test { if (test(view)) { return YES; } for (UIView *subview in [view subviews]) { if ([self findSubviewInView:subview matching:test]) { return YES; } } return NO; } - (void)testRendersWelcomeScreen { UIViewController *vc = [[[RCTSharedApplication() delegate] window] rootViewController]; NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS]; BOOL foundElement = NO; __block NSString *redboxError = nil; #ifdef DEBUG RCTSetLogFunction(^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) { if (level >= RCTLogLevelError) { redboxError = message; } }); #endif while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) { [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; foundElement = [self findSubviewInView:vc.view matching:^BOOL(UIView *view) { if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) { return YES; } return NO; }]; } #ifdef DEBUG RCTSetLogFunction(RCTDefaultLogFunction); #endif XCTAssertNil(redboxError, @"RedBox error: %@", redboxError); XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS); } @end ================================================ FILE: Examples/CodePushDemoApp/ios/CodePushDemoAppTests/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 ================================================ FILE: Examples/CodePushDemoApp/ios/Podfile ================================================ require_relative '../node_modules/react-native/scripts/react_native_pods' require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules' platform :ios, '11.0' target 'CodePushDemoApp' do config = use_native_modules! use_react_native!( :path => config[:reactNativePath], # to enable hermes on iOS, change `false` to `true` and then install pods :hermes_enabled => false ) target 'CodePushDemoAppTests' do inherit! :complete # Pods for testing end # Enables Flipper. # # Note that if you have use_frameworks! enabled, Flipper will not work and # you should disable the next line. use_flipper!() post_install do |installer| react_native_post_install(installer) __apply_Xcode_12_5_M1_post_install_workaround(installer) end end ================================================ FILE: Examples/CodePushDemoApp/metro.config.js ================================================ /** * Metro configuration for React Native * https://github.com/facebook/react-native * * @format */ module.exports = { transformer: { getTransformOptions: async () => ({ transform: { experimentalImportSupport: false, inlineRequires: true, }, }), }, }; ================================================ FILE: Examples/CodePushDemoApp/package.json ================================================ { "name": "CodePushDemoApp", "version": "0.0.1", "private": true, "scripts": { "android": "react-native run-android", "ios": "react-native run-ios", "start": "react-native start", "test": "jest", "lint": "eslint ." }, "dependencies": { "react": "17.0.2", "react-native": "0.68.5", "react-native-code-push": "8.1.0" }, "resolutions": { "strip-ansi": "^6.0.1", "ansi-regex": "^5.0.1" }, "devDependencies": { "@babel/core": "^7.15.8", "@babel/runtime": "^7.15.4", "@react-native-community/eslint-config": "^3.0.1", "babel-jest": "^27.2.5", "eslint": "^8.0.0", "jest": "^27.2.5", "metro-react-native-babel-preset": "^0.66.2", "react-test-renderer": "17.0.2" }, "jest": { "preset": "react-native" } } ================================================ FILE: Examples/CodePushDemoAppCpp/.buckconfig ================================================ [android] target = Google Inc.:Google APIs:23 [maven_repositories] central = https://repo1.maven.org/maven2 ================================================ FILE: Examples/CodePushDemoAppCpp/.eslintrc.js ================================================ module.exports = { root: true, extends: '@react-native-community', }; ================================================ FILE: Examples/CodePushDemoAppCpp/.flowconfig ================================================ [ignore] ; We fork some components by platform .*/*[.]android.js ; Ignore "BUCK" generated dirs /\.buckd/ ; Ignore polyfills node_modules/react-native/Libraries/polyfills/.* ; These should not be required directly ; require from fbjs/lib instead: require('fbjs/lib/warning') node_modules/warning/.* ; Flow doesn't support platforms .*/Libraries/Utilities/LoadingView.js [untyped] .*/node_modules/@react-native-community/cli/.*/.* [include] [libs] node_modules/react-native/interface.js node_modules/react-native/flow/ [options] emoji=true esproposal.optional_chaining=enable esproposal.nullish_coalescing=enable module.file_ext=.js module.file_ext=.json module.file_ext=.ios.js munge_underscores=true module.name_mapper='^react-native/\(.*\)$' -> '/node_modules/react-native/\1' module.name_mapper='^@?[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> '/node_modules/react-native/Libraries/Image/RelativeImageStub' suppress_type=$FlowIssue suppress_type=$FlowFixMe suppress_type=$FlowFixMeProps suppress_type=$FlowFixMeState suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(\\)? *\\(site=[a-z,_]*react_native\\(_ios\\)?_\\(oss\\|fb\\)[a-z,_]*\\)?)\\) suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(\\)? *\\(site=[a-z,_]*react_native\\(_ios\\)?_\\(oss\\|fb\\)[a-z,_]*\\)?)\\)?:? #[0-9]+ suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError [lints] sketchy-null-number=warn sketchy-null-mixed=warn sketchy-number=warn untyped-type-import=warn nonstrict-import=warn deprecated-type=warn unsafe-getters-setters=warn unnecessary-invariant=warn signature-verification-failure=warn deprecated-utility=error [strict] deprecated-type nonstrict-import sketchy-null unclear-type unsafe-getters-setters untyped-import untyped-type-import [version] ^0.122.0 ================================================ FILE: Examples/CodePushDemoAppCpp/.gitattributes ================================================ *.pbxproj -text ================================================ FILE: Examples/CodePushDemoAppCpp/.gitignore ================================================ # OSX # .DS_Store # Xcode # build/ *.pbxuser !default.pbxuser *.mode1v3 !default.mode1v3 *.mode2v3 !default.mode2v3 *.perspectivev3 !default.perspectivev3 xcuserdata *.xccheckout *.moved-aside DerivedData *.hmap *.ipa *.xcuserstate # Android/IntelliJ # build/ .idea .gradle local.properties *.iml # Visual Studio Code # .vscode/ # node.js # node_modules/ npm-debug.log yarn-error.log # BUCK buck-out/ \.buckd/ *.keystore !debug.keystore # fastlane # # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the # screenshots whenever they are needed. # For more information about the recommended setup visit: # https://docs.fastlane.tools/best-practices/source-control/ */fastlane/report.xml */fastlane/Preview.html */fastlane/screenshots # Bundle artifact *.jsbundle # CocoaPods /ios/Pods/ ================================================ FILE: Examples/CodePushDemoAppCpp/.prettierrc.js ================================================ module.exports = { bracketSpacing: false, jsxBracketSameLine: true, singleQuote: true, trailingComma: 'all', }; ================================================ FILE: Examples/CodePushDemoAppCpp/.watchmanconfig ================================================ {} ================================================ FILE: Examples/CodePushDemoAppCpp/App.js ================================================ import React, { Component } from 'react'; import { AppRegistry, Dimensions, Image, SafeAreaView, ScrollView, StyleSheet, Text, TouchableOpacity, View, } from 'react-native'; import CodePush from "react-native-code-push"; class App extends Component<{}> { constructor() { super(); this.state = { restartAllowed: true }; } codePushStatusDidChange(syncStatus) { switch(syncStatus) { case CodePush.SyncStatus.CHECKING_FOR_UPDATE: this.setState({ syncMessage: "Checking for update." }); break; case CodePush.SyncStatus.DOWNLOADING_PACKAGE: this.setState({ syncMessage: "Downloading package." }); break; case CodePush.SyncStatus.AWAITING_USER_ACTION: this.setState({ syncMessage: "Awaiting user action." }); break; case CodePush.SyncStatus.INSTALLING_UPDATE: this.setState({ syncMessage: "Installing update." }); break; case CodePush.SyncStatus.UP_TO_DATE: this.setState({ syncMessage: "App up to date.", progress: false }); break; case CodePush.SyncStatus.UPDATE_IGNORED: this.setState({ syncMessage: "Update cancelled by user.", progress: false }); break; case CodePush.SyncStatus.UPDATE_INSTALLED: this.setState({ syncMessage: "Update installed and will be applied on restart.", progress: false }); break; case CodePush.SyncStatus.UNKNOWN_ERROR: this.setState({ syncMessage: "An unknown error occurred.", progress: false }); break; } } codePushDownloadDidProgress(progress) { this.setState({ progress }); } toggleAllowRestart() { this.state.restartAllowed ? CodePush.disallowRestart() : CodePush.allowRestart(); this.setState({ restartAllowed: !this.state.restartAllowed }); } getUpdateMetadata() { CodePush.getUpdateMetadata(CodePush.UpdateState.RUNNING) .then((metadata: LocalPackage) => { this.setState({ syncMessage: metadata ? JSON.stringify(metadata) : "Running binary version", progress: false }); }, (error: any) => { this.setState({ syncMessage: "Error: " + error, progress: false }); }); } /** Update is downloaded silently, and applied on restart (recommended) */ sync() { CodePush.sync( {}, this.codePushStatusDidChange.bind(this), this.codePushDownloadDidProgress.bind(this) ); } /** Update pops a confirmation dialog, and then immediately reboots the app */ syncImmediate() { CodePush.sync( { installMode: CodePush.InstallMode.IMMEDIATE, updateDialog: true }, this.codePushStatusDidChange.bind(this), this.codePushDownloadDidProgress.bind(this) ); } restartApp() { CodePush.restartApp(); } render() { let progressView; if (this.state.progress) { progressView = ( {this.state.progress.receivedBytes} of {this.state.progress.totalBytes} bytes received ); } return ( Welcome to CodePush! Demo bundle Press to restart Press for background sync Press for dialog-driven sync {progressView} Restart { this.state.restartAllowed ? "allowed" : "forbidden"} Press for Update Metadata {this.state.syncMessage || ""} ); } } const styles = StyleSheet.create({ container: { flex: 1, alignItems: "center", backgroundColor: "#F5FCFF", paddingTop: 50 }, image: { margin: 30, width: Dimensions.get("window").width - 100, height: 365 * (Dimensions.get("window").width - 100) / 651, }, messages: { marginTop: 30, textAlign: "center", }, restartToggleButton: { color: "blue", fontSize: 17 }, syncButton: { color: "green", fontSize: 17 }, welcome: { fontSize: 20, textAlign: "center", margin: 20 }, }); /** * Configured with a MANUAL check frequency for easy testing. For production apps, it is recommended to configure a * different check frequency, such as ON_APP_START, for a 'hands-off' approach where CodePush.sync() does not * need to be explicitly called. All options of CodePush.sync() are also available in this decorator. */ let codePushOptions = { checkFrequency: CodePush.CheckFrequency.MANUAL }; App = CodePush(codePushOptions)(App); export default App; ================================================ FILE: Examples/CodePushDemoAppCpp/app.json ================================================ { "name": "CodePushDemoAppCpp", "displayName": "CodePushDemoAppCpp" } ================================================ FILE: Examples/CodePushDemoAppCpp/babel.config.js ================================================ module.exports = { presets: ['module:metro-react-native-babel-preset'], }; ================================================ FILE: Examples/CodePushDemoAppCpp/index.js ================================================ /** * @format */ import {AppRegistry} from 'react-native'; import App from './App'; import {name as appName} from './app.json'; AppRegistry.registerComponent(appName, () => App); ================================================ FILE: Examples/CodePushDemoAppCpp/metro.config.js ================================================ /** * Metro configuration for React Native * https://github.com/facebook/react-native * * @format */ const path = require('path'); const blacklist = require('metro-config/src/defaults/blacklist'); module.exports = { resolver: { blacklistRE: blacklist([ // This stops "react-native run-windows" from causing the metro server to crash if its already running new RegExp( `${path.resolve(__dirname, 'windows').replace(/[/\\]/g, '/')}.*`, ), // This prevents "react-native run-windows" from hitting: EBUSY: resource busy or locked, open msbuild.ProjectImports.zip /.*\.ProjectImports\.zip/, ]), }, transformer: { getTransformOptions: async () => ({ transform: { experimentalImportSupport: false, inlineRequires: false, }, }), }, }; ================================================ FILE: Examples/CodePushDemoAppCpp/package.json ================================================ { "name": "CodePushDemoAppCpp", "version": "0.0.1", "private": true, "scripts": { "start": "react-native start", "test": "jest", "lint": "eslint .", "windows": "react-native run-windows" }, "dependencies": { "react": "^17.0.2", "react-native": "^0.68.5", "react-native-code-push": "^8.1.0", "react-native-windows": "^1.0.0" }, "resolutions": { "strip-ansi": "^6.0.1", "ansi-regex": "^5.0.1", "node-fetch": "^2.6.7" }, "devDependencies": { "@babel/core": "^7.8.4", "@babel/runtime": "^7.8.4", "@react-native-community/eslint-config": "^3.0.1", "appcenter-cli": "^2.14.0", "babel-jest": "^27.2.5", "eslint": "^8.0.0", "jest": "^27.2.5", "metro-react-native-babel-preset": "^0.66.2", "react-test-renderer": "17.0.2" }, "jest": { "preset": "react-native" } } ================================================ FILE: Examples/CodePushDemoAppCpp/windows/.gitignore ================================================ *AppPackages* *BundleArtifacts* #OS junk files [Tt]humbs.db *.DS_Store #Visual Studio files *.[Oo]bj *.user *.aps *.pch *.vspscc *.vssscc *_i.c *_p.c *.ncb *.suo *.tlb *.tlh *.bak *.[Cc]ache *.ilk *.log *.lib *.sbr *.sdf *.opensdf *.opendb *.unsuccessfulbuild ipch/ [Oo]bj/ [Bb]in [Dd]ebug*/ [Rr]elease*/ Ankh.NoLoad # Visual C++ cache files ipch/ *.aps *.ncb *.opendb *.opensdf *.sdf *.cachefile *.VC.db *.VC.VC.opendb #MonoDevelop *.pidb *.userprefs #Tooling _ReSharper*/ *.resharper [Tt]est[Rr]esult* *.sass-cache #Project files [Bb]uild/ #Subversion files .svn # Office Temp Files ~$* # vim Temp Files *~ #NuGet packages/ *.nupkg #ncrunch *ncrunch* *crunch*.local.xml # visual studio database projects *.dbmdl #Test files *.testsettings #Other files *.DotSettings .vs/ *project.lock.json #Files generated by the VS build **/Generated Files/** ================================================ FILE: Examples/CodePushDemoAppCpp/windows/CodePushDemoAppCpp/.gitignore ================================================ /Bundle ================================================ FILE: Examples/CodePushDemoAppCpp/windows/CodePushDemoAppCpp/App.cpp ================================================ #include "pch.h" #include "App.h" #include "AutolinkedNativeModules.g.h" #include "ReactPackageProvider.h" #include "winrt/Microsoft.CodePush.ReactNative.h" #include "winrt/Windows.Storage.h" #include "winrt/Windows.Foundation.h" #include "winrt/Windows.Data.Json.h" #include using namespace winrt::CodePushDemoAppCpp; using namespace winrt::CodePushDemoAppCpp::implementation; using namespace winrt; using namespace Windows::UI::Xaml; using namespace Windows::UI::Xaml::Controls; using namespace Windows::UI::Xaml::Navigation; using namespace Windows::ApplicationModel; using namespace Windows::ApplicationModel::Activation; using namespace Windows::Storage; using namespace Windows::Data::Json; using namespace Microsoft::ReactNative; using namespace std; /// /// Initializes the singleton application object. This is the first line of /// authored code executed, and as such is the logical equivalent of main() or /// WinMain(). /// App::App() noexcept { #if BUNDLE m_host.InstanceSettings().JavaScriptBundleFile(L"index.windows"); m_host.InstanceSettings().UseWebDebugger(false); m_host.InstanceSettings().UseFastRefresh(false); #else m_host.InstanceSettings().JavaScriptMainModuleName(L"index"); m_host.InstanceSettings().UseWebDebugger(true); m_host.InstanceSettings().UseFastRefresh(true); #endif #if _DEBUG m_host.InstanceSettings().UseDeveloperSupport(true); #else m_host.InstanceSettings().UseDeveloperSupport(false); #endif RegisterAutolinkedNativeModulePackages(m_host.InstanceSettings().PackageProviders()); // Includes any autolinked modules m_host.InstanceSettings().PackageProviders().Append(make()); // Includes all modules in this project InitializeComponent(); Suspending({ this, &App::OnSuspending }); #if defined _DEBUG && !defined DISABLE_XAML_GENERATED_BREAK_ON_UNHANDLED_EXCEPTION UnhandledException([this](IInspectable const&, UnhandledExceptionEventArgs const& e) { if (IsDebuggerPresent()) { auto errorMessage = e.Message(); __debugbreak(); } }); #endif } /// /// Invoked when the application is launched normally by the end user. Other entry points /// will be used such as when the application is launched to open a specific file. /// /// Details about the launch request and process. void App::OnLaunched(activation::LaunchActivatedEventArgs const& e) { winrt::Microsoft::CodePush::ReactNative::CodePushConfig::SetHost(Host()); auto configMap{ winrt::single_threaded_map() }; configMap.Insert(L"appVersion", L"1.0.0"); configMap.Insert(L"deploymentKey", L""); winrt::Microsoft::CodePush::ReactNative::CodePushConfig::Init(configMap); Frame rootFrame{ nullptr }; auto content = Window::Current().Content(); if (content) { rootFrame = content.try_as(); } // Do not repeat app initialization when the Window already has content, // just ensure that the window is active if (rootFrame == nullptr) { // Create a Frame to act as the navigation context and associate it with // a SuspensionManager key rootFrame = Frame(); rootFrame.NavigationFailed({ this, &App::OnNavigationFailed }); if (e.PreviousExecutionState() == ApplicationExecutionState::Terminated) { // Restore the saved session state only when appropriate, scheduling the // final launch steps after the restore is complete } if (e.PrelaunchActivated() == false) { if (rootFrame.Content() == nullptr) { // When the navigation stack isn't restored navigate to the first page, // configuring the new page by passing required information as a navigation // parameter rootFrame.Navigate(xaml_typename(), box_value(e.Arguments())); } // Place the frame in the current Window Window::Current().Content(rootFrame); // Ensure the current window is active Window::Current().Activate(); } } else { if (e.PrelaunchActivated() == false) { if (rootFrame.Content() == nullptr) { // When the navigation stack isn't restored navigate to the first page, // configuring the new page by passing required information as a navigation // parameter rootFrame.Navigate(xaml_typename(), box_value(e.Arguments())); } // Ensure the current window is active Window::Current().Activate(); } } } /// /// Invoked when application execution is being suspended. Application state is saved /// without knowing whether the application will be terminated or resumed with the contents /// of memory still intact. /// /// The source of the suspend request. /// Details about the suspend request. void App::OnSuspending([[maybe_unused]] IInspectable const& sender, [[maybe_unused]] SuspendingEventArgs const& e) { // Save application state and stop any background activity } /// /// Invoked when Navigation to a certain page fails /// /// The Frame which failed navigation /// Details about the navigation failure void App::OnNavigationFailed(IInspectable const&, NavigationFailedEventArgs const& e) { throw hresult_error(E_FAIL, hstring(L"Failed to load Page ") + e.SourcePageType().Name); } ================================================ FILE: Examples/CodePushDemoAppCpp/windows/CodePushDemoAppCpp/App.h ================================================ #pragma once #include "App.xaml.g.h" #include "winrt/Microsoft.ReactNative.h" namespace activation = winrt::Windows::ApplicationModel::Activation; namespace winrt::CodePushDemoAppCpp::implementation { struct App : AppT { App() noexcept; void OnLaunched(Windows::ApplicationModel::Activation::LaunchActivatedEventArgs const&); void OnSuspending(IInspectable const&, Windows::ApplicationModel::SuspendingEventArgs const&); void OnNavigationFailed(IInspectable const&, Windows::UI::Xaml::Navigation::NavigationFailedEventArgs const&); winrt::Microsoft::ReactNative::ReactNativeHost& Host() noexcept { return m_host; } private: winrt::Microsoft::ReactNative::ReactNativeHost m_host; }; } // namespace winrt::CodePushDemoAppCpp::implementation ================================================ FILE: Examples/CodePushDemoAppCpp/windows/CodePushDemoAppCpp/App.idl ================================================ namespace CodePushDemoAppCpp { } ================================================ FILE: Examples/CodePushDemoAppCpp/windows/CodePushDemoAppCpp/App.xaml ================================================  ================================================ FILE: Examples/CodePushDemoAppCpp/windows/CodePushDemoAppCpp/AutolinkedNativeModules.g.cpp ================================================ // AutolinkedNativeModules.g.cpp contents generated by "react-native autolink-windows" // clang-format off #include "pch.h" #include "AutolinkedNativeModules.g.h" // Includes from react-native-code-push-windows #include "winrt/Microsoft.CodePush.ReactNative.h" namespace winrt::Microsoft::ReactNative { void RegisterAutolinkedNativeModulePackages(winrt::Windows::Foundation::Collections::IVector const& packageProviders) { // IReactPackageProviders from react-native-code-push-windows packageProviders.Append(winrt::Microsoft::CodePush::ReactNative::ReactPackageProvider()); } } ================================================ FILE: Examples/CodePushDemoAppCpp/windows/CodePushDemoAppCpp/AutolinkedNativeModules.g.h ================================================ // AutolinkedNativeModules.g.h contents generated by "react-native autolink-windows" #pragma once namespace winrt::Microsoft::ReactNative { void RegisterAutolinkedNativeModulePackages(winrt::Windows::Foundation::Collections::IVector const& packageProviders); } ================================================ FILE: Examples/CodePushDemoAppCpp/windows/CodePushDemoAppCpp/AutolinkedNativeModules.g.targets ================================================ ================================================ FILE: Examples/CodePushDemoAppCpp/windows/CodePushDemoAppCpp/CodePushDemoAppCpp.vcxproj ================================================ true true true {609f44f6-01cf-4270-85a3-09f9ca10b434} CodePushDemoAppCpp CodePushDemoAppCpp en-US 16.0 true Windows Store 10.0 10.0.18362.0 10.0.16299.0 CodePushDemoAppCpp_TemporaryKey.pfx 5FBADC5BFA887CF7B571A1685542D69E23F6A0F2 password $([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), 'node_modules\react-native-windows\package.json'))\node_modules\react-native-windows\ true false Debug ARM Debug ARM64 Debug Win32 Debug x64 Release ARM Release ARM64 Release Win32 Release x64 Application Unicode true true false true false Use pch.h $(IntDir)pch.pch Level4 %(AdditionalOptions) /bigobj 4453;28204 _DEBUG;%(PreprocessorDefinitions) NDEBUG;%(PreprocessorDefinitions) MainPage.xaml Code App.xaml Designer Designer MainPage.xaml Code Create App.xaml App.xaml MainPage.xaml Code Designer {a6b6216e-fa3f-45e2-9c8e-40023cce9132} This project references targets in your node_modules\react-native-windows folder. The missing file is {0}. This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. ================================================ FILE: Examples/CodePushDemoAppCpp/windows/CodePushDemoAppCpp/CodePushDemoAppCpp.vcxproj.filters ================================================  Assets Assets Assets Assets Assets Assets Assets {e48dc53e-40b1-40cb-970a-f89935452892} ================================================ FILE: Examples/CodePushDemoAppCpp/windows/CodePushDemoAppCpp/MainPage.cpp ================================================ #include "pch.h" #include "MainPage.h" #if __has_include("MainPage.g.cpp") #include "MainPage.g.cpp" #endif #include "App.h" using namespace winrt; using namespace Windows::UI::Xaml; namespace winrt::CodePushDemoAppCpp::implementation { MainPage::MainPage() { InitializeComponent(); auto app = Application::Current().as(); ReactRootView().ReactNativeHost(app->Host()); } } ================================================ FILE: Examples/CodePushDemoAppCpp/windows/CodePushDemoAppCpp/MainPage.h ================================================ #pragma once #include "MainPage.g.h" #include namespace winrt::CodePushDemoAppCpp::implementation { struct MainPage : MainPageT { MainPage(); }; } namespace winrt::CodePushDemoAppCpp::factory_implementation { struct MainPage : MainPageT { }; } ================================================ FILE: Examples/CodePushDemoAppCpp/windows/CodePushDemoAppCpp/MainPage.idl ================================================ namespace CodePushDemoAppCpp { [default_interface] runtimeclass MainPage : Windows.UI.Xaml.Controls.Page { MainPage(); } } ================================================ FILE: Examples/CodePushDemoAppCpp/windows/CodePushDemoAppCpp/MainPage.xaml ================================================ ================================================ FILE: Examples/CodePushDemoAppCpp/windows/CodePushDemoAppCpp/Package.appxmanifest ================================================  CodePushDemoAppCpp Aleksey Assets\StoreLogo.png ================================================ FILE: Examples/CodePushDemoAppCpp/windows/CodePushDemoAppCpp/PropertySheet.props ================================================ ================================================ FILE: Examples/CodePushDemoAppCpp/windows/CodePushDemoAppCpp/ReactPackageProvider.cpp ================================================ #include "pch.h" #include "ReactPackageProvider.h" #include "NativeModules.h" using namespace winrt::Microsoft::ReactNative; namespace winrt::CodePushDemoAppCpp::implementation { void ReactPackageProvider::CreatePackage(IReactPackageBuilder const &packageBuilder) noexcept { AddAttributedModules(packageBuilder); } } // namespace winrt::CodePushDemoAppCpp::implementation ================================================ FILE: Examples/CodePushDemoAppCpp/windows/CodePushDemoAppCpp/ReactPackageProvider.h ================================================ #pragma once #include "winrt/Microsoft.ReactNative.h" namespace winrt::CodePushDemoAppCpp::implementation { struct ReactPackageProvider : winrt::implements { public: // IReactPackageProvider void CreatePackage(winrt::Microsoft::ReactNative::IReactPackageBuilder const &packageBuilder) noexcept; }; } // namespace winrt::CodePushDemoAppCpp::implementation ================================================ FILE: Examples/CodePushDemoAppCpp/windows/CodePushDemoAppCpp/packages.config ================================================  ================================================ FILE: Examples/CodePushDemoAppCpp/windows/CodePushDemoAppCpp/pch.cpp ================================================ #include "pch.h" ================================================ FILE: Examples/CodePushDemoAppCpp/windows/CodePushDemoAppCpp/pch.h ================================================ #pragma once #define NOMINMAX #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include ================================================ FILE: Examples/CodePushDemoAppCpp/windows/CodePushDemoAppCpp.sln ================================================  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 16 VisualStudioVersion = 16.0.29215.179 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CodePushDemoAppCpp", "CodePushDemoAppCpp\CodePushDemoAppCpp.vcxproj", "{609F44F6-01CF-4270-85A3-09F9CA10B434}" ProjectSection(ProjectDependencies) = postProject {F7D32BD0-2749-483E-9A0D-1635EF7E3136} = {F7D32BD0-2749-483E-9A0D-1635EF7E3136} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Folly", "..\node_modules\react-native-windows\Folly\Folly.vcxproj", "{A990658C-CE31-4BCC-976F-0FC6B1AF693D}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ReactCommon", "..\node_modules\react-native-windows\ReactCommon\ReactCommon.vcxproj", "{A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}" ProjectSection(ProjectDependencies) = postProject {A990658C-CE31-4BCC-976F-0FC6B1AF693D} = {A990658C-CE31-4BCC-976F-0FC6B1AF693D} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Chakra", "..\node_modules\react-native-windows\Chakra\Chakra.vcxitems", "{C38970C0-5FBF-4D69-90D8-CBAC225AE895}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.ReactNative", "..\node_modules\react-native-windows\Microsoft.ReactNative\Microsoft.ReactNative.vcxproj", "{F7D32BD0-2749-483E-9A0D-1635EF7E3136}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "JSI.Shared", "..\node_modules\react-native-windows\JSI\Shared\JSI.Shared.vcxitems", "{0CC28589-39E4-4288-B162-97B959F8B843}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "JSI.Universal", "..\node_modules\react-native-windows\JSI\Universal\JSI.Universal.vcxproj", "{A62D504A-16B8-41D2-9F19-E2E86019E5E4}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.ReactNative.Cxx", "..\node_modules\react-native-windows\Microsoft.ReactNative.Cxx\Microsoft.ReactNative.Cxx.vcxitems", "{DA8B35B3-DA00-4B02-BDE6-6A397B3FD46B}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Common", "..\node_modules\react-native-windows\Common\Common.vcxproj", "{FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ReactNative", "ReactNative", "{5EA20F54-880A-49F3-99FA-4B3FE54E8AB1}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.ReactNative.Shared", "..\node_modules\react-native-windows\Shared\Shared.vcxitems", "{2049DBE9-8D13-42C9-AE4B-413AE38FFFD0}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Mso", "..\node_modules\react-native-windows\Mso\Mso.vcxitems", "{84E05BFA-CBAF-4F0D-BFB6-4CE85742A57E}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Include", "..\node_modules\react-native-windows\include\Include.vcxitems", "{EF074BA1-2D54-4D49-A28E-5E040B47CD2E}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CodePush", "..\..\..\windows\CodePush\CodePush.vcxproj", "{A6B6216E-FA3F-45E2-9C8E-40023CCE9132}" EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution ..\node_modules\react-native-windows\JSI\Shared\JSI.Shared.vcxitems*{0cc28589-39e4-4288-b162-97b959f8b843}*SharedItemsImports = 9 ..\node_modules\react-native-windows\Shared\Shared.vcxitems*{2049dbe9-8d13-42c9-ae4b-413ae38fffd0}*SharedItemsImports = 9 ..\node_modules\react-native-windows\Mso\Mso.vcxitems*{84e05bfa-cbaf-4f0d-bfb6-4ce85742a57e}*SharedItemsImports = 9 ..\node_modules\react-native-windows\JSI\Shared\JSI.Shared.vcxitems*{a62d504a-16b8-41d2-9f19-e2e86019e5e4}*SharedItemsImports = 4 ..\node_modules\react-native-windows\Chakra\Chakra.vcxitems*{c38970c0-5fbf-4d69-90d8-cbac225ae895}*SharedItemsImports = 9 ..\node_modules\react-native-windows\Microsoft.ReactNative.Cxx\Microsoft.ReactNative.Cxx.vcxitems*{da8b35b3-da00-4b02-bde6-6a397b3fd46b}*SharedItemsImports = 9 ..\node_modules\react-native-windows\include\Include.vcxitems*{ef074ba1-2d54-4d49-a28e-5e040b47cd2e}*SharedItemsImports = 9 ..\node_modules\react-native-windows\Chakra\Chakra.vcxitems*{f7d32bd0-2749-483e-9a0d-1635ef7e3136}*SharedItemsImports = 4 ..\node_modules\react-native-windows\Microsoft.ReactNative.Cxx\Microsoft.ReactNative.Cxx.vcxitems*{f7d32bd0-2749-483e-9a0d-1635ef7e3136}*SharedItemsImports = 4 ..\node_modules\react-native-windows\Mso\Mso.vcxitems*{f7d32bd0-2749-483e-9a0d-1635ef7e3136}*SharedItemsImports = 4 ..\node_modules\react-native-windows\Shared\Shared.vcxitems*{f7d32bd0-2749-483e-9a0d-1635ef7e3136}*SharedItemsImports = 4 EndGlobalSection GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|ARM = Debug|ARM Debug|ARM64 = Debug|ARM64 Debug|x64 = Debug|x64 Debug|x86 = Debug|x86 Release|ARM = Release|ARM Release|ARM64 = Release|ARM64 Release|x64 = Release|x64 Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {609F44F6-01CF-4270-85A3-09F9CA10B434}.Debug|ARM.ActiveCfg = Debug|ARM {609F44F6-01CF-4270-85A3-09F9CA10B434}.Debug|ARM.Build.0 = Debug|ARM {609F44F6-01CF-4270-85A3-09F9CA10B434}.Debug|ARM.Deploy.0 = Debug|ARM {609F44F6-01CF-4270-85A3-09F9CA10B434}.Debug|ARM64.ActiveCfg = Debug|ARM64 {609F44F6-01CF-4270-85A3-09F9CA10B434}.Debug|ARM64.Build.0 = Debug|ARM64 {609F44F6-01CF-4270-85A3-09F9CA10B434}.Debug|ARM64.Deploy.0 = Debug|ARM64 {609F44F6-01CF-4270-85A3-09F9CA10B434}.Debug|x64.ActiveCfg = Debug|x64 {609F44F6-01CF-4270-85A3-09F9CA10B434}.Debug|x64.Build.0 = Debug|x64 {609F44F6-01CF-4270-85A3-09F9CA10B434}.Debug|x64.Deploy.0 = Debug|x64 {609F44F6-01CF-4270-85A3-09F9CA10B434}.Debug|x86.ActiveCfg = Debug|Win32 {609F44F6-01CF-4270-85A3-09F9CA10B434}.Debug|x86.Build.0 = Debug|Win32 {609F44F6-01CF-4270-85A3-09F9CA10B434}.Debug|x86.Deploy.0 = Debug|Win32 {609F44F6-01CF-4270-85A3-09F9CA10B434}.Release|ARM.ActiveCfg = Release|ARM {609F44F6-01CF-4270-85A3-09F9CA10B434}.Release|ARM.Build.0 = Release|ARM {609F44F6-01CF-4270-85A3-09F9CA10B434}.Release|ARM.Deploy.0 = Release|ARM {609F44F6-01CF-4270-85A3-09F9CA10B434}.Release|ARM64.ActiveCfg = Release|ARM64 {609F44F6-01CF-4270-85A3-09F9CA10B434}.Release|ARM64.Build.0 = Release|ARM64 {609F44F6-01CF-4270-85A3-09F9CA10B434}.Release|ARM64.Deploy.0 = Release|ARM64 {609F44F6-01CF-4270-85A3-09F9CA10B434}.Release|x64.ActiveCfg = Release|x64 {609F44F6-01CF-4270-85A3-09F9CA10B434}.Release|x64.Build.0 = Release|x64 {609F44F6-01CF-4270-85A3-09F9CA10B434}.Release|x64.Deploy.0 = Release|x64 {609F44F6-01CF-4270-85A3-09F9CA10B434}.Release|x86.ActiveCfg = Release|Win32 {609F44F6-01CF-4270-85A3-09F9CA10B434}.Release|x86.Build.0 = Release|Win32 {609F44F6-01CF-4270-85A3-09F9CA10B434}.Release|x86.Deploy.0 = Release|Win32 {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Debug|ARM.ActiveCfg = Debug|ARM {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Debug|ARM.Build.0 = Debug|ARM {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Debug|ARM64.ActiveCfg = Debug|ARM64 {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Debug|ARM64.Build.0 = Debug|ARM64 {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Debug|x64.ActiveCfg = Debug|x64 {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Debug|x64.Build.0 = Debug|x64 {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Debug|x86.ActiveCfg = Debug|Win32 {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Debug|x86.Build.0 = Debug|Win32 {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Release|ARM.ActiveCfg = Release|ARM {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Release|ARM.Build.0 = Release|ARM {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Release|ARM64.ActiveCfg = Release|ARM64 {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Release|ARM64.Build.0 = Release|ARM64 {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Release|x64.ActiveCfg = Release|x64 {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Release|x64.Build.0 = Release|x64 {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Release|x86.ActiveCfg = Release|Win32 {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Release|x86.Build.0 = Release|Win32 {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Debug|ARM.ActiveCfg = Debug|ARM {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Debug|ARM.Build.0 = Debug|ARM {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Debug|ARM64.ActiveCfg = Debug|ARM64 {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Debug|ARM64.Build.0 = Debug|ARM64 {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Debug|x64.ActiveCfg = Debug|x64 {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Debug|x64.Build.0 = Debug|x64 {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Debug|x86.ActiveCfg = Debug|Win32 {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Debug|x86.Build.0 = Debug|Win32 {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Release|ARM.ActiveCfg = Release|ARM {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Release|ARM.Build.0 = Release|ARM {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Release|ARM64.ActiveCfg = Release|ARM64 {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Release|ARM64.Build.0 = Release|ARM64 {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Release|x64.ActiveCfg = Release|x64 {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Release|x64.Build.0 = Release|x64 {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Release|x86.ActiveCfg = Release|Win32 {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Release|x86.Build.0 = Release|Win32 {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Debug|ARM.ActiveCfg = Debug|ARM {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Debug|ARM.Build.0 = Debug|ARM {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Debug|ARM64.ActiveCfg = Debug|ARM64 {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Debug|ARM64.Build.0 = Debug|ARM64 {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Debug|x64.ActiveCfg = Debug|x64 {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Debug|x64.Build.0 = Debug|x64 {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Debug|x86.ActiveCfg = Debug|Win32 {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Debug|x86.Build.0 = Debug|Win32 {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Release|ARM.ActiveCfg = Release|ARM {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Release|ARM.Build.0 = Release|ARM {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Release|ARM64.ActiveCfg = Release|ARM64 {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Release|ARM64.Build.0 = Release|ARM64 {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Release|x64.ActiveCfg = Release|x64 {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Release|x64.Build.0 = Release|x64 {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Release|x86.ActiveCfg = Release|Win32 {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Release|x86.Build.0 = Release|Win32 {A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Debug|ARM.ActiveCfg = Debug|ARM {A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Debug|ARM.Build.0 = Debug|ARM {A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Debug|ARM64.ActiveCfg = Debug|ARM64 {A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Debug|ARM64.Build.0 = Debug|ARM64 {A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Debug|x64.ActiveCfg = Debug|x64 {A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Debug|x64.Build.0 = Debug|x64 {A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Debug|x86.ActiveCfg = Debug|Win32 {A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Debug|x86.Build.0 = Debug|Win32 {A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Release|ARM.ActiveCfg = Release|ARM {A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Release|ARM.Build.0 = Release|ARM {A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Release|ARM64.ActiveCfg = Release|ARM64 {A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Release|ARM64.Build.0 = Release|ARM64 {A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Release|x64.ActiveCfg = Release|x64 {A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Release|x64.Build.0 = Release|x64 {A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Release|x86.ActiveCfg = Release|Win32 {A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Release|x86.Build.0 = Release|Win32 {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Debug|ARM.ActiveCfg = Debug|ARM {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Debug|ARM.Build.0 = Debug|ARM {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Debug|ARM64.ActiveCfg = Debug|ARM64 {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Debug|ARM64.Build.0 = Debug|ARM64 {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Debug|x64.ActiveCfg = Debug|x64 {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Debug|x64.Build.0 = Debug|x64 {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Debug|x86.ActiveCfg = Debug|Win32 {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Debug|x86.Build.0 = Debug|Win32 {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Release|ARM.ActiveCfg = Release|ARM {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Release|ARM.Build.0 = Release|ARM {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Release|ARM64.ActiveCfg = Release|ARM64 {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Release|ARM64.Build.0 = Release|ARM64 {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Release|x64.ActiveCfg = Release|x64 {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Release|x64.Build.0 = Release|x64 {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Release|x86.ActiveCfg = Release|Win32 {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Release|x86.Build.0 = Release|Win32 {A6B6216E-FA3F-45E2-9C8E-40023CCE9132}.Debug|ARM.ActiveCfg = Debug|ARM {A6B6216E-FA3F-45E2-9C8E-40023CCE9132}.Debug|ARM.Build.0 = Debug|ARM {A6B6216E-FA3F-45E2-9C8E-40023CCE9132}.Debug|ARM64.ActiveCfg = Debug|ARM64 {A6B6216E-FA3F-45E2-9C8E-40023CCE9132}.Debug|ARM64.Build.0 = Debug|ARM64 {A6B6216E-FA3F-45E2-9C8E-40023CCE9132}.Debug|x64.ActiveCfg = Debug|x64 {A6B6216E-FA3F-45E2-9C8E-40023CCE9132}.Debug|x64.Build.0 = Debug|x64 {A6B6216E-FA3F-45E2-9C8E-40023CCE9132}.Debug|x86.ActiveCfg = Debug|Win32 {A6B6216E-FA3F-45E2-9C8E-40023CCE9132}.Debug|x86.Build.0 = Debug|Win32 {A6B6216E-FA3F-45E2-9C8E-40023CCE9132}.Release|ARM.ActiveCfg = Release|ARM {A6B6216E-FA3F-45E2-9C8E-40023CCE9132}.Release|ARM.Build.0 = Release|ARM {A6B6216E-FA3F-45E2-9C8E-40023CCE9132}.Release|ARM64.ActiveCfg = Release|ARM64 {A6B6216E-FA3F-45E2-9C8E-40023CCE9132}.Release|ARM64.Build.0 = Release|ARM64 {A6B6216E-FA3F-45E2-9C8E-40023CCE9132}.Release|x64.ActiveCfg = Release|x64 {A6B6216E-FA3F-45E2-9C8E-40023CCE9132}.Release|x64.Build.0 = Release|x64 {A6B6216E-FA3F-45E2-9C8E-40023CCE9132}.Release|x86.ActiveCfg = Release|Win32 {A6B6216E-FA3F-45E2-9C8E-40023CCE9132}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution {A990658C-CE31-4BCC-976F-0FC6B1AF693D} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1} {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1} {C38970C0-5FBF-4D69-90D8-CBAC225AE895} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1} {F7D32BD0-2749-483E-9A0D-1635EF7E3136} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1} {0CC28589-39E4-4288-B162-97B959F8B843} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1} {A62D504A-16B8-41D2-9F19-E2E86019E5E4} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1} {DA8B35B3-DA00-4B02-BDE6-6A397B3FD46B} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1} {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1} {2049DBE9-8D13-42C9-AE4B-413AE38FFFD0} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1} {84E05BFA-CBAF-4F0D-BFB6-4CE85742A57E} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1} {EF074BA1-2D54-4D49-A28E-5E040B47CD2E} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {D43FAD39-F619-437D-BB40-04A3982ACB6A} EndGlobalSection EndGlobal ================================================ FILE: Examples/create-app.js ================================================ /* The script serves to generate CodePushified React Native app to reproduce issues or for testing purposes. NOTE: Use CodePushDemoApp and CodePushDemoAppCpp as reference how to implement CodePush in your app. For creating a working demo app follow steps bellow. Requirements: 1. npm i -g react-native-cli 2. npm i -g appcenter-cli 3. appcenter login 4. If you use this script on macOS for react-native v0.60+ then you need to have CocoaPods installed. Use this command to (re)install CocoaPods: sudo gem install cocoapods -n /usr/local/bin Usage: node create-app.js 1. node create-app.js 2. node create-app.js myapp 3. node create-app.js myapp react-native@0.62 react-native-code-push@6.1.0 4. node create-app.js myapp react-native@latest Microsoft/react-native-code-push Parameters: 1. - CodePushDemoAppTest 2. - react-native@latest 3. - react-native-code-push@latest */ const fs = require('fs'); const path = require('path'); const nexpect = require('./nexpect'); const child_process = require('child_process'); const execSync = child_process.execSync; const args = process.argv.slice(2); const appName = args[0] || 'CodePushDemoAppTest'; if (fs.existsSync(appName)) { console.error(`Folder with name "${appName}" already exists! Please delete`); process.exit(); } const appNameAndroid = `${appName}-android`; const appNameIOS = `${appName}-ios`; let owner = null; const reactNativeVersion = args[1] || `react-native@${execCommand('npm view react-native version')}`.trim(); const reactNativeVersionIsLowerThanV049 = isReactNativeVersionLowerThan(49); const reactNativeCodePushVersion = args[2] || `react-native-code-push@${execCommand('npm view react-native-code-push version')}`.trim(); const reactNativeVersionIsLowerThanV073 = isReactNativeVersionLowerThan(73) if (!isReactNativeVersionLowerThan(60) && process.platform === "darwin") { try { console.log("Verify that CocoaPods installed"); execCommand("pod --version"); console.log("CocoaPods has installed"); } catch { console.error(`'CocoaPods' are required to run the script, you can install it with\n'sudo gem install cocoapods -n /usr/local/bin'\ncommand`); process.exit(); } } console.log(`App name: ${appName}`); console.log(`React Native version: ${reactNativeVersion}`); console.log(`React Native Module for CodePush version: ${reactNativeCodePushVersion} \n`); let androidStagingDeploymentKey = null; let iosStagingDeploymentKey = null; //GENERATE START createCodePushApp(appNameAndroid, 'Android'); createCodePushApp(appNameIOS, 'iOS'); generatePlainReactNativeApp(appName, reactNativeVersion); process.chdir(appName); installCodePush(reactNativeCodePushVersion); linkCodePush(androidStagingDeploymentKey, iosStagingDeploymentKey); //GENERATE END function createCodePushApp(name, os) { try { console.log(`Creating CodePush app "${name}" to release updates for ${os}...`); try { const appResult = execCommand(`appcenter apps create -d ${name} -n ${name} -o ${os} -p React-Native --output json`); const app = JSON.parse(appResult); owner = app.owner.name; console.log(`App "${name}" has been created \n`); } catch (e) { console.error(`Error: Unable to create CodePush app. Please check that you haven't application with "${name}" name on portal.`,); console.error("Error: ", e.toString()); } execCommand(`appcenter codepush deployment add -a ${owner}/${name} Staging`); } catch (e) { console.error("Error", e.toString()); } try { const deploymentKeysResult = execCommand(`appcenter codepush deployment list -a ${owner}/${name} -k --output json`); const deploymentKeys = JSON.parse(deploymentKeysResult); const stagingDeploymentKey = deploymentKeys[0][1]; console.log(`Deployment key for ${os}: ${stagingDeploymentKey}`); console.log(`Use "appcenter codepush release-react ${owner}/${name}" command to release updates for ${os} \n`); switch (os) { case 'Android': androidStagingDeploymentKey = stagingDeploymentKey; break; case 'iOS': iosStagingDeploymentKey = stagingDeploymentKey; break; } } catch (e) { console.error("Error: Unable to load deployment keys"); console.error("Error: ", e.toString()); } } function generatePlainReactNativeApp(appName, reactNativeVersion) { console.log(`Installing React Native...`); execCommand(`react-native init ${appName} --version ${reactNativeVersion.split('@')[1]}`); console.log(`React Native has been installed \n`); } function installCodePush(reactNativeCodePushVersion) { console.log(`Installing React Native Module for CodePush...`); execCommand(`npm i ${reactNativeCodePushVersion}`); console.log(`React Native Module for CodePush has been installed \n`); } function linkCodePush(androidStagingDeploymentKey, iosStagingDeploymentKey) { console.log(`Linking React Native Module for CodePush...`); if (isReactNativeVersionLowerThan(60)) { nexpect.spawn(`react-native link react-native-code-push`) .wait("What is your CodePush deployment key for Android (hit to ignore)") .sendline(androidStagingDeploymentKey) .wait("What is your CodePush deployment key for iOS (hit to ignore)") .sendline(iosStagingDeploymentKey) .run(function (err) { if (!err) { console.log(`React Native Module for CodePush has been linked \n`); setupAssets(); } else { console.log(err); } }); } else { androidSetup(); if (process.platform === 'darwin') { iosSetup(); } else { console.log('Your OS is not "Mac OS" so the iOS application will not be configured') } setupAssets(); console.log(`React Native Module for CodePush has been linked \n`); } } function setupAssets() { let fileToEdit; if (reactNativeVersionIsLowerThanV049) { fs.unlinkSync('./index.ios.js'); fs.unlinkSync('./index.android.js'); fs.writeFileSync('demo.js', fs.readFileSync('../CodePushDemoApp-pre0.49/demo.js')); fs.writeFileSync('index.ios.js', fs.readFileSync('../CodePushDemoApp-pre0.49/index.ios.js')); fs.writeFileSync('index.android.js', fs.readFileSync('../CodePushDemoApp-pre0.49/index.android.js')); fileToEdit = 'demo.js' } else { fs.writeFileSync('index.js', fs.readFileSync(__dirname + '/CodePushDemoApp/index.js')); fs.writeFileSync('App.js', fs.readFileSync(__dirname + '/CodePushDemoApp/App.js')); fileToEdit = 'index.js' } copyRecursiveSync(__dirname + '/CodePushDemoApp/images', './images'); fs.readFile(fileToEdit, 'utf8', function (err, data) { if (err) { return console.error(err); } const result = data.replace(/CodePushDemoApp/g, appName); fs.writeFile(fileToEdit, result, 'utf8', function (err) { if (err) return console.error(err); if (!/^win/.test(process.platform)) { optimizeToTestInDebugMode(); process.chdir('../'); grantAccess(appName); } console.log(`\nReact Native app "${appName}" has been generated and CodePushified!`); process.exit(); }); }); } function optimizeToTestInDebugMode() { const rnXcodeShLocationFolder = 'scripts'; try { const rnVersions = JSON.parse(execCommand(`npm view react-native versions --json`)); const currentRNversion = JSON.parse(fs.readFileSync('./package.json'))['dependencies']['react-native']; if (rnVersions.indexOf(currentRNversion) > -1 && rnVersions.indexOf(currentRNversion) < rnVersions.indexOf("0.46.0-rc.0")) { rnXcodeShLocationFolder = 'packager'; } } catch (e) { } const rnXcodeShPath = `node_modules/react-native/${rnXcodeShLocationFolder}/react-native-xcode.sh`; // Replace "if [[ "$PLATFORM_NAME" == *simulator ]]; then" with "if false; then" to force bundling execCommand(`sed -ie 's/if \\[\\[ "\$PLATFORM_NAME" == \\*simulator \\]\\]; then/if false; then/' ${rnXcodeShPath}`); execCommand(`perl -i -p0e 's/#ifdef DEBUG.*?#endif/jsCodeLocation = [CodePush bundleURL];/s' ios/${appName}/${getAppDelegateName()}`); reactNativeVersionIsLowerThanV073 && execCommand(`sed -ie 's/targetName.toLowerCase().contains("release")/true/' node_modules/react-native/react.gradle`); } function grantAccess(folderPath) { execCommand('chown -R `whoami` ' + folderPath); } function copyRecursiveSync(src, dest) { const exists = fs.existsSync(src); const stats = exists && fs.statSync(src); const isDirectory = exists && stats.isDirectory(); if (exists && isDirectory) { fs.mkdirSync(dest); fs.readdirSync(src).forEach(function (childItemName) { copyRecursiveSync(path.join(src, childItemName), path.join(dest, childItemName)); }); } else { fs.linkSync(src, dest); } } function isReactNativeVersionLowerThan(version) { if (!reactNativeVersion || reactNativeVersion == "react-native@latest" || reactNativeVersion == "react-native@next") return false; const reactNativeVersionNumberString = reactNativeVersion.split("@")[1]; return reactNativeVersionNumberString.split('.')[1] < version; } // Configuring android applications for react-native version higher than 0.60 function androidSetup() { const buildGradlePath = path.join('android', 'app', 'build.gradle'); const settingsGradlePath = path.join('android', 'settings.gradle'); const mainApplicationType = reactNativeVersionIsLowerThanV073 ? 'java' : 'kt'; const mainApplicationPath = path.join('android', 'app', 'src', 'main', 'java', 'com', appName, `MainApplication.${mainApplicationType}`); const stringsResourcesPath = path.join('android', 'app', 'src', 'main', 'res', 'values', 'strings.xml'); let stringsResourcesContent = fs.readFileSync(stringsResourcesPath, "utf8"); const insertAfterString = ""; const deploymentKeyString = `\t${androidStagingDeploymentKey || "deployment-key-here"}`; stringsResourcesContent = stringsResourcesContent.replace(insertAfterString, `${insertAfterString}\n${deploymentKeyString}`); fs.writeFileSync(stringsResourcesPath, stringsResourcesContent); let buildGradleContents = fs.readFileSync(buildGradlePath, "utf8"); const reactGradleLink = buildGradleContents.match(/\napply from: ["'].*?react\.gradle["']/); const codePushGradleLink = `\napply from: "../../node_modules/react-native-code-push/android/codepush.gradle"`; if (reactGradleLink != null) { buildGradleContents = buildGradleContents.replace(reactGradleLink[0], `${reactGradleLink[0]}${codePushGradleLink}`); fs.writeFileSync(buildGradlePath, buildGradleContents); } // react.gradle script removed from 0.71 thus this workaround else { const appPluginLastLine = buildGradleContents.match(/apply plugin: "com.facebook.react"/)[0]; buildGradleContents = buildGradleContents.replace(appPluginLastLine, `${appPluginLastLine}${codePushGradleLink}`) fs.writeFileSync(buildGradlePath, buildGradleContents); } let settingsGradleContents = fs.readFileSync(settingsGradlePath, "utf8"); const settingsGradleInclude = "include \':app\'"; const codePushProjectImport = `':react-native-code-push'\nproject(':react-native-code-push').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-code-push/android/app')`; settingsGradleContents = settingsGradleContents.replace(settingsGradleInclude, `${settingsGradleInclude}, ${codePushProjectImport}`); fs.writeFileSync(settingsGradlePath, settingsGradleContents); let importCodePush = `\nimport com.microsoft.codepush.react.CodePush;`; let reactNativeHostInstantiationImport = "import android.app.Application;"; let mainApplicationContents = fs.readFileSync(mainApplicationPath, "utf8"); let getJSBundleFileOverride = ""; let reactNativeHostInstantiation = ""; // handle react-native version with java if (reactNativeVersionIsLowerThanV073) { reactNativeHostInstantiation = "new ReactNativeHost(this) {"; getJSBundleFileOverride = ` @Override protected String getJSBundleFile(){ return CodePush.getJSBundleFile(); } `; } // handle react-native version with kotlin else { reactNativeHostInstantiation = "object : DefaultReactNativeHost(this) {" getJSBundleFileOverride = ` override fun getJSBundleFile(): String { return CodePush.getJSBundleFile() } `; importCodePush = importCodePush.replace(';', ''); reactNativeHostInstantiationImport = reactNativeHostInstantiationImport.replace(';', ''); } mainApplicationContents = mainApplicationContents.replace(reactNativeHostInstantiation, `${reactNativeHostInstantiation}${getJSBundleFileOverride}`); mainApplicationContents = mainApplicationContents.replace(reactNativeHostInstantiationImport, `${reactNativeHostInstantiationImport}${importCodePush}`); fs.writeFileSync(mainApplicationPath, mainApplicationContents); } function getAppDelegateName() { return fs.readdirSync(path.join('ios', appName)).find(file => file === ('AppDelegate.mm') || file === 'AppDelegate.m') }; // Configuring ios applications for react-native version higher than 0.60 function iosSetup() { const plistPath = path.join('ios', appName, 'Info.plist'); const appDelegatePath = path.join('ios', appName, getAppDelegateName()); let plistContents = fs.readFileSync(plistPath, "utf8"); const dictPlistTag = `\n`; const codePushDeploymentKey = iosStagingDeploymentKey || 'deployment-key-here'; plistContents = plistContents.replace(dictPlistTag, `\tCodePushDeploymentKey\n\t${codePushDeploymentKey}${dictPlistTag}`); fs.writeFileSync(plistPath, plistContents); let appDelegateContents = fs.readFileSync(appDelegatePath, "utf8"); const appDelegateHeaderImportStatement = `#import "AppDelegate.h"`; const codePushHeaderImportStatementFormatted = `\n#import `; appDelegateContents = appDelegateContents.replace(appDelegateHeaderImportStatement, `${appDelegateHeaderImportStatement}${codePushHeaderImportStatementFormatted}`); const oldBundleUrl = "[[NSBundle mainBundle] URLForResource:@\"main\" withExtension:@\"jsbundle\"]"; const codePushBundleUrl = "[CodePush bundleURL]"; appDelegateContents = appDelegateContents.replace(oldBundleUrl, codePushBundleUrl); fs.writeFileSync(appDelegatePath, appDelegateContents); execCommand(`cd ios && pod install && cd ..`); } function execCommand(command) { console.log(`\n\x1b[2m${command}\x1b[0m\n`); const result = execSync(command).toString(); return result; } ================================================ FILE: Examples/nexpect.js ================================================ /* * nexpect.js: Top-level include for the `nexpect` module. * * (C) 2011, Elijah Insua, Marak Squires, Charlie Robbins. * */ var spawn = require('child_process').spawn; var util = require('util'); var AssertionError = require('assert').AssertionError; function chain (context) { return { expect: function (expectation) { var _expect = function _expect (data) { return testExpectation(data, expectation); }; _expect.shift = true; _expect.expectation = expectation; _expect.description = '[expect] ' + expectation; _expect.requiresInput = true; context.queue.push(_expect); return chain(context); }, wait: function (expectation, callback) { var _wait = function _wait (data) { var val = testExpectation(data, expectation); if (val === true && typeof callback === 'function') { callback(data); } return val; }; _wait.shift = false; _wait.expectation = expectation; _wait.description = '[wait] ' + expectation; _wait.requiresInput = true; context.queue.push(_wait); return chain(context); }, sendline: function (line) { var _sendline = function _sendline () { context.process.stdin.write(line + '\n'); if (context.verbose) { process.stdout.write(line + '\n'); } }; _sendline.shift = true; _sendline.description = '[sendline] ' + line; _sendline.requiresInput = false; context.queue.push(_sendline); return chain(context); }, sendEof: function() { var _sendEof = function _sendEof () { context.process.stdin.destroy(); }; _sendEof.shift = true; _sendEof.description = '[sendEof]'; _sendEof.requiresInput = false; context.queue.push(_sendEof); return chain(context); }, run: function (callback) { var errState = null, responded = false, stdout = [], options; // // **onError** // // Helper function to respond to the callback with a // specified error. Kills the child process if necessary. // function onError (err, kill) { if (errState || responded) { return; } errState = err; responded = true; if (kill) { try { context.process.kill(); } catch (ex) { } } callback(err); } // // **validateFnType** // // Helper function to validate the `currentFn` in the // `context.queue` for the target chain. // function validateFnType (currentFn) { if (typeof currentFn !== 'function') { // // If the `currentFn` is not a function, short-circuit with an error. // onError(new Error('Cannot process non-function on nexpect stack.'), true); return false; } else if (['_expect', '_sendline', '_wait', '_sendEof'].indexOf(currentFn.name) === -1) { // // If the `currentFn` is a function, but not those set by `.sendline()` or // `.expect()` then short-circuit with an error. // onError(new Error('Unexpected context function name: ' + currentFn.name), true); return false; } return true; } // // **evalContext** // // Core evaluation logic that evaluates the next function in // `context.queue` against the specified `data` where the last // function run had `name`. // function evalContext (data, name) { var currentFn = context.queue[0]; if (!currentFn || (name === '_expect' && currentFn.name === '_expect')) { // // If there is nothing left on the context or we are trying to // evaluate two consecutive `_expect` functions, return. // return; } if (currentFn.shift) { context.queue.shift(); } if (!validateFnType(currentFn)) { return; } if (currentFn.name === '_expect') { // // If this is an `_expect` function, then evaluate it and attempt // to evaluate the next function (in case it is a `_sendline` function). // return currentFn(data) === true ? evalContext(data, '_expect') : onError(createExpectationError(currentFn.expectation, data), true); } else if (currentFn.name === '_wait') { // // If this is a `_wait` function, then evaluate it and if it returns true, // then evaluate the function (in case it is a `_sendline` function). // if (currentFn(data) === true) { context.queue.shift(); evalContext(data, '_expect'); } } else { // // If the `currentFn` is any other function then evaluate it // currentFn(); // Evaluate the next function if it does not need input var nextFn = context.queue[0]; if (nextFn && !nextFn.requiresInput) evalContext(data); } } // // **onLine** // // Preprocesses the `data` from `context.process` on the // specified `context.stream` and then evaluates the processed lines: // // 1. Stripping ANSI colors (if necessary) // 2. Removing case sensitivity (if necessary) // 3. Splitting `data` into multiple lines. // function onLine (data) { data = data.toString(); if (context.stripColors) { data = data.replace(/\u001b\[\d{0,2}m/g, ''); } if (context.ignoreCase) { data = data.toLowerCase(); } var lines = data.split('\n').filter(function (line) { return line.length > 0; }); stdout = stdout.concat(lines); while (lines.length > 0) { evalContext(lines.shift(), null); } } // // **flushQueue** // // Helper function which flushes any remaining functions from // `context.queue` and responds to the `callback` accordingly. // function flushQueue () { var remainingQueue = context.queue.slice(), currentFn = context.queue.shift(), lastLine = stdout[stdout.length - 1]; if (!lastLine) { onError(createUnexpectedEndError( 'No data from child with non-empty queue.', remainingQueue)); return false; } else if (context.queue.length > 0) { onError(createUnexpectedEndError( 'Non-empty queue on spawn exit.', remainingQueue)); return false; } else if (!validateFnType(currentFn)) { // onError was called return false; } else if (currentFn.name === '_sendline') { onError(new Error('Cannot call sendline after the process has exited')); return false; } else if (currentFn.name === '_wait' || currentFn.name === '_expect') { if (currentFn(lastLine) !== true) { onError(createExpectationError(currentFn.expectation, lastLine)); return false; } } return true; } // // **onData** // // Helper function for writing any data from a stream // to `process.stdout`. // function onData (data) { process.stdout.write(data); } options = { cwd: context.cwd, env: context.env }; // // Spawn the child process and begin processing the target // stream for this chain. // if (!/^win/.test(process.platform)) { context.process = spawn(context.command, context.params, options); } else { context.process = spawn('cmd', ['/c', `${context.command}`].concat(context.params), options); } if (context.verbose) { context.process.stdout.on('data', onData); context.process.stderr.on('data', onData); } if (context.stream === 'all') { context.process.stdout.on('data', onLine); context.process.stderr.on('data', onLine); } else { context.process[context.stream].on('data', onLine); } context.process.on('error', onError); // // When the process exits, check the output `code` and `signal`, // flush `context.queue` (if necessary) and respond to the callback // appropriately. // context.process.on('close', function (code, signal) { if (code === 127) { // XXX(sam) Not how node works (anymore?), 127 is what /bin/sh returns, // but it appears node does not, or not in all conditions, blithely // return 127 to user, it emits an 'error' from the child_process. // // If the response code is `127` then `context.command` was not found. // return onError(new Error('Command not found: ' + context.command)); } else if (context.queue.length && !flushQueue()) { // if flushQueue returned false, onError was called return; } callback(null, stdout, signal || code); }); return context.process; } }; } function testExpectation(data, expectation) { if (util.isRegExp(expectation)) { return expectation.test(data); } else { return data.indexOf(expectation) > -1; } } function createUnexpectedEndError(message, remainingQueue) { var desc = remainingQueue.map(function(it) { return it.description; }); var msg = message + '\n' + desc.join('\n'); return new AssertionError({ message: msg, expected: [], actual: desc }); } function createExpectationError(expected, actual) { var expectation; if (util.isRegExp(expected)) expectation = 'to match ' + expected; else expectation = 'to contain ' + JSON.stringify(expected); var err = new AssertionError({ message: util.format('expected %j %s', actual, expectation), actual: actual, expected: expected }); return err; } function nspawn (command, params, options) { if (arguments.length === 2) { if (Array.isArray(arguments[1])) { options = {}; } else { options = arguments[1]; params = null; } } if (Array.isArray(command)) { params = command; command = params.shift(); } else if (typeof command === 'string') { command = command.split(' '); params = params || command.slice(1); command = command[0]; } options = options || {}; context = { command: command, cwd: options.cwd || undefined, env: options.env || undefined, ignoreCase: options.ignoreCase, params: params, queue: [], stream: options.stream || 'stdout', stripColors: options.stripColors, verbose: options.verbose }; return chain(context); } // // Export the core `nspawn` function as well as `nexpect.nspawn` for // backwards compatibility. // module.exports.spawn = nspawn; module.exports.nspawn = { spawn: nspawn }; ================================================ FILE: LICENSE.md ================================================ Microsoft CodePush Plugin for React Native Copyright (c) Microsoft Corporation All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ # Archiving this repository Visual Studio App Center was retired on March 31, 2025, except for its Analytics and Diagnostics features. You can learn more about the retirement and the Analytics and Diagnostics extension [here](https://aka.ms/appcenter/retire). CodePush, along with other App Center features, was also retired on March 31, 2025. Consequently, we are archiving this repository. --- [![appcenterbanner](https://user-images.githubusercontent.com/31293287/32969262-3cc5d48a-cb99-11e7-91bf-fa57c67a371c.png)](http://microsoft.github.io/code-push/) #### [Sign up With App Center](https://appcenter.ms/signup?utm_source=CodePush&utm_medium=Azure) to use CodePush ## React Native Module for CodePush > [!WARNING] > React Native CodePush won't support new Architecture. In order to use this plugin on React Native versions starting from 0.76 you will need to [opt out](https://reactnative.dev/blog/2024/10/23/the-new-architecture-is-here#opt-out) from new architecture. > *Note: This README is only relevant to the latest version of our plugin. If you are using an older version, please switch to the relevant tag on [our GitHub repo](https://github.com/microsoft/react-native-code-push) to view the docs for that particular version.* ![Switching tags](https://user-images.githubusercontent.com/42337914/57237511-0835de80-7030-11e9-88fa-64eb200478d0.png) This plugin provides client-side integration for the [CodePush service](https://microsoft.github.io/code-push/), allowing you to easily add a dynamic update experience to your React Native app(s). * [How does it work?](#how-does-it-work) * [Supported React Native Platforms](#supported-react-native-platforms) * [Supported Components](#supported-components) * [Getting Started](#getting-started) * [iOS Setup](docs/setup-ios.md) * [Android Setup](docs/setup-android.md) * [Windows Setup](docs/setup-windows.md) * [Plugin Usage](#plugin-usage) * [Store Guideline Compliance](#store-guideline-compliance) * [Releasing Updates](#releasing-updates) * [Multi-Deployment Testing](#multi-deployment-testing) * [Android](docs/multi-deployment-testing-android.md) * [iOS](docs/multi-deployment-testing-ios.md) * [Dynamic Deployment Assignment](#dynamic-deployment-assignment) * [API Reference](#api-reference) * [JavaScript API](docs/api-js.md) * [Objective-C API Reference (iOS)](docs/api-ios.md) * [Java API Reference (Android)](docs/api-android.md) * [Debugging / Troubleshooting](#debugging--troubleshooting) * [Example Apps / Starters](#example-apps--starters) * [Continuous Integration / Delivery](#continuous-integration--delivery) * [TypeScript Consumption](#typescript-consumption) ## How does it work? A React Native app is composed of JavaScript files and any accompanying [images](https://reactnative.dev/docs/image), which are bundled together by the [metro bundler](https://github.com/facebook/metro) and distributed as part of a platform-specific binary (i.e. an `.ipa` or `.apk` file). Once the app is released, updating either the JavaScript code (e.g. making bug fixes, adding new features) or image assets, requires you to recompile and redistribute the entire binary, which of course, includes any review time associated with the store(s) you are publishing to. The CodePush plugin helps get product improvements in front of your end users instantly, by keeping your JavaScript and images synchronized with updates you release to the CodePush server. This way, your app gets the benefits of an offline mobile experience, as well as the "web-like" agility of side-loading updates as soon as they are available. It's a win-win! In order to ensure that your end users always have a functioning version of your app, the CodePush plugin maintains a copy of the previous update, so that in the event that you accidentally push an update which includes a crash, it can automatically roll back. This way, you can rest assured that your newfound release agility won't result in users becoming blocked before you have a chance to [roll back](https://docs.microsoft.com/en-us/appcenter/distribution/codepush/cli#rolling-back-updates) on the server. It's a win-win-win! *Note: Any product changes which touch native code (e.g. modifying your `AppDelegate.m`/`MainActivity.java` file, adding a new plugin) cannot be distributed via CodePush, and therefore, must be updated via the appropriate store(s).* ## Supported React Native platforms - iOS (7+) - Android (4.1+) on TLS 1.2 compatible devices - Windows (UWP) We try our best to maintain backwards compatibility of our plugin with previous versions of React Native, but due to the nature of the platform, and the existence of breaking changes between releases, it is possible that you need to use a specific version of the CodePush plugin in order to support the exact version of React Native you are using. The following table outlines which CodePush plugin versions officially support the respective React Native versions: | React Native version(s) | Supporting CodePush version(s) | |-------------------------|-------------------------------------------------------| | <0.14 | **Unsupported** | | v0.14 | v1.3 *(introduced Android support)* | | v0.15-v0.18 | v1.4-v1.6 *(introduced iOS asset support)* | | v0.19-v0.28 | v1.7-v1.17 *(introduced Android asset support)* | | v0.29-v0.30 | v1.13-v1.17 *(RN refactored native hosting code)* | | v0.31-v0.33 | v1.14.6-v1.17 *(RN refactored native hosting code)* | | v0.34-v0.35 | v1.15-v1.17 *(RN refactored native hosting code)* | | v0.36-v0.39 | v1.16-v1.17 *(RN refactored resume handler)* | | v0.40-v0.42 | v1.17 *(RN refactored iOS header files)* | | v0.43-v0.44 | v2.0+ *(RN refactored uimanager dependencies)* | | v0.45 | v3.0+ *(RN refactored instance manager code)* | | v0.46 | v4.0+ *(RN refactored js bundle loader code)* | | v0.46-v0.53 | v5.1+ *(RN removed unused registration of JS modules)*| | v0.54-v0.55 | v5.3+ *(Android Gradle Plugin 3.x integration)* | | v0.56-v0.58 | v5.4+ *(RN upgraded versions for Android tools)* | | v0.59 | v5.6+ *(RN refactored js bundle loader code)* | | v0.60-v0.61 | v6.0+ *(RN migrated to Autolinking)* | | v0.62-v0.64 | v6.2+ *(RN removed LiveReload)* | | v0.65-v0.70 | v7.0+ *(RN updated iPhone-target-version)* | | v0.71 | v8.0+ *(RN moved to react-native-gradle-plugin)* | *NOTE: `react-native-code-push` versions lower than **[v5.7.0](https://github.com/microsoft/react-native-code-push/releases/tag/v5.7.0)** will stop working in the near future. You can find more information in our [documentation](https://github.com/microsoft/code-push/blob/master/migration-notice.md).* We work hard to respond to new RN releases, but they do occasionally break us. We will update this chart with each RN release, so that users can check to see what our "official" support is. ### Supported Components When using the React Native assets system (i.e. using the `require("./foo.png")` syntax), the following list represents the set of core components (and props) that support having their referenced images and videos updated via CodePush: | Component | Prop(s) | |-------------------------------------------------|------------------------------------------| | `Image` | `source` | | `MapView.Marker`
*(Requires [react-native-maps](https://github.com/lelandrichardson/react-native-maps) `>=O.3.2`)* | `image` | | `ProgressViewIOS` | `progressImage`, `trackImage` | | `TabBarIOS.Item` | `icon`, `selectedIcon` | | `ToolbarAndroid`
*(React Native 0.21.0+)* | `actions[].icon`, `logo`, `overflowIcon` | | `Video` | `source` | The following list represents the set of components (and props) that don't currently support their assets being updated via CodePush, due to their dependency on static images and videos (i.e. using the `{ uri: "foo" }` syntax): | Component | Prop(s) | |-------------|----------------------------------------------------------------------| | `SliderIOS` | `maximumTrackImage`, `minimumTrackImage`, `thumbImage`, `trackImage` | | `Video` | `source` | As new core components are released, which support referencing assets, we'll update this list to ensure users know what exactly they can expect to update using CodePush. *Note: CodePush only works with Video components when using `require` in the source prop. For example:* ```javascript