├── .github ├── ISSUE_TEMPLATE.md ├── actions │ └── setup │ │ └── action.yml └── workflows │ ├── onRelease.yml │ └── tests.yml ├── .gitignore ├── .node-version ├── .npmignore ├── .prettierrc.json ├── .watchmanconfig ├── .yarnrc.yml ├── CONTRIBUTING.md ├── 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 │ │ │ │ ├── mipmap-hdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ │ ├── mipmap-mdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ │ ├── mipmap-xhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ │ └── values │ │ │ │ ├── strings.xml │ │ │ │ └── styles.xml │ │ ├── build.gradle │ │ ├── gradle.properties │ │ ├── gradle │ │ │ └── wrapper │ │ │ │ ├── gradle-wrapper.jar │ │ │ │ └── gradle-wrapper.properties │ │ ├── gradlew │ │ ├── gradlew.bat │ │ └── settings.gradle │ ├── app.json │ ├── babel.config.js │ ├── images │ │ └── laptop_phone_howitworks.png │ ├── index.js │ ├── ios │ │ ├── CodePushDemoApp.xcodeproj │ │ │ ├── project.pbxproj │ │ │ └── xcshareddata │ │ │ │ └── xcschemes │ │ │ │ └── CodePushDemoApp.xcscheme │ │ ├── CodePushDemoApp.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ └── IDEWorkspaceChecks.plist │ │ ├── CodePushDemoApp │ │ │ ├── AppDelegate.h │ │ │ ├── AppDelegate.m │ │ │ ├── Images.xcassets │ │ │ │ ├── AppIcon.appiconset │ │ │ │ │ └── Contents.json │ │ │ │ └── Contents.json │ │ │ ├── Info.plist │ │ │ ├── LaunchScreen.storyboard │ │ │ └── main.m │ │ ├── CodePushDemoAppTests │ │ │ ├── CodePushDemoAppTests.m │ │ │ └── Info.plist │ │ ├── Podfile │ │ └── Podfile.lock │ ├── metro.config.js │ ├── package-lock.json │ └── package.json ├── CodePushDemoAppCpp │ ├── .buckconfig │ ├── .eslintrc.js │ ├── .flowconfig │ ├── .gitattributes │ ├── .gitignore │ ├── .prettierrc.js │ ├── .watchmanconfig │ ├── App.js │ ├── app.json │ ├── babel.config.js │ ├── images │ │ └── laptop_phone_howitworks.png │ ├── index.js │ ├── metro.config.js │ ├── package-lock.json │ ├── package.json │ └── windows │ │ ├── .gitignore │ │ ├── CodePushDemoAppCpp.sln │ │ └── CodePushDemoAppCpp │ │ ├── .gitignore │ │ ├── App.cpp │ │ ├── App.h │ │ ├── App.idl │ │ ├── App.xaml │ │ ├── Assets │ │ ├── LockScreenLogo.scale-200.png │ │ ├── SplashScreen.scale-200.png │ │ ├── Square150x150Logo.scale-200.png │ │ ├── Square44x44Logo.scale-200.png │ │ ├── Square44x44Logo.targetsize-24_altform-unplated.png │ │ ├── StoreLogo.png │ │ └── Wide310x150Logo.scale-200.png │ │ ├── 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 ├── create-app.js └── nexpect.js ├── LICENSE.md ├── README.md ├── android ├── app │ ├── build.gradle │ ├── proguard-rules.pro │ └── src │ │ ├── debug │ │ └── AndroidManifest.xml │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── AndroidManifestNew.xml │ │ └── java │ │ └── com │ │ └── appzung │ │ └── codepush │ │ └── react │ │ ├── CodePush.java │ │ ├── CodePushConstants.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 │ │ ├── ReactHostHolder.java │ │ ├── ReactInstanceHolder.java │ │ ├── SettingsManager.java │ │ └── TLSSocketFactory.java ├── build.gradle ├── codepush.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle ├── babel.config.js ├── 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 ├── advanced-usage.md ├── api-android.md ├── api-ios.md ├── api-js │ ├── README.md │ ├── enumerations │ │ ├── CheckFrequency.md │ │ ├── DeploymentStatus.md │ │ ├── InstallMode.md │ │ ├── LogLevel.md │ │ ├── SyncStatus.md │ │ └── UpdateState.md │ ├── functions │ │ ├── allowRestart.md │ │ ├── checkForUpdate.md │ │ ├── clearUpdates.md │ │ ├── disallowRestart.md │ │ ├── getClientUniqueId.md │ │ ├── getDataTransmissionEnabled.md │ │ ├── getLogLevel.md │ │ ├── getTelemetryEnabled.md │ │ ├── getUpdateMetadata.md │ │ ├── notifyAppReady.md │ │ ├── resetClientUniqueId.md │ │ ├── resetLogger.md │ │ ├── restartApp.md │ │ ├── setDataTransmissionEnabled.md │ │ ├── setLogLevel.md │ │ ├── setLogger.md │ │ ├── setTelemetryEnabled.md │ │ ├── sync.md │ │ └── withCodePush.md │ ├── interfaces │ │ ├── CodePushOptions.md │ │ ├── DownloadProgress.md │ │ ├── LocalPackage.md │ │ ├── Package.md │ │ ├── RemotePackage.md │ │ ├── RollbackRetryOptions.md │ │ ├── StatusReport.md │ │ ├── SyncOptions.md │ │ └── UpdateDialog.md │ ├── type-aliases │ │ ├── DownloadProgressCallback.md │ │ ├── HandleBinaryVersionMismatchCallback.md │ │ ├── LoggerFunction.md │ │ └── SyncStatusChangedCallback.md │ └── variables │ │ └── DEFAULT_UPDATE_DIALOG.md ├── code-signing.md ├── migrating-to-v10.md ├── privacy.md ├── setup-android.md ├── setup-ios.md └── setup-windows.md ├── eslint.config.mjs ├── ios ├── CodePush.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── CodePush │ ├── CodePush.h │ ├── CodePush.mm │ ├── CodePushConfig.m │ ├── CodePushDownloadHandler.m │ ├── CodePushErrorUtils.m │ ├── CodePushPackage.m │ ├── CodePushTelemetryManager.m │ ├── CodePushUpdateUtils.m │ ├── CodePushUtils.m │ ├── RCTConvert+CodePushInstallMode.m │ └── RCTConvert+CodePushUpdateState.m └── PrivacyInfo.xcprivacy ├── package.json ├── react-native.config.js ├── scripts ├── generateBundledResourcesHash.js ├── getFilesInFolder.js └── recordFilesBeforeBundleCommand.js ├── src ├── CodePush.tsx ├── allowRestart.ts ├── checkForUpdates.ts ├── clearUpdates.ts ├── dataTransmission.ts ├── disallowRestart.ts ├── enums │ ├── CheckFrequency.enum.ts │ ├── InstallMode.enum.ts │ ├── LogLevel.enum.ts │ ├── SyncStatus.enum.ts │ └── UpdateState.enum.ts ├── getClientUniqueId.ts ├── getUpdateMetadata.ts ├── index.ts ├── internals │ ├── CodePushApiSdk.errors.ts │ ├── CodePushApiSdk.ts │ ├── CodePushApiSdk.types.ts │ ├── CodePushEventEmitter.ts │ ├── LocalPackageImplementation.ts │ ├── NativeRNAppZungCodePushModule.ts │ ├── RNAppZungCodePushModuleSpec.ts │ ├── RemotePackageImplementation.ts │ ├── getConfiguration.ts │ ├── getCurrentPackage.ts │ ├── logger.ts │ ├── shouldUpdateBeIgnored.ts │ ├── types.ts │ └── utils │ │ ├── fetchRetry.ts │ │ ├── log.ts │ │ ├── queryStringify.ts │ │ └── requestFetchAdapter.ts ├── logLevel.ts ├── logger.ts ├── notifyAppReady.ts ├── reactNative.d.ts ├── resetClientUniqueId.ts ├── restartApp.ts ├── sync.ts ├── telemetry.ts └── types.ts ├── 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.build.json ├── tsconfig.json ├── typedoc.json ├── 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 └── yarn.lock /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Thanks so much for filing an issue or feature request! Please fill out the following (wherever relevant): 2 | 3 | ### Steps to Reproduce 4 | 1. 5 | 2. 6 | 3. 7 | 8 | ### Expected Behavior 9 | What you expected to happen? 10 | 11 | ### Actual Behavior 12 | What actually happens? 13 | ``` 14 | STACK TRACE AND/OR SCREENSHOTS 15 | ``` 16 | 17 | ### Reproducible Demo 18 | 19 | * Download https://github.com/appzung/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 20 | * If you can't reproduce the bug on it, provide us as much info as possible about your project 21 | 22 | ### Environment 23 | 24 | * react-native-code-push version: 25 | * react-native version: 26 | * iOS/Android/Windows version: 27 | * Does this reproduce on a debug build or release build? 28 | * Does this reproduce on a simulator, or only on a physical device? 29 | 30 | (The more info the faster we will be able to address it!) 31 | -------------------------------------------------------------------------------- /.github/actions/setup/action.yml: -------------------------------------------------------------------------------- 1 | name: Setup 2 | description: Setup Node.js and install dependencies 3 | 4 | runs: 5 | using: composite 6 | steps: 7 | - name: Setup Node.js 8 | uses: actions/setup-node@v4 9 | with: 10 | node-version-file: .node-version 11 | 12 | - run: corepack enable 13 | shell: bash 14 | 15 | - name: Restore dependencies 16 | id: yarn-cache 17 | uses: actions/cache/restore@v4 18 | with: 19 | path: | 20 | **/node_modules 21 | .yarn/install-state.gz 22 | key: ${{ runner.os }}-yarn-${{ hashFiles('yarn.lock') }}-${{ hashFiles('**/package.json', '!node_modules/**') }} 23 | restore-keys: | 24 | ${{ runner.os }}-yarn-${{ hashFiles('yarn.lock') }} 25 | ${{ runner.os }}-yarn- 26 | 27 | - name: Install dependencies 28 | if: steps.yarn-cache.outputs.cache-hit != 'true' 29 | run: yarn install --immutable 30 | shell: bash 31 | 32 | - name: Run yarn genversion 33 | run: yarn genversion 34 | shell: bash 35 | 36 | - name: Cache dependencies 37 | if: steps.yarn-cache.outputs.cache-hit != 'true' 38 | uses: actions/cache/save@v4 39 | with: 40 | path: | 41 | **/node_modules 42 | .yarn/install-state.gz 43 | key: ${{ steps.yarn-cache.outputs.cache-primary-key }} 44 | -------------------------------------------------------------------------------- /.github/workflows/onRelease.yml: -------------------------------------------------------------------------------- 1 | name: publish 2 | 3 | on: 4 | release: 5 | types: [published] 6 | 7 | jobs: 8 | publish: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Checkout 12 | uses: actions/checkout@v4 13 | 14 | - name: Setup 15 | uses: ./.github/actions/setup 16 | 17 | - name: Set npm tag 18 | id: set-npm-tag 19 | run: | 20 | RELEASE_TAG=${{ github.event.release.tag_name }} 21 | if [[ $RELEASE_TAG == *"rc"* || $RELEASE_TAG == *"alpha"* || $RELEASE_TAG == *"beta"* ]]; then 22 | echo "NPM_TAG=next" >> $GITHUB_OUTPUT 23 | else 24 | echo "NPM_TAG=latest" >> $GITHUB_OUTPUT 25 | fi 26 | 27 | - uses: JS-DevTools/npm-publish@19c28f1ef146469e409470805ea4279d47c3d35c 28 | with: 29 | token: "${{ secrets.NPM_TOKEN }}" 30 | tag: ${{ steps.set-npm-tag.outputs.NPM_TAG }} 31 | -------------------------------------------------------------------------------- /.github/workflows/tests.yml: -------------------------------------------------------------------------------- 1 | name: Tests 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | branches: 7 | - main 8 | - 'v[0-9]+' 9 | - 'v[0-9]+.[0-9]+' 10 | pull_request: 11 | branches: 12 | - main 13 | - 'v[0-9]+' 14 | - 'v[0-9]+.[0-9]+' 15 | merge_group: 16 | types: 17 | - checks_requested 18 | 19 | jobs: 20 | lint: 21 | runs-on: ubuntu-latest 22 | steps: 23 | - name: Checkout 24 | uses: actions/checkout@v4 25 | 26 | - name: Setup 27 | uses: ./.github/actions/setup 28 | 29 | - run: yarn test:lint 30 | 31 | types: 32 | runs-on: ubuntu-latest 33 | steps: 34 | - name: Checkout 35 | uses: actions/checkout@v4 36 | 37 | - name: Setup 38 | uses: ./.github/actions/setup 39 | 40 | - run: yarn test:types 41 | 42 | build-library: 43 | runs-on: ubuntu-latest 44 | steps: 45 | - name: Checkout 46 | uses: actions/checkout@v4 47 | 48 | - name: Setup 49 | uses: ./.github/actions/setup 50 | 51 | - name: Build package 52 | run: yarn prepare 53 | -------------------------------------------------------------------------------- /.node-version: -------------------------------------------------------------------------------- 1 | 22 2 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | .DS_Store 4 | 5 | # Xcode 6 | # 7 | build/ 8 | *.pbxuser 9 | !default.pbxuser 10 | *.mode1v3 11 | !default.mode1v3 12 | *.mode2v3 13 | !default.mode2v3 14 | *.perspectivev3 15 | !default.perspectivev3 16 | xcuserdata 17 | *.xccheckout 18 | *.moved-aside 19 | DerivedData 20 | *.hmap 21 | *.ipa 22 | *.xcuserstate 23 | 24 | # node.js 25 | # 26 | node_modules/ 27 | npm-debug.log 28 | 29 | # Don't publish example apps 30 | Examples/ 31 | Recipes/ 32 | 33 | # Don't publish testing code 34 | bin/ 35 | test/ 36 | 37 | # Remove after this framework is published on NPM 38 | code-push-plugin-testing-framework/ 39 | 40 | # Android build artifacts and Android Studio bits 41 | android/app/build 42 | android/local.properties 43 | android/app/local.properties 44 | android/.gradle 45 | android/app/.gradle 46 | android/**/*.iml 47 | android/.idea 48 | 49 | 50 | # Windows 51 | windows/.vs/ 52 | windows/obj/ 53 | 54 | #Tests 55 | windows/CodePush.Net46.Test 56 | 57 | #Visual Studio files 58 | *.[Oo]bj 59 | *.user 60 | *.aps 61 | *.pch 62 | *.vspscc 63 | *.vssscc 64 | *_i.c 65 | *_p.c 66 | *.ncb 67 | *.suo 68 | *.tlb 69 | *.tlh 70 | *.bak 71 | *.[Cc]ache 72 | *.ilk 73 | *.log 74 | *.lib 75 | *.sbr 76 | *.sdf 77 | *.opensdf 78 | *.opendb 79 | *.unsuccessfulbuild 80 | ipch/ 81 | [Oo]bj/ 82 | [Bb]in 83 | [Dd]ebug*/ 84 | [Rr]elease*/ 85 | Ankh.NoLoad 86 | 87 | #NuGet 88 | packages/ 89 | *.nupkg 90 | 91 | # VSCode 92 | .vscode/ 93 | 94 | # IntelliJIDEA 95 | .idea/ 96 | 97 | 98 | # Github 99 | .github/ 100 | 101 | # Git 102 | .git/ 103 | 104 | .watchmanconfig 105 | 106 | .prettierrc.json 107 | .node-version 108 | 109 | docs 110 | 111 | .yarn 112 | .yarnrc.yml 113 | yarn.lock 114 | 115 | typedoc.json 116 | babel.config.js 117 | eslint.config.mjs 118 | 119 | CONTRIBUTING.md 120 | 121 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": ["@trivago/prettier-plugin-sort-imports"], 3 | "trailingComma": "all", 4 | "singleQuote": true, 5 | "printWidth": 120, 6 | "importOrderGroupNamespaceSpecifiers": true, 7 | "importOrderSortSpecifiers": true, 8 | "importOrder": ["", "^[./]"] 9 | } 10 | -------------------------------------------------------------------------------- /.watchmanconfig: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /.yarnrc.yml: -------------------------------------------------------------------------------- 1 | nodeLinker: node-modules 2 | nmHoistingLimits: workspaces 3 | -------------------------------------------------------------------------------- /CodePush.podspec: -------------------------------------------------------------------------------- 1 | require 'json' 2 | 3 | package = JSON.parse(File.read(File.join(__dir__, 'package.json'))) 4 | 5 | Pod::Spec.new do |s| 6 | s.name = 'CodePush' 7 | s.version = package['version'].gsub(/v|-beta/, '') 8 | s.summary = package['description'] 9 | s.author = package['author'] 10 | s.license = package['license'] 11 | s.homepage = package['homepage'] 12 | s.source = { :git => 'https://github.com/appzung/react-native-code-push.git', :tag => "v#{s.version}"} 13 | s.ios.deployment_target = '15.5' 14 | s.tvos.deployment_target = '15.5' 15 | s.preserve_paths = '*.js' 16 | s.library = 'z' 17 | s.source_files = 'ios/CodePush/*.{h,m,mm}' 18 | s.public_header_files = ['ios/CodePush/CodePush.h'] 19 | s.pod_target_xcconfig = { "DEFINES_MODULE" => "YES" } 20 | 21 | install_modules_dependencies(s) 22 | 23 | s.dependency 'SSZipArchive', '~> 2.5.5' 24 | s.dependency 'JWT', '~> 3.0.0-beta.12' 25 | s.dependency 'Base64', '~> 1.1' 26 | end 27 | -------------------------------------------------------------------------------- /Examples/CodePushDemoApp/.buckconfig: -------------------------------------------------------------------------------- 1 | 2 | [android] 3 | target = Google Inc.:Google APIs:23 4 | 5 | [maven_repositories] 6 | central = https://repo1.maven.org/maven2 7 | -------------------------------------------------------------------------------- /Examples/CodePushDemoApp/.editorconfig: -------------------------------------------------------------------------------- 1 | # Windows files 2 | [*.bat] 3 | end_of_line = crlf 4 | -------------------------------------------------------------------------------- /Examples/CodePushDemoApp/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | extends: '@react-native-community', 4 | }; 5 | -------------------------------------------------------------------------------- /Examples/CodePushDemoApp/.flowconfig: -------------------------------------------------------------------------------- 1 | [ignore] 2 | ; We fork some components by platform 3 | .*/*[.]android.js 4 | 5 | ; Ignore "BUCK" generated dirs 6 | /\.buckd/ 7 | 8 | ; Ignore polyfills 9 | node_modules/react-native/Libraries/polyfills/.* 10 | 11 | ; Flow doesn't support platforms 12 | .*/Libraries/Utilities/LoadingView.js 13 | 14 | [untyped] 15 | .*/node_modules/@react-native-community/cli/.*/.* 16 | 17 | [include] 18 | 19 | [libs] 20 | node_modules/react-native/interface.js 21 | node_modules/react-native/flow/ 22 | 23 | [options] 24 | emoji=true 25 | 26 | exact_by_default=true 27 | 28 | format.bracket_spacing=false 29 | 30 | module.file_ext=.js 31 | module.file_ext=.json 32 | module.file_ext=.ios.js 33 | 34 | munge_underscores=true 35 | 36 | module.name_mapper='^react-native/\(.*\)$' -> '/node_modules/react-native/\1' 37 | 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' 38 | 39 | suppress_type=$FlowIssue 40 | suppress_type=$FlowFixMe 41 | suppress_type=$FlowFixMeProps 42 | suppress_type=$FlowFixMeState 43 | 44 | [lints] 45 | sketchy-null-number=warn 46 | sketchy-null-mixed=warn 47 | sketchy-number=warn 48 | untyped-type-import=warn 49 | nonstrict-import=warn 50 | deprecated-type=warn 51 | unsafe-getters-setters=warn 52 | unnecessary-invariant=warn 53 | signature-verification-failure=warn 54 | 55 | [strict] 56 | deprecated-type 57 | nonstrict-import 58 | sketchy-null 59 | unclear-type 60 | unsafe-getters-setters 61 | untyped-import 62 | untyped-type-import 63 | 64 | [version] 65 | ^0.158.0 66 | -------------------------------------------------------------------------------- /Examples/CodePushDemoApp/.gitattributes: -------------------------------------------------------------------------------- 1 | # Windows files should use crlf line endings 2 | # https://help.github.com/articles/dealing-with-line-endings/ 3 | *.bat text eol=crlf 4 | -------------------------------------------------------------------------------- /Examples/CodePushDemoApp/.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | .DS_Store 4 | 5 | # Xcode 6 | # 7 | build/ 8 | *.pbxuser 9 | !default.pbxuser 10 | *.mode1v3 11 | !default.mode1v3 12 | *.mode2v3 13 | !default.mode2v3 14 | *.perspectivev3 15 | !default.perspectivev3 16 | xcuserdata 17 | *.xccheckout 18 | *.moved-aside 19 | DerivedData 20 | *.hmap 21 | *.ipa 22 | *.xcuserstate 23 | 24 | # Android/IntelliJ 25 | # 26 | build/ 27 | .idea 28 | .gradle 29 | local.properties 30 | *.iml 31 | *.hprof 32 | 33 | # node.js 34 | # 35 | node_modules/ 36 | npm-debug.log 37 | yarn-error.log 38 | 39 | # BUCK 40 | buck-out/ 41 | \.buckd/ 42 | *.keystore 43 | !debug.keystore 44 | 45 | # fastlane 46 | # 47 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 48 | # screenshots whenever they are needed. 49 | # For more information about the recommended setup visit: 50 | # https://docs.fastlane.tools/best-practices/source-control/ 51 | 52 | */fastlane/report.xml 53 | */fastlane/Preview.html 54 | */fastlane/screenshots 55 | 56 | # Bundle artifact 57 | *.jsbundle 58 | 59 | # CocoaPods 60 | /ios/Pods/ 61 | -------------------------------------------------------------------------------- /Examples/CodePushDemoApp/.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | bracketSpacing: false, 3 | jsxBracketSameLine: true, 4 | singleQuote: true, 5 | trailingComma: 'all', 6 | arrowParens: 'avoid', 7 | }; 8 | -------------------------------------------------------------------------------- /Examples/CodePushDemoApp/.watchmanconfig: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /Examples/CodePushDemoApp/__tests__/App-test.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @format 3 | */ 4 | 5 | import 'react-native'; 6 | import React from 'react'; 7 | import App from '../App'; 8 | 9 | // Note: test renderer must be required after react-native. 10 | import renderer from 'react-test-renderer'; 11 | 12 | it('renders correctly', () => { 13 | renderer.create(); 14 | }); 15 | -------------------------------------------------------------------------------- /Examples/CodePushDemoApp/android/app/BUCK: -------------------------------------------------------------------------------- 1 | # To learn about Buck see [Docs](https://buckbuild.com/). 2 | # To run your application with Buck: 3 | # - install Buck 4 | # - `npm start` - to start the packager 5 | # - `cd android` 6 | # - `keytool -genkey -v -keystore keystores/debug.keystore -storepass android -alias androiddebugkey -keypass android -dname "CN=Android Debug,O=Android,C=US"` 7 | # - `./gradlew :app:copyDownloadableDepsToLibs` - make all Gradle compile dependencies available to Buck 8 | # - `buck install -r android/app` - compile, install and run application 9 | # 10 | 11 | load(":build_defs.bzl", "create_aar_targets", "create_jar_targets") 12 | 13 | lib_deps = [] 14 | 15 | create_aar_targets(glob(["libs/*.aar"])) 16 | 17 | create_jar_targets(glob(["libs/*.jar"])) 18 | 19 | android_library( 20 | name = "all-libs", 21 | exported_deps = lib_deps, 22 | ) 23 | 24 | android_library( 25 | name = "app-code", 26 | srcs = glob([ 27 | "src/main/java/**/*.java", 28 | ]), 29 | deps = [ 30 | ":all-libs", 31 | ":build_config", 32 | ":res", 33 | ], 34 | ) 35 | 36 | android_build_config( 37 | name = "build_config", 38 | package = "com.codepushdemoapp", 39 | ) 40 | 41 | android_resource( 42 | name = "res", 43 | package = "com.codepushdemoapp", 44 | res = "src/main/res", 45 | ) 46 | 47 | android_binary( 48 | name = "app", 49 | keystore = "//android/keystores:debug", 50 | manifest = "src/main/AndroidManifest.xml", 51 | package_type = "debug", 52 | deps = [ 53 | ":app-code", 54 | ], 55 | ) 56 | -------------------------------------------------------------------------------- /Examples/CodePushDemoApp/android/app/build_defs.bzl: -------------------------------------------------------------------------------- 1 | """Helper definitions to glob .aar and .jar targets""" 2 | 3 | def create_aar_targets(aarfiles): 4 | for aarfile in aarfiles: 5 | name = "aars__" + aarfile[aarfile.rindex("/") + 1:aarfile.rindex(".aar")] 6 | lib_deps.append(":" + name) 7 | android_prebuilt_aar( 8 | name = name, 9 | aar = aarfile, 10 | ) 11 | 12 | def create_jar_targets(jarfiles): 13 | for jarfile in jarfiles: 14 | name = "jars__" + jarfile[jarfile.rindex("/") + 1:jarfile.rindex(".jar")] 15 | lib_deps.append(":" + name) 16 | prebuilt_jar( 17 | name = name, 18 | binary_jar = jarfile, 19 | ) 20 | -------------------------------------------------------------------------------- /Examples/CodePushDemoApp/android/app/debug.keystore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AppZung/react-native-code-push/b1884458f58f9e43a50469d761bde645e80ecf18/Examples/CodePushDemoApp/android/app/debug.keystore -------------------------------------------------------------------------------- /Examples/CodePushDemoApp/android/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | -------------------------------------------------------------------------------- /Examples/CodePushDemoApp/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 13 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Examples/CodePushDemoApp/android/app/src/main/java/com/codepushdemoapp/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.codepushdemoapp; 2 | 3 | import com.facebook.react.ReactActivity; 4 | 5 | public class MainActivity extends ReactActivity { 6 | 7 | /** 8 | * Returns the name of the main component registered from JavaScript. This is used to schedule 9 | * rendering of the component. 10 | */ 11 | @Override 12 | protected String getMainComponentName() { 13 | return "CodePushDemoApp"; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Examples/CodePushDemoApp/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AppZung/react-native-code-push/b1884458f58f9e43a50469d761bde645e80ecf18/Examples/CodePushDemoApp/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /Examples/CodePushDemoApp/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AppZung/react-native-code-push/b1884458f58f9e43a50469d761bde645e80ecf18/Examples/CodePushDemoApp/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /Examples/CodePushDemoApp/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AppZung/react-native-code-push/b1884458f58f9e43a50469d761bde645e80ecf18/Examples/CodePushDemoApp/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /Examples/CodePushDemoApp/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AppZung/react-native-code-push/b1884458f58f9e43a50469d761bde645e80ecf18/Examples/CodePushDemoApp/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /Examples/CodePushDemoApp/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AppZung/react-native-code-push/b1884458f58f9e43a50469d761bde645e80ecf18/Examples/CodePushDemoApp/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /Examples/CodePushDemoApp/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AppZung/react-native-code-push/b1884458f58f9e43a50469d761bde645e80ecf18/Examples/CodePushDemoApp/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /Examples/CodePushDemoApp/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AppZung/react-native-code-push/b1884458f58f9e43a50469d761bde645e80ecf18/Examples/CodePushDemoApp/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /Examples/CodePushDemoApp/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AppZung/react-native-code-push/b1884458f58f9e43a50469d761bde645e80ecf18/Examples/CodePushDemoApp/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /Examples/CodePushDemoApp/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AppZung/react-native-code-push/b1884458f58f9e43a50469d761bde645e80ecf18/Examples/CodePushDemoApp/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /Examples/CodePushDemoApp/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AppZung/react-native-code-push/b1884458f58f9e43a50469d761bde645e80ecf18/Examples/CodePushDemoApp/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /Examples/CodePushDemoApp/android/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | release-channel-public-id-here 3 | CodePushDemoApp 4 | 5 | -------------------------------------------------------------------------------- /Examples/CodePushDemoApp/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Examples/CodePushDemoApp/android/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | ext { 5 | buildToolsVersion = "30.0.2" 6 | minSdkVersion = 21 7 | compileSdkVersion = 30 8 | targetSdkVersion = 30 9 | ndkVersion = "21.4.7075529" 10 | } 11 | repositories { 12 | google() 13 | mavenCentral() 14 | } 15 | dependencies { 16 | classpath("com.android.tools.build:gradle:4.2.2") 17 | // NOTE: Do not place your application dependencies here; they belong 18 | // in the individual module build.gradle files 19 | } 20 | } 21 | 22 | allprojects { 23 | repositories { 24 | mavenCentral() 25 | mavenLocal() 26 | maven { 27 | // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm 28 | url("$rootDir/../node_modules/react-native/android") 29 | } 30 | maven { 31 | // Android JSC is installed from npm 32 | url("$rootDir/../node_modules/jsc-android/dist") 33 | } 34 | 35 | google() 36 | maven { url 'https://www.jitpack.io' } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Examples/CodePushDemoApp/android/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m 13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true 19 | 20 | # AndroidX package structure to make it clearer which packages are bundled with the 21 | # Android operating system, and which are packaged with your app's APK 22 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 23 | android.useAndroidX=true 24 | # Automatically convert third-party libraries to use AndroidX 25 | android.enableJetifier=true 26 | 27 | # Version of flipper SDK to use with React Native 28 | FLIPPER_VERSION=0.99.0 29 | -------------------------------------------------------------------------------- /Examples/CodePushDemoApp/android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AppZung/react-native-code-push/b1884458f58f9e43a50469d761bde645e80ecf18/Examples/CodePushDemoApp/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /Examples/CodePushDemoApp/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.9-all.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /Examples/CodePushDemoApp/android/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'CodePushDemoApp' 2 | apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings) 3 | include ':app' 4 | -------------------------------------------------------------------------------- /Examples/CodePushDemoApp/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "CodePushDemoApp", 3 | "displayName": "CodePushDemoApp" 4 | } -------------------------------------------------------------------------------- /Examples/CodePushDemoApp/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ['module:metro-react-native-babel-preset'], 3 | }; 4 | -------------------------------------------------------------------------------- /Examples/CodePushDemoApp/images/laptop_phone_howitworks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AppZung/react-native-code-push/b1884458f58f9e43a50469d761bde645e80ecf18/Examples/CodePushDemoApp/images/laptop_phone_howitworks.png -------------------------------------------------------------------------------- /Examples/CodePushDemoApp/index.js: -------------------------------------------------------------------------------- 1 | import { AppRegistry } from 'react-native'; 2 | import App from './App'; 3 | 4 | AppRegistry.registerComponent('CodePushDemoApp', () => App); 5 | -------------------------------------------------------------------------------- /Examples/CodePushDemoApp/ios/CodePushDemoApp.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Examples/CodePushDemoApp/ios/CodePushDemoApp.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Examples/CodePushDemoApp/ios/CodePushDemoApp/AppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @interface AppDelegate : UIResponder 5 | 6 | @property (nonatomic, strong) UIWindow *window; 7 | 8 | @end 9 | -------------------------------------------------------------------------------- /Examples/CodePushDemoApp/ios/CodePushDemoApp/AppDelegate.m: -------------------------------------------------------------------------------- 1 | #import "AppDelegate.h" 2 | #import 3 | 4 | #import 5 | #import 6 | #import 7 | 8 | #ifdef FB_SONARKIT_ENABLED 9 | #import 10 | #import 11 | #import 12 | #import 13 | #import 14 | #import 15 | 16 | static void InitializeFlipper(UIApplication *application) { 17 | FlipperClient *client = [FlipperClient sharedClient]; 18 | SKDescriptorMapper *layoutDescriptorMapper = [[SKDescriptorMapper alloc] initWithDefaults]; 19 | [client addPlugin:[[FlipperKitLayoutPlugin alloc] initWithRootNode:application withDescriptorMapper:layoutDescriptorMapper]]; 20 | [client addPlugin:[[FKUserDefaultsPlugin alloc] initWithSuiteName:nil]]; 21 | [client addPlugin:[FlipperKitReactPlugin new]]; 22 | [client addPlugin:[[FlipperKitNetworkPlugin alloc] initWithNetworkAdapter:[SKIOSNetworkAdapter new]]]; 23 | [client start]; 24 | } 25 | #endif 26 | 27 | @implementation AppDelegate 28 | 29 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 30 | { 31 | #ifdef FB_SONARKIT_ENABLED 32 | InitializeFlipper(application); 33 | #endif 34 | 35 | RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions]; 36 | RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge 37 | moduleName:@"CodePushDemoApp" 38 | initialProperties:nil]; 39 | 40 | if (@available(iOS 13.0, *)) { 41 | rootView.backgroundColor = [UIColor systemBackgroundColor]; 42 | } else { 43 | rootView.backgroundColor = [UIColor whiteColor]; 44 | } 45 | 46 | self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; 47 | UIViewController *rootViewController = [UIViewController new]; 48 | rootViewController.view = rootView; 49 | self.window.rootViewController = rootViewController; 50 | [self.window makeKeyAndVisible]; 51 | return YES; 52 | } 53 | 54 | - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge 55 | { 56 | #if DEBUG 57 | return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil]; 58 | #else 59 | return [CodePush bundleURL]; 60 | #endif 61 | } 62 | 63 | @end 64 | -------------------------------------------------------------------------------- /Examples/CodePushDemoApp/ios/CodePushDemoApp/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /Examples/CodePushDemoApp/ios/CodePushDemoApp/Images.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Examples/CodePushDemoApp/ios/CodePushDemoApp/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | CodePushDemoApp 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | LSRequiresIPhoneOS 26 | 27 | NSAppTransportSecurity 28 | 29 | NSExceptionDomains 30 | 31 | localhost 32 | 33 | NSExceptionAllowsInsecureHTTPLoads 34 | 35 | 36 | 37 | 38 | NSLocationWhenInUseUsageDescription 39 | 40 | UILaunchStoryboardName 41 | LaunchScreen 42 | UIRequiredDeviceCapabilities 43 | 44 | armv7 45 | 46 | UISupportedInterfaceOrientations 47 | 48 | UIInterfaceOrientationPortrait 49 | UIInterfaceOrientationLandscapeLeft 50 | UIInterfaceOrientationLandscapeRight 51 | 52 | UIViewControllerBasedStatusBarAppearance 53 | 54 | CodePushReleaseChannelPublicId 55 | release-channel-public-id-here 56 | 57 | 58 | -------------------------------------------------------------------------------- /Examples/CodePushDemoApp/ios/CodePushDemoApp/main.m: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | #import "AppDelegate.h" 4 | 5 | int main(int argc, char * argv[]) { 6 | @autoreleasepool { 7 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Examples/CodePushDemoApp/ios/CodePushDemoAppTests/CodePushDemoAppTests.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | #import 5 | #import 6 | 7 | #define TIMEOUT_SECONDS 600 8 | #define TEXT_TO_LOOK_FOR @"Welcome to React" 9 | 10 | @interface CodePushDemoAppTests : XCTestCase 11 | 12 | @end 13 | 14 | @implementation CodePushDemoAppTests 15 | 16 | - (BOOL)findSubviewInView:(UIView *)view matching:(BOOL(^)(UIView *view))test 17 | { 18 | if (test(view)) { 19 | return YES; 20 | } 21 | for (UIView *subview in [view subviews]) { 22 | if ([self findSubviewInView:subview matching:test]) { 23 | return YES; 24 | } 25 | } 26 | return NO; 27 | } 28 | 29 | - (void)testRendersWelcomeScreen 30 | { 31 | UIViewController *vc = [[[RCTSharedApplication() delegate] window] rootViewController]; 32 | NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS]; 33 | BOOL foundElement = NO; 34 | 35 | __block NSString *redboxError = nil; 36 | #ifdef DEBUG 37 | RCTSetLogFunction(^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) { 38 | if (level >= RCTLogLevelError) { 39 | redboxError = message; 40 | } 41 | }); 42 | #endif 43 | 44 | while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) { 45 | [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; 46 | [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; 47 | 48 | foundElement = [self findSubviewInView:vc.view matching:^BOOL(UIView *view) { 49 | if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) { 50 | return YES; 51 | } 52 | return NO; 53 | }]; 54 | } 55 | 56 | #ifdef DEBUG 57 | RCTSetLogFunction(RCTDefaultLogFunction); 58 | #endif 59 | 60 | XCTAssertNil(redboxError, @"RedBox error: %@", redboxError); 61 | XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS); 62 | } 63 | 64 | 65 | @end 66 | -------------------------------------------------------------------------------- /Examples/CodePushDemoApp/ios/CodePushDemoAppTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /Examples/CodePushDemoApp/ios/Podfile: -------------------------------------------------------------------------------- 1 | require_relative '../node_modules/react-native/scripts/react_native_pods' 2 | require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules' 3 | 4 | platform :ios, '11.0' 5 | 6 | target 'CodePushDemoApp' do 7 | config = use_native_modules! 8 | 9 | use_react_native!( 10 | :path => config[:reactNativePath], 11 | # to enable hermes on iOS, change `false` to `true` and then install pods 12 | :hermes_enabled => false 13 | ) 14 | 15 | target 'CodePushDemoAppTests' do 16 | inherit! :complete 17 | # Pods for testing 18 | end 19 | 20 | # Enables Flipper. 21 | # 22 | # Note that if you have use_frameworks! enabled, Flipper will not work and 23 | # you should disable the next line. 24 | use_flipper!() 25 | 26 | post_install do |installer| 27 | react_native_post_install(installer) 28 | __apply_Xcode_12_5_M1_post_install_workaround(installer) 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /Examples/CodePushDemoApp/metro.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Metro configuration for React Native 3 | * https://github.com/facebook/react-native 4 | * 5 | * @format 6 | */ 7 | 8 | module.exports = { 9 | transformer: { 10 | getTransformOptions: async () => ({ 11 | transform: { 12 | experimentalImportSupport: false, 13 | inlineRequires: true, 14 | }, 15 | }), 16 | }, 17 | }; 18 | -------------------------------------------------------------------------------- /Examples/CodePushDemoApp/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "CodePushDemoApp", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "android": "react-native run-android", 7 | "ios": "react-native run-ios", 8 | "start": "react-native start", 9 | "test": "jest", 10 | "lint": "eslint ." 11 | }, 12 | "dependencies": { 13 | "@appzung/react-native-code-push": "^8.3.2", 14 | "react": "17.0.2", 15 | "react-native": "0.68.5" 16 | }, 17 | "resolutions": { 18 | "strip-ansi": "^6.0.1", 19 | "ansi-regex": "^5.0.1" 20 | }, 21 | "devDependencies": { 22 | "@babel/core": "^7.15.8", 23 | "@babel/runtime": "^7.15.4", 24 | "@react-native-community/eslint-config": "^3.0.1", 25 | "babel-jest": "^27.2.5", 26 | "eslint": "^8.0.0", 27 | "jest": "^27.2.5", 28 | "metro-react-native-babel-preset": "^0.66.2", 29 | "react-test-renderer": "17.0.2" 30 | }, 31 | "jest": { 32 | "preset": "react-native" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Examples/CodePushDemoAppCpp/.buckconfig: -------------------------------------------------------------------------------- 1 | 2 | [android] 3 | target = Google Inc.:Google APIs:23 4 | 5 | [maven_repositories] 6 | central = https://repo1.maven.org/maven2 7 | -------------------------------------------------------------------------------- /Examples/CodePushDemoAppCpp/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | extends: '@react-native-community', 4 | }; 5 | -------------------------------------------------------------------------------- /Examples/CodePushDemoAppCpp/.flowconfig: -------------------------------------------------------------------------------- 1 | [ignore] 2 | ; We fork some components by platform 3 | .*/*[.]android.js 4 | 5 | ; Ignore "BUCK" generated dirs 6 | /\.buckd/ 7 | 8 | ; Ignore polyfills 9 | node_modules/react-native/Libraries/polyfills/.* 10 | 11 | ; These should not be required directly 12 | ; require from fbjs/lib instead: require('fbjs/lib/warning') 13 | node_modules/warning/.* 14 | 15 | ; Flow doesn't support platforms 16 | .*/Libraries/Utilities/LoadingView.js 17 | 18 | [untyped] 19 | .*/node_modules/@react-native-community/cli/.*/.* 20 | 21 | [include] 22 | 23 | [libs] 24 | node_modules/react-native/interface.js 25 | node_modules/react-native/flow/ 26 | 27 | [options] 28 | emoji=true 29 | 30 | esproposal.optional_chaining=enable 31 | esproposal.nullish_coalescing=enable 32 | 33 | module.file_ext=.js 34 | module.file_ext=.json 35 | module.file_ext=.ios.js 36 | 37 | munge_underscores=true 38 | 39 | module.name_mapper='^react-native/\(.*\)$' -> '/node_modules/react-native/\1' 40 | 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' 41 | 42 | suppress_type=$FlowIssue 43 | suppress_type=$FlowFixMe 44 | suppress_type=$FlowFixMeProps 45 | suppress_type=$FlowFixMeState 46 | 47 | suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(\\)? *\\(site=[a-z,_]*react_native\\(_ios\\)?_\\(oss\\|fb\\)[a-z,_]*\\)?)\\) 48 | suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(\\)? *\\(site=[a-z,_]*react_native\\(_ios\\)?_\\(oss\\|fb\\)[a-z,_]*\\)?)\\)?:? #[0-9]+ 49 | suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError 50 | 51 | [lints] 52 | sketchy-null-number=warn 53 | sketchy-null-mixed=warn 54 | sketchy-number=warn 55 | untyped-type-import=warn 56 | nonstrict-import=warn 57 | deprecated-type=warn 58 | unsafe-getters-setters=warn 59 | unnecessary-invariant=warn 60 | signature-verification-failure=warn 61 | deprecated-utility=error 62 | 63 | [strict] 64 | deprecated-type 65 | nonstrict-import 66 | sketchy-null 67 | unclear-type 68 | unsafe-getters-setters 69 | untyped-import 70 | untyped-type-import 71 | 72 | [version] 73 | ^0.122.0 74 | -------------------------------------------------------------------------------- /Examples/CodePushDemoAppCpp/.gitattributes: -------------------------------------------------------------------------------- 1 | *.pbxproj -text 2 | -------------------------------------------------------------------------------- /Examples/CodePushDemoAppCpp/.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | .DS_Store 4 | 5 | # Xcode 6 | # 7 | build/ 8 | *.pbxuser 9 | !default.pbxuser 10 | *.mode1v3 11 | !default.mode1v3 12 | *.mode2v3 13 | !default.mode2v3 14 | *.perspectivev3 15 | !default.perspectivev3 16 | xcuserdata 17 | *.xccheckout 18 | *.moved-aside 19 | DerivedData 20 | *.hmap 21 | *.ipa 22 | *.xcuserstate 23 | 24 | # Android/IntelliJ 25 | # 26 | build/ 27 | .idea 28 | .gradle 29 | local.properties 30 | *.iml 31 | 32 | # Visual Studio Code 33 | # 34 | .vscode/ 35 | 36 | # node.js 37 | # 38 | node_modules/ 39 | npm-debug.log 40 | yarn-error.log 41 | 42 | # BUCK 43 | buck-out/ 44 | \.buckd/ 45 | *.keystore 46 | !debug.keystore 47 | 48 | # fastlane 49 | # 50 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 51 | # screenshots whenever they are needed. 52 | # For more information about the recommended setup visit: 53 | # https://docs.fastlane.tools/best-practices/source-control/ 54 | 55 | */fastlane/report.xml 56 | */fastlane/Preview.html 57 | */fastlane/screenshots 58 | 59 | # Bundle artifact 60 | *.jsbundle 61 | 62 | # CocoaPods 63 | /ios/Pods/ 64 | -------------------------------------------------------------------------------- /Examples/CodePushDemoAppCpp/.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | bracketSpacing: false, 3 | jsxBracketSameLine: true, 4 | singleQuote: true, 5 | trailingComma: 'all', 6 | }; 7 | -------------------------------------------------------------------------------- /Examples/CodePushDemoAppCpp/.watchmanconfig: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /Examples/CodePushDemoAppCpp/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "CodePushDemoAppCpp", 3 | "displayName": "CodePushDemoAppCpp" 4 | } 5 | -------------------------------------------------------------------------------- /Examples/CodePushDemoAppCpp/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ['module:metro-react-native-babel-preset'], 3 | }; 4 | -------------------------------------------------------------------------------- /Examples/CodePushDemoAppCpp/images/laptop_phone_howitworks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AppZung/react-native-code-push/b1884458f58f9e43a50469d761bde645e80ecf18/Examples/CodePushDemoAppCpp/images/laptop_phone_howitworks.png -------------------------------------------------------------------------------- /Examples/CodePushDemoAppCpp/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @format 3 | */ 4 | 5 | import {AppRegistry} from 'react-native'; 6 | import App from './App'; 7 | import {name as appName} from './app.json'; 8 | 9 | AppRegistry.registerComponent(appName, () => App); 10 | -------------------------------------------------------------------------------- /Examples/CodePushDemoAppCpp/metro.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Metro configuration for React Native 3 | * https://github.com/facebook/react-native 4 | * 5 | * @format 6 | */ 7 | const path = require('path'); 8 | const blacklist = require('metro-config/src/defaults/blacklist'); 9 | 10 | module.exports = { 11 | resolver: { 12 | blacklistRE: blacklist([ 13 | // This stops "react-native run-windows" from causing the metro server to crash if its already running 14 | new RegExp( 15 | `${path.resolve(__dirname, 'windows').replace(/[/\\]/g, '/')}.*`, 16 | ), 17 | // This prevents "react-native run-windows" from hitting: EBUSY: resource busy or locked, open msbuild.ProjectImports.zip 18 | /.*\.ProjectImports\.zip/, 19 | ]), 20 | }, 21 | transformer: { 22 | getTransformOptions: async () => ({ 23 | transform: { 24 | experimentalImportSupport: false, 25 | inlineRequires: false, 26 | }, 27 | }), 28 | }, 29 | }; 30 | -------------------------------------------------------------------------------- /Examples/CodePushDemoAppCpp/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "CodePushDemoAppCpp", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "start": "react-native start", 7 | "test": "jest", 8 | "lint": "eslint .", 9 | "windows": "react-native run-windows" 10 | }, 11 | "dependencies": { 12 | "@appzung/react-native-code-push": "^8.3.2", 13 | "react": "^17.0.2", 14 | "react-native": "^0.68.5", 15 | "react-native-windows": "^1.0.0" 16 | }, 17 | "resolutions": { 18 | "strip-ansi": "^6.0.1", 19 | "ansi-regex": "^5.0.1", 20 | "node-fetch": "^2.6.7" 21 | }, 22 | "devDependencies": { 23 | "@babel/core": "^7.8.4", 24 | "@babel/runtime": "^7.8.4", 25 | "@react-native-community/eslint-config": "^3.0.1", 26 | "babel-jest": "^27.2.5", 27 | "eslint": "^8.0.0", 28 | "jest": "^27.2.5", 29 | "metro-react-native-babel-preset": "^0.66.2", 30 | "react-test-renderer": "17.0.2" 31 | }, 32 | "jest": { 33 | "preset": "react-native" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Examples/CodePushDemoAppCpp/windows/.gitignore: -------------------------------------------------------------------------------- 1 | *AppPackages* 2 | *BundleArtifacts* 3 | 4 | #OS junk files 5 | [Tt]humbs.db 6 | *.DS_Store 7 | 8 | #Visual Studio files 9 | *.[Oo]bj 10 | *.user 11 | *.aps 12 | *.pch 13 | *.vspscc 14 | *.vssscc 15 | *_i.c 16 | *_p.c 17 | *.ncb 18 | *.suo 19 | *.tlb 20 | *.tlh 21 | *.bak 22 | *.[Cc]ache 23 | *.ilk 24 | *.log 25 | *.lib 26 | *.sbr 27 | *.sdf 28 | *.opensdf 29 | *.opendb 30 | *.unsuccessfulbuild 31 | ipch/ 32 | [Oo]bj/ 33 | [Bb]in 34 | [Dd]ebug*/ 35 | [Rr]elease*/ 36 | Ankh.NoLoad 37 | 38 | # Visual C++ cache files 39 | ipch/ 40 | *.aps 41 | *.ncb 42 | *.opendb 43 | *.opensdf 44 | *.sdf 45 | *.cachefile 46 | *.VC.db 47 | *.VC.VC.opendb 48 | 49 | #MonoDevelop 50 | *.pidb 51 | *.userprefs 52 | 53 | #Tooling 54 | _ReSharper*/ 55 | *.resharper 56 | [Tt]est[Rr]esult* 57 | *.sass-cache 58 | 59 | #Project files 60 | [Bb]uild/ 61 | 62 | #Subversion files 63 | .svn 64 | 65 | # Office Temp Files 66 | ~$* 67 | 68 | # vim Temp Files 69 | *~ 70 | 71 | #NuGet 72 | packages/ 73 | *.nupkg 74 | 75 | #ncrunch 76 | *ncrunch* 77 | *crunch*.local.xml 78 | 79 | # visual studio database projects 80 | *.dbmdl 81 | 82 | #Test files 83 | *.testsettings 84 | 85 | #Other files 86 | *.DotSettings 87 | .vs/ 88 | *project.lock.json 89 | 90 | #Files generated by the VS build 91 | **/Generated Files/** 92 | 93 | -------------------------------------------------------------------------------- /Examples/CodePushDemoAppCpp/windows/CodePushDemoAppCpp/.gitignore: -------------------------------------------------------------------------------- 1 | /Bundle 2 | -------------------------------------------------------------------------------- /Examples/CodePushDemoAppCpp/windows/CodePushDemoAppCpp/App.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "App.xaml.g.h" 4 | #include "winrt/Microsoft.ReactNative.h" 5 | 6 | namespace activation = winrt::Windows::ApplicationModel::Activation; 7 | 8 | namespace winrt::CodePushDemoAppCpp::implementation 9 | { 10 | struct App : AppT 11 | { 12 | App() noexcept; 13 | 14 | void OnLaunched(Windows::ApplicationModel::Activation::LaunchActivatedEventArgs const&); 15 | void OnSuspending(IInspectable const&, Windows::ApplicationModel::SuspendingEventArgs const&); 16 | void OnNavigationFailed(IInspectable const&, Windows::UI::Xaml::Navigation::NavigationFailedEventArgs const&); 17 | 18 | winrt::Microsoft::ReactNative::ReactNativeHost& Host() noexcept { return m_host; } 19 | private: 20 | winrt::Microsoft::ReactNative::ReactNativeHost m_host; 21 | }; 22 | } // namespace winrt::CodePushDemoAppCpp::implementation 23 | -------------------------------------------------------------------------------- /Examples/CodePushDemoAppCpp/windows/CodePushDemoAppCpp/App.idl: -------------------------------------------------------------------------------- 1 | namespace CodePushDemoAppCpp 2 | { 3 | } 4 | -------------------------------------------------------------------------------- /Examples/CodePushDemoAppCpp/windows/CodePushDemoAppCpp/App.xaml: -------------------------------------------------------------------------------- 1 |  6 | 7 | -------------------------------------------------------------------------------- /Examples/CodePushDemoAppCpp/windows/CodePushDemoAppCpp/Assets/LockScreenLogo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AppZung/react-native-code-push/b1884458f58f9e43a50469d761bde645e80ecf18/Examples/CodePushDemoAppCpp/windows/CodePushDemoAppCpp/Assets/LockScreenLogo.scale-200.png -------------------------------------------------------------------------------- /Examples/CodePushDemoAppCpp/windows/CodePushDemoAppCpp/Assets/SplashScreen.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AppZung/react-native-code-push/b1884458f58f9e43a50469d761bde645e80ecf18/Examples/CodePushDemoAppCpp/windows/CodePushDemoAppCpp/Assets/SplashScreen.scale-200.png -------------------------------------------------------------------------------- /Examples/CodePushDemoAppCpp/windows/CodePushDemoAppCpp/Assets/Square150x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AppZung/react-native-code-push/b1884458f58f9e43a50469d761bde645e80ecf18/Examples/CodePushDemoAppCpp/windows/CodePushDemoAppCpp/Assets/Square150x150Logo.scale-200.png -------------------------------------------------------------------------------- /Examples/CodePushDemoAppCpp/windows/CodePushDemoAppCpp/Assets/Square44x44Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AppZung/react-native-code-push/b1884458f58f9e43a50469d761bde645e80ecf18/Examples/CodePushDemoAppCpp/windows/CodePushDemoAppCpp/Assets/Square44x44Logo.scale-200.png -------------------------------------------------------------------------------- /Examples/CodePushDemoAppCpp/windows/CodePushDemoAppCpp/Assets/Square44x44Logo.targetsize-24_altform-unplated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AppZung/react-native-code-push/b1884458f58f9e43a50469d761bde645e80ecf18/Examples/CodePushDemoAppCpp/windows/CodePushDemoAppCpp/Assets/Square44x44Logo.targetsize-24_altform-unplated.png -------------------------------------------------------------------------------- /Examples/CodePushDemoAppCpp/windows/CodePushDemoAppCpp/Assets/StoreLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AppZung/react-native-code-push/b1884458f58f9e43a50469d761bde645e80ecf18/Examples/CodePushDemoAppCpp/windows/CodePushDemoAppCpp/Assets/StoreLogo.png -------------------------------------------------------------------------------- /Examples/CodePushDemoAppCpp/windows/CodePushDemoAppCpp/Assets/Wide310x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AppZung/react-native-code-push/b1884458f58f9e43a50469d761bde645e80ecf18/Examples/CodePushDemoAppCpp/windows/CodePushDemoAppCpp/Assets/Wide310x150Logo.scale-200.png -------------------------------------------------------------------------------- /Examples/CodePushDemoAppCpp/windows/CodePushDemoAppCpp/AutolinkedNativeModules.g.cpp: -------------------------------------------------------------------------------- 1 | // AutolinkedNativeModules.g.cpp contents generated by "react-native autolink-windows" 2 | // clang-format off 3 | #include "pch.h" 4 | #include "AutolinkedNativeModules.g.h" 5 | 6 | // Includes from react-native-code-push-windows 7 | #include "winrt/Microsoft.CodePush.ReactNative.h" 8 | 9 | namespace winrt::Microsoft::ReactNative 10 | { 11 | 12 | void RegisterAutolinkedNativeModulePackages(winrt::Windows::Foundation::Collections::IVector const& packageProviders) 13 | { 14 | // IReactPackageProviders from react-native-code-push-windows 15 | packageProviders.Append(winrt::Microsoft::CodePush::ReactNative::ReactPackageProvider()); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /Examples/CodePushDemoAppCpp/windows/CodePushDemoAppCpp/AutolinkedNativeModules.g.h: -------------------------------------------------------------------------------- 1 | // AutolinkedNativeModules.g.h contents generated by "react-native autolink-windows" 2 | 3 | #pragma once 4 | 5 | namespace winrt::Microsoft::ReactNative 6 | { 7 | 8 | void RegisterAutolinkedNativeModulePackages(winrt::Windows::Foundation::Collections::IVector const& packageProviders); 9 | 10 | } 11 | -------------------------------------------------------------------------------- /Examples/CodePushDemoAppCpp/windows/CodePushDemoAppCpp/AutolinkedNativeModules.g.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Examples/CodePushDemoAppCpp/windows/CodePushDemoAppCpp/CodePushDemoAppCpp.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | Assets 25 | 26 | 27 | Assets 28 | 29 | 30 | Assets 31 | 32 | 33 | Assets 34 | 35 | 36 | Assets 37 | 38 | 39 | Assets 40 | 41 | 42 | Assets 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | {e48dc53e-40b1-40cb-970a-f89935452892} 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /Examples/CodePushDemoAppCpp/windows/CodePushDemoAppCpp/CodePushDemoAppCpp_TemporaryKey.pfx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AppZung/react-native-code-push/b1884458f58f9e43a50469d761bde645e80ecf18/Examples/CodePushDemoAppCpp/windows/CodePushDemoAppCpp/CodePushDemoAppCpp_TemporaryKey.pfx -------------------------------------------------------------------------------- /Examples/CodePushDemoAppCpp/windows/CodePushDemoAppCpp/MainPage.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "MainPage.h" 3 | #if __has_include("MainPage.g.cpp") 4 | #include "MainPage.g.cpp" 5 | #endif 6 | 7 | #include "App.h" 8 | 9 | 10 | 11 | using namespace winrt; 12 | using namespace Windows::UI::Xaml; 13 | 14 | namespace winrt::CodePushDemoAppCpp::implementation 15 | { 16 | MainPage::MainPage() 17 | { 18 | InitializeComponent(); 19 | auto app = Application::Current().as(); 20 | ReactRootView().ReactNativeHost(app->Host()); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Examples/CodePushDemoAppCpp/windows/CodePushDemoAppCpp/MainPage.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "MainPage.g.h" 3 | #include 4 | 5 | 6 | namespace winrt::CodePushDemoAppCpp::implementation 7 | { 8 | struct MainPage : MainPageT 9 | { 10 | MainPage(); 11 | }; 12 | } 13 | 14 | namespace winrt::CodePushDemoAppCpp::factory_implementation 15 | { 16 | struct MainPage : MainPageT 17 | { 18 | }; 19 | } 20 | -------------------------------------------------------------------------------- /Examples/CodePushDemoAppCpp/windows/CodePushDemoAppCpp/MainPage.idl: -------------------------------------------------------------------------------- 1 | namespace CodePushDemoAppCpp 2 | { 3 | [default_interface] 4 | runtimeclass MainPage : Windows.UI.Xaml.Controls.Page 5 | { 6 | MainPage(); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Examples/CodePushDemoAppCpp/windows/CodePushDemoAppCpp/MainPage.xaml: -------------------------------------------------------------------------------- 1 | 11 | 16 | 17 | -------------------------------------------------------------------------------- /Examples/CodePushDemoAppCpp/windows/CodePushDemoAppCpp/Package.appxmanifest: -------------------------------------------------------------------------------- 1 |  2 | 3 | 8 | 9 | 13 | 14 | 15 | 16 | 17 | CodePushDemoAppCpp 18 | Aleksey 19 | Assets\StoreLogo.png 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 35 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /Examples/CodePushDemoAppCpp/windows/CodePushDemoAppCpp/PropertySheet.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /Examples/CodePushDemoAppCpp/windows/CodePushDemoAppCpp/ReactPackageProvider.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "ReactPackageProvider.h" 3 | #include "NativeModules.h" 4 | 5 | 6 | using namespace winrt::Microsoft::ReactNative; 7 | 8 | namespace winrt::CodePushDemoAppCpp::implementation 9 | { 10 | 11 | void ReactPackageProvider::CreatePackage(IReactPackageBuilder const &packageBuilder) noexcept 12 | { 13 | AddAttributedModules(packageBuilder); 14 | } 15 | 16 | } // namespace winrt::CodePushDemoAppCpp::implementation 17 | -------------------------------------------------------------------------------- /Examples/CodePushDemoAppCpp/windows/CodePushDemoAppCpp/ReactPackageProvider.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "winrt/Microsoft.ReactNative.h" 4 | 5 | namespace winrt::CodePushDemoAppCpp::implementation 6 | { 7 | struct ReactPackageProvider : winrt::implements 8 | { 9 | public: // IReactPackageProvider 10 | void CreatePackage(winrt::Microsoft::ReactNative::IReactPackageBuilder const &packageBuilder) noexcept; 11 | }; 12 | } // namespace winrt::CodePushDemoAppCpp::implementation 13 | -------------------------------------------------------------------------------- /Examples/CodePushDemoAppCpp/windows/CodePushDemoAppCpp/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Examples/CodePushDemoAppCpp/windows/CodePushDemoAppCpp/pch.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | -------------------------------------------------------------------------------- /Examples/CodePushDemoAppCpp/windows/CodePushDemoAppCpp/pch.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define NOMINMAX 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | AppZung CodePush Plugin for React Native 2 | 3 | Copyright (c) Louis Lagrange and Louis Lagrange Consulting 4 | 5 | All rights reserved. 6 | 7 | MIT License 8 | 9 | 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: 10 | 11 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 12 | 13 | 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. 14 | -------------------------------------------------------------------------------- /android/app/build.gradle: -------------------------------------------------------------------------------- 1 | def isNewArchitectureEnabled() { 2 | return rootProject.hasProperty("newArchEnabled") && rootProject.getProperty("newArchEnabled") == "true" 3 | } 4 | 5 | apply plugin: "com.android.library" 6 | 7 | if (isNewArchitectureEnabled()) { 8 | apply plugin: "com.facebook.react" 9 | } 10 | 11 | def getExtOrDefault(name) { 12 | return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties["CodePush_" + name] 13 | } 14 | 15 | def getExtOrIntegerDefault(name) { 16 | return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["CodePush_" + name]).toInteger() 17 | } 18 | 19 | def supportsNamespace() { 20 | def parsed = com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION.tokenize('.') 21 | def major = parsed[0].toInteger() 22 | def minor = parsed[1].toInteger() 23 | 24 | // Namespace support was added in 7.3.0 25 | return (major == 7 && minor >= 3) || major >= 8 26 | } 27 | 28 | android { 29 | if (supportsNamespace()) { 30 | namespace "com.appzung.codepush.react" 31 | 32 | sourceSets { 33 | main { 34 | manifest.srcFile "src/main/AndroidManifestNew.xml" 35 | } 36 | } 37 | } 38 | 39 | compileSdkVersion getExtOrIntegerDefault("compileSdkVersion") 40 | 41 | defaultConfig { 42 | minSdkVersion getExtOrIntegerDefault("minSdkVersion") 43 | targetSdkVersion getExtOrIntegerDefault("targetSdkVersion") 44 | buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString() 45 | 46 | consumerProguardFiles 'proguard-rules.pro' 47 | } 48 | 49 | buildFeatures { 50 | buildConfig true 51 | } 52 | 53 | buildTypes { 54 | release { 55 | minifyEnabled false 56 | } 57 | } 58 | 59 | lintOptions { 60 | disable "GradleCompatible" 61 | } 62 | 63 | compileOptions { 64 | sourceCompatibility JavaVersion.VERSION_1_8 65 | targetCompatibility JavaVersion.VERSION_1_8 66 | } 67 | } 68 | 69 | repositories { 70 | mavenCentral() 71 | google() 72 | } 73 | 74 | def isInDevelopment = project.hasProperty('CodePush_development') && project.property('CodePush_development') == "true" 75 | 76 | dependencies { 77 | if (isInDevelopment) { 78 | implementation("com.facebook.react:react-android:0.71.+") 79 | } else { 80 | // For < 0.71, this will be from the local maven repo 81 | // For > 0.71, this will be replaced by `com.facebook.react:react-android:$version` by react gradle plugin 82 | //noinspection GradleDynamicVersion 83 | implementation "com.facebook.react:react-native:+" 84 | } 85 | implementation "com.nimbusds:nimbus-jose-jwt:9.37.3" 86 | } 87 | -------------------------------------------------------------------------------- /android/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | 19 | # Invoked via reflection, when setting js bundle. 20 | -keepclassmembers class com.facebook.react.ReactInstanceManager { 21 | private final ** mBundleLoader; 22 | } 23 | -keepclassmembers class com.facebook.react.runtime.ReactHostImpl { 24 | private final ** mReactHostDelegate; 25 | } 26 | -keep interface com.facebook.react.runtime.ReactHostDelegate { *; } 27 | -keep class * implements com.facebook.react.runtime.ReactHostDelegate { *; } 28 | 29 | # Can't find referenced class org.bouncycastle.** 30 | -dontwarn com.nimbusds.jose.** 31 | -------------------------------------------------------------------------------- /android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /android/app/src/main/AndroidManifestNew.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /android/app/src/main/java/com/appzung/codepush/react/CodePushConstants.java: -------------------------------------------------------------------------------- 1 | package com.appzung.codepush.react; 2 | 3 | public class CodePushConstants { 4 | public static final String ASSETS_BUNDLE_PREFIX = "assets://"; 5 | public static final String BINARY_MODIFIED_TIME_KEY = "binaryModifiedTime"; 6 | public static final String CODE_PUSH_FOLDER_PREFIX = "CodePush"; 7 | public static final String CODE_PUSH_HASH_FILE_NAME = "CodePushHash"; 8 | public static final String CODE_PUSH_OLD_HASH_FILE_NAME = "CodePushHash.json"; 9 | public static final String CODE_PUSH_PREFERENCES = "CodePush"; 10 | public static final String CURRENT_PACKAGE_KEY = "currentPackage"; 11 | public static final String DEFAULT_JS_BUNDLE_NAME = "index.android.bundle"; 12 | public static final String DIFF_MANIFEST_FILE_NAME = "hotcodepush.json"; 13 | public static final int DOWNLOAD_BUFFER_SIZE = 1024 * 256; 14 | public static final String DOWNLOAD_FILE_NAME = "download.zip"; 15 | public static final String DOWNLOAD_PROGRESS_EVENT_NAME = "CodePushDownloadProgress"; 16 | public static final String DOWNLOAD_URL_KEY = "downloadUrl"; 17 | public static final String FAILED_UPDATES_KEY = "CODE_PUSH_FAILED_UPDATES"; 18 | public static final String PACKAGE_FILE_NAME = "app.json"; 19 | public static final String PACKAGE_HASH_KEY = "packageHash"; 20 | public static final String PENDING_UPDATE_HASH_KEY = "hash"; 21 | public static final String PENDING_UPDATE_IS_LOADING_KEY = "isLoading"; 22 | public static final String PENDING_UPDATE_KEY = "CODE_PUSH_PENDING_UPDATE"; 23 | public static final String PREVIOUS_PACKAGE_KEY = "previousPackage"; 24 | public static final String REACT_NATIVE_LOG_TAG = "ReactNative"; 25 | public static final String RELATIVE_BUNDLE_PATH_KEY = "bundlePath"; 26 | public static final String STATUS_FILE = "codepush.json"; 27 | public static final String UNZIPPED_FOLDER_NAME = "unzipped"; 28 | public static final String CODE_PUSH_APK_BUILD_TIME_KEY = "CODE_PUSH_APK_BUILD_TIME"; 29 | public static final String BUNDLE_JWT_FILE = ".codepushrelease"; 30 | public static final String LATEST_ROLLBACK_INFO_KEY = "LATEST_ROLLBACK_INFO"; 31 | public static final String LATEST_ROLLBACK_PACKAGE_HASH_KEY = "packageHash"; 32 | public static final String LATEST_ROLLBACK_TIME_KEY = "time"; 33 | public static final String LATEST_ROLLBACK_COUNT_KEY = "count"; 34 | public static final String CLIENT_UNIQUE_ID_KEY = "clientUniqueId"; 35 | public static final String TELEMETRY_ENABLED_KEY = "telemetryEnabled"; 36 | public static final String DATA_TRANSMISSION_ENABLED_KEY = "dataTransmissionEnabled"; 37 | } 38 | -------------------------------------------------------------------------------- /android/app/src/main/java/com/appzung/codepush/react/CodePushInstallMode.java: -------------------------------------------------------------------------------- 1 | package com.appzung.codepush.react; 2 | 3 | public enum CodePushInstallMode { 4 | IMMEDIATE(0), 5 | ON_NEXT_RESTART(1), 6 | ON_NEXT_RESUME(2), 7 | ON_NEXT_SUSPEND(3); 8 | 9 | private final int value; 10 | CodePushInstallMode(int value) { 11 | this.value = value; 12 | } 13 | public int getValue() { 14 | return this.value; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /android/app/src/main/java/com/appzung/codepush/react/CodePushInvalidPublicKeyException.java: -------------------------------------------------------------------------------- 1 | package com.appzung.codepush.react; 2 | 3 | class CodePushInvalidPublicKeyException extends RuntimeException { 4 | 5 | public CodePushInvalidPublicKeyException(String message, Throwable cause) { 6 | super(message, cause); 7 | } 8 | 9 | public CodePushInvalidPublicKeyException(String message) { 10 | super(message); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /android/app/src/main/java/com/appzung/codepush/react/CodePushInvalidUpdateException.java: -------------------------------------------------------------------------------- 1 | package com.appzung.codepush.react; 2 | 3 | public class CodePushInvalidUpdateException extends RuntimeException { 4 | public CodePushInvalidUpdateException(String message) { 5 | super(message); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /android/app/src/main/java/com/appzung/codepush/react/CodePushMalformedDataException.java: -------------------------------------------------------------------------------- 1 | package com.appzung.codepush.react; 2 | 3 | import java.net.MalformedURLException; 4 | 5 | public class CodePushMalformedDataException extends RuntimeException { 6 | public CodePushMalformedDataException(String path, Throwable cause) { 7 | super("Unable to parse contents of " + path + ", the file may be corrupted.", cause); 8 | } 9 | public CodePushMalformedDataException(String url, MalformedURLException cause) { 10 | super("The package has an invalid downloadUrl: " + url, cause); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /android/app/src/main/java/com/appzung/codepush/react/CodePushNotInitializedException.java: -------------------------------------------------------------------------------- 1 | package com.appzung.codepush.react; 2 | 3 | public final class CodePushNotInitializedException extends RuntimeException { 4 | 5 | public CodePushNotInitializedException(String message, Throwable cause) { 6 | super(message, cause); 7 | } 8 | 9 | public CodePushNotInitializedException(String message) { 10 | super(message); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /android/app/src/main/java/com/appzung/codepush/react/CodePushUnknownException.java: -------------------------------------------------------------------------------- 1 | package com.appzung.codepush.react; 2 | 3 | class CodePushUnknownException extends RuntimeException { 4 | 5 | public CodePushUnknownException(String message, Throwable cause) { 6 | super(message, cause); 7 | } 8 | 9 | public CodePushUnknownException(String message) { 10 | super(message); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /android/app/src/main/java/com/appzung/codepush/react/CodePushUpdateState.java: -------------------------------------------------------------------------------- 1 | package com.appzung.codepush.react; 2 | 3 | public enum CodePushUpdateState { 4 | RUNNING(0), 5 | PENDING(1), 6 | LATEST(2); 7 | 8 | private final int value; 9 | CodePushUpdateState(int value) { 10 | this.value = value; 11 | } 12 | public int getValue() { 13 | return this.value; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /android/app/src/main/java/com/appzung/codepush/react/DownloadProgress.java: -------------------------------------------------------------------------------- 1 | package com.appzung.codepush.react; 2 | 3 | import com.facebook.react.bridge.WritableMap; 4 | import com.facebook.react.bridge.WritableNativeMap; 5 | 6 | class DownloadProgress { 7 | private long mTotalBytes; 8 | private long mReceivedBytes; 9 | 10 | public DownloadProgress (long totalBytes, long receivedBytes){ 11 | mTotalBytes = totalBytes; 12 | mReceivedBytes = receivedBytes; 13 | } 14 | 15 | public WritableMap createWritableMap() { 16 | WritableMap map = new WritableNativeMap(); 17 | if (mTotalBytes < Integer.MAX_VALUE) { 18 | map.putInt("totalBytes", (int) mTotalBytes); 19 | map.putInt("receivedBytes", (int) mReceivedBytes); 20 | } else { 21 | map.putDouble("totalBytes", mTotalBytes); 22 | map.putDouble("receivedBytes", mReceivedBytes); 23 | } 24 | return map; 25 | } 26 | 27 | public boolean isCompleted() { 28 | return mTotalBytes == mReceivedBytes; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /android/app/src/main/java/com/appzung/codepush/react/DownloadProgressCallback.java: -------------------------------------------------------------------------------- 1 | package com.appzung.codepush.react; 2 | 3 | interface DownloadProgressCallback { 4 | void call(DownloadProgress downloadProgress); 5 | } 6 | -------------------------------------------------------------------------------- /android/app/src/main/java/com/appzung/codepush/react/ReactHostHolder.java: -------------------------------------------------------------------------------- 1 | package com.appzung.codepush.react; 2 | 3 | import com.facebook.react.ReactHost; 4 | import com.facebook.react.runtime.ReactHostDelegate; 5 | 6 | /** 7 | * Provides access to a {@link ReactHostDelegate} 8 | */ 9 | public interface ReactHostHolder { 10 | ReactHost getReactHost(); 11 | } 12 | -------------------------------------------------------------------------------- /android/app/src/main/java/com/appzung/codepush/react/ReactInstanceHolder.java: -------------------------------------------------------------------------------- 1 | package com.appzung.codepush.react; 2 | 3 | import com.facebook.react.ReactInstanceManager; 4 | 5 | /** 6 | * Provides access to a {@link ReactInstanceManager}. 7 | * 8 | * ReactNativeHost already implements this interface, if you make use of that react-native 9 | * component (just add `implements ReactInstanceHolder`). 10 | */ 11 | public interface ReactInstanceHolder { 12 | 13 | /** 14 | * Get the current {@link ReactInstanceManager} instance. May return null. 15 | */ 16 | ReactInstanceManager getReactInstanceManager(); 17 | } 18 | -------------------------------------------------------------------------------- /android/app/src/main/java/com/appzung/codepush/react/TLSSocketFactory.java: -------------------------------------------------------------------------------- 1 | package com.appzung.codepush.react; 2 | 3 | import java.io.IOException; 4 | import java.net.InetAddress; 5 | import java.net.Socket; 6 | import java.net.UnknownHostException; 7 | import java.security.KeyManagementException; 8 | import java.security.NoSuchAlgorithmException; 9 | 10 | import javax.net.ssl.SSLContext; 11 | import javax.net.ssl.SSLSocket; 12 | import javax.net.ssl.SSLSocketFactory; 13 | 14 | public class TLSSocketFactory extends SSLSocketFactory { 15 | 16 | private SSLSocketFactory delegate; 17 | 18 | public TLSSocketFactory() throws KeyManagementException, NoSuchAlgorithmException { 19 | SSLContext context = SSLContext.getInstance("TLS"); 20 | context.init(null, null, null); 21 | delegate = context.getSocketFactory(); 22 | } 23 | 24 | @Override 25 | public String[] getDefaultCipherSuites() { 26 | return delegate.getDefaultCipherSuites(); 27 | } 28 | 29 | @Override 30 | public String[] getSupportedCipherSuites() { 31 | return delegate.getSupportedCipherSuites(); 32 | } 33 | 34 | @Override 35 | public Socket createSocket() throws IOException { 36 | return enableTLSOnSocket(delegate.createSocket()); 37 | } 38 | 39 | @Override 40 | public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException { 41 | return enableTLSOnSocket(delegate.createSocket(s, host, port, autoClose)); 42 | } 43 | 44 | @Override 45 | public Socket createSocket(String host, int port) throws IOException, UnknownHostException { 46 | return enableTLSOnSocket(delegate.createSocket(host, port)); 47 | } 48 | 49 | @Override 50 | public Socket createSocket(String host, int port, InetAddress localHost, int localPort) 51 | throws IOException, UnknownHostException { 52 | return enableTLSOnSocket(delegate.createSocket(host, port, localHost, localPort)); 53 | } 54 | 55 | @Override 56 | public Socket createSocket(InetAddress host, int port) throws IOException { 57 | return enableTLSOnSocket(delegate.createSocket(host, port)); 58 | } 59 | 60 | @Override 61 | public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) 62 | throws IOException { 63 | return enableTLSOnSocket(delegate.createSocket(address, port, localAddress, localPort)); 64 | } 65 | 66 | private Socket enableTLSOnSocket(Socket socket) { 67 | if (socket != null && (socket instanceof SSLSocket)) { 68 | ((SSLSocket) socket).setEnabledProtocols(new String[] { "TLSv1.1", "TLSv1.2" }); 69 | } 70 | return socket; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | repositories { 5 | google() 6 | mavenCentral() 7 | } 8 | dependencies { 9 | classpath "com.android.tools.build:gradle:7.2.1" 10 | 11 | // NOTE: Do not place your application dependencies here; they belong 12 | // in the individual module build.gradle files 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | CodePush_minSdkVersion=16 2 | CodePush_targetSdkVersion=31 3 | CodePush_compileSdkVersion=31 4 | # CodePush_development=true # enable this when developing on the module outside a React Native app 5 | -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AppZung/react-native-code-push/b1884458f58f9e43a50469d761bde645e80ecf18/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /android/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ['module:react-native-builder-bob/babel-preset'], 3 | }; 4 | -------------------------------------------------------------------------------- /code-push-plugin-testing-framework/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "code-push-plugin-testing-framework", 3 | "version": "0.0.1", 4 | "description": "Plugin Testing Framework for CodePush Plugins", 5 | "main": "script/index.js", 6 | "scripts": { 7 | "test": "gulp" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/microsoft/code-push.git" 12 | }, 13 | "author": { 14 | "name": "Microsoft Corporation" 15 | }, 16 | "license": "MIT", 17 | "homepage": "https://microsoft.github.io/code-push", 18 | "dependencies": { 19 | "@types/uuid": "^8.3.1", 20 | "base-64": "^1.0.0", 21 | "mocha": "latest", 22 | "mocha-junit-reporter": "latest", 23 | "q": "^1.5.1", 24 | "replace": "latest", 25 | "superagent": "^6.1.0", 26 | "superagent-proxy": "^3.0.0", 27 | "uuid": "^8.3.2" 28 | }, 29 | "bugs": { 30 | "url": "https://github.com/microsoft/code-push/issues" 31 | }, 32 | "readme": "ERROR: No README data found!", 33 | "_id": "code-push-plugin-testing-framework@0.0.1", 34 | "_shasum": "6ea33a661710628af266d714949fe95f88d71f0d", 35 | "_from": "../code-push/plugin-testing-framework/bin", 36 | "_resolved": "file:../code-push/plugin-testing-framework/bin" 37 | } 38 | -------------------------------------------------------------------------------- /code-push-plugin-testing-framework/script/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var Platform = require("./platform"); 3 | exports.Platform = Platform; 4 | var PluginTestingFramework = require("./test"); 5 | exports.PluginTestingFramework = PluginTestingFramework; 6 | var projectManager_1 = require("./projectManager"); 7 | exports.ProjectManager = projectManager_1.ProjectManager; 8 | exports.setupTestRunScenario = projectManager_1.setupTestRunScenario; 9 | exports.setupUpdateScenario = projectManager_1.setupUpdateScenario; 10 | var ServerUtil = require("./serverUtil"); 11 | exports.ServerUtil = ServerUtil; 12 | var testBuilder_1 = require("./testBuilder"); 13 | exports.TestBuilder = testBuilder_1.TestBuilder; 14 | var TestConfig = require("./testConfig"); 15 | exports.TestConfig = TestConfig; 16 | var testUtil_1 = require("./testUtil"); 17 | exports.TestUtil = testUtil_1.TestUtil; 18 | -------------------------------------------------------------------------------- /code-push-plugin-testing-framework/script/testConfig.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | // IMPORTS // 3 | var os = require("os"); 4 | var path = require("path"); 5 | var TestUtil_1 = require("./testUtil"); 6 | ////////////////////////////////////////////////////////////////////////////////////////// 7 | // Configuration variables. 8 | // What plugin to use, what project directories to use, etc. 9 | // COMMAND LINE OPTION NAMES, FLAGS, AND DEFAULTS 10 | var DEFAULT_TEST_RUN_DIRECTORY = path.join(os.tmpdir(), TestUtil_1.TestUtil.getPluginName(), "test-run"); 11 | var DEFAULT_UPDATES_DIRECTORY = path.join(os.tmpdir(), TestUtil_1.TestUtil.getPluginName(), "updates"); 12 | var DEFAULT_PLUGIN_PATH = path.join(__dirname, "../.."); 13 | var NPM_PLUGIN_PATH = TestUtil_1.TestUtil.getPluginName(); 14 | var SETUP_FLAG_NAME = "--setup"; 15 | var DEFAULT_PLUGIN_TGZ_NAME = TestUtil_1.TestUtil.getPluginName() + "-" + TestUtil_1.TestUtil.getPluginVersion() + ".tgz"; 16 | // CONST VARIABLES 17 | exports.TestAppName = "TestCodePush"; 18 | exports.TestNamespace = "com.testcodepush"; 19 | exports.AcquisitionSDKPluginName = "code-push"; 20 | exports.templatePath = path.join(__dirname, "../../test/template"); 21 | exports.thisPluginInstallString = TestUtil_1.TestUtil.resolveBooleanVariables(process.env.NPM) ? `npm install ${NPM_PLUGIN_PATH}` : `npm pack ${DEFAULT_PLUGIN_PATH} && npm install ${DEFAULT_PLUGIN_TGZ_NAME} && npm link`; 22 | exports.testRunDirectory = process.env.RUN_DIR ? process.env.RUN_DIR: DEFAULT_TEST_RUN_DIRECTORY; 23 | exports.updatesDirectory = process.env.UPDATE_DIR ? process.env.UPDATE_DIR : DEFAULT_UPDATES_DIRECTORY; 24 | exports.onlyRunCoreTests = TestUtil_1.TestUtil.resolveBooleanVariables(process.env.CORE); 25 | exports.shouldSetup = TestUtil_1.TestUtil.readMochaCommandLineFlag(SETUP_FLAG_NAME); 26 | exports.restartEmulators = TestUtil_1.TestUtil.resolveBooleanVariables(process.env.CLEAN); 27 | -------------------------------------------------------------------------------- /docs/api-android.md: -------------------------------------------------------------------------------- 1 | ## Java API reference (Android) 2 | 3 | You can customize CodePush by placing these values in string resources. 4 | 5 | - **Release channel Public ID** - The default release channel's **public ID** that will be used to check updates. For example: 6 | 7 | ```xml 8 | sU0Eikse9JFCDLZmAT-_lUSwDWACrSGgTKCXyWqcE0 9 | ``` 10 | 11 | - **Public Key** - used for bundle verification in the Code Signing Feature. Please refer to [Code Signing](setup-android.md#code-signing-setup) section for more details about the Code Signing Feature. 12 | To set the public key, you should add the content of the public key to `strings.xml` with name `CodePushSigningPublicKey`. CodePush automatically gets this property and enables the Code Signing feature. For example: 13 | 14 | ```xml 15 | your-public-key 16 | ``` 17 | 18 | - **Server Url** - used for specifying CodePush Server Url (as an Enterprise customer we may setup a custom infra for your needs). 19 | The Default value: "https://codepush.appzung.com/" is overridden by adding your path to `strings.xml` with name `CodePushServerUrl`. CodePush automatically gets this property and will use this path to send requests. For example: 20 | ```xml 21 | https://codepush.yourdomain.com 22 | ``` 23 | -------------------------------------------------------------------------------- /docs/api-ios.md: -------------------------------------------------------------------------------- 1 | ## Objective-C API reference (iOS) 2 | 3 | The Objective-C API is made available by importing the `CodePush.h` header into your `AppDelegate.m` file, and consists of a single public class named `CodePush`. 4 | 5 | ### CodePush 6 | 7 | Contains static methods for retrieving the `NSURL` that represents the most recent JavaScript bundle file, and can be passed to the `RCTRootView`'s `initWithBundleURL` method when bootstrapping your app in the `AppDelegate.m` file. 8 | 9 | #### Methods 10 | 11 | - **(NSURL \*)bundleURL** - Returns the most recent JS bundle `NSURL` as described above. This method assumes that the name of the JS bundle contained within your app binary is `main.jsbundle`. 12 | 13 | - **(NSURL \*)bundleURLForResource:(NSString \*)resourceName** - Equivalent to the `bundleURL` method, but also allows customizing the name of the JS bundle that is looked for within the app binary. This is useful if you aren't naming this file `main` (which is the default convention). This method assumes that the JS bundle's extension is `*.jsbundle`. 14 | 15 | - **(NSURL \*)bundleURLForResource:(NSString \*)resourceName withExtension:(NSString \*)resourceExtension**: Equivalent to the `bundleURLForResource:` method, but also allows customizing the extension used by the JS bundle that is looked for within the app binary. This is useful if you aren't naming this file `*.jsbundle` (which is the default convention). 16 | 17 | - **(void)overrideAppVersion:(NSString \*)appVersionOverride** - Sets the version of the application's binary interface, which would otherwise default to the App Store version specified as the `CFBundleShortVersionString` in the `Info.plist`. This should be called a single time, before the bundle URL is loaded. 18 | 19 | - **(void)setReleaseChannelPublicId:(NSString \*)releaseChannelPublicId** - Sets the release channel public ID that the app should use when querying for updates. This is a dynamic alternative to setting the release channel in your `Info.plist` and/or specifying a release channel in JS when calling `checkForUpdate` or `sync`. 20 | -------------------------------------------------------------------------------- /docs/api-js/README.md: -------------------------------------------------------------------------------- 1 | **@appzung/react-native-code-push v11.0.0-rc8** 2 | 3 | --- 4 | 5 | # @appzung/react-native-code-push v11.0.0-rc8 6 | 7 | ## Enumerations 8 | 9 | - [CheckFrequency](enumerations/CheckFrequency.md) 10 | - [DeploymentStatus](enumerations/DeploymentStatus.md) 11 | - [InstallMode](enumerations/InstallMode.md) 12 | - [LogLevel](enumerations/LogLevel.md) 13 | - [SyncStatus](enumerations/SyncStatus.md) 14 | - [UpdateState](enumerations/UpdateState.md) 15 | 16 | ## Interfaces 17 | 18 | - [CodePushOptions](interfaces/CodePushOptions.md) 19 | - [DownloadProgress](interfaces/DownloadProgress.md) 20 | - [LocalPackage](interfaces/LocalPackage.md) 21 | - [Package](interfaces/Package.md) 22 | - [RemotePackage](interfaces/RemotePackage.md) 23 | - [RollbackRetryOptions](interfaces/RollbackRetryOptions.md) 24 | - [StatusReport](interfaces/StatusReport.md) 25 | - [SyncOptions](interfaces/SyncOptions.md) 26 | - [UpdateDialog](interfaces/UpdateDialog.md) 27 | 28 | ## Type Aliases 29 | 30 | - [DownloadProgressCallback](type-aliases/DownloadProgressCallback.md) 31 | - [HandleBinaryVersionMismatchCallback](type-aliases/HandleBinaryVersionMismatchCallback.md) 32 | - [LoggerFunction](type-aliases/LoggerFunction.md) 33 | - [SyncStatusChangedCallback](type-aliases/SyncStatusChangedCallback.md) 34 | 35 | ## Variables 36 | 37 | - [DEFAULT_UPDATE_DIALOG](variables/DEFAULT_UPDATE_DIALOG.md) 38 | 39 | ## Functions 40 | 41 | - [allowRestart](functions/allowRestart.md) 42 | - [checkForUpdate](functions/checkForUpdate.md) 43 | - [clearUpdates](functions/clearUpdates.md) 44 | - [disallowRestart](functions/disallowRestart.md) 45 | - [getClientUniqueId](functions/getClientUniqueId.md) 46 | - [getDataTransmissionEnabled](functions/getDataTransmissionEnabled.md) 47 | - [getLogLevel](functions/getLogLevel.md) 48 | - [getTelemetryEnabled](functions/getTelemetryEnabled.md) 49 | - [getUpdateMetadata](functions/getUpdateMetadata.md) 50 | - [notifyAppReady](functions/notifyAppReady.md) 51 | - [resetClientUniqueId](functions/resetClientUniqueId.md) 52 | - [resetLogger](functions/resetLogger.md) 53 | - [restartApp](functions/restartApp.md) 54 | - [setDataTransmissionEnabled](functions/setDataTransmissionEnabled.md) 55 | - [setLogger](functions/setLogger.md) 56 | - [setLogLevel](functions/setLogLevel.md) 57 | - [setTelemetryEnabled](functions/setTelemetryEnabled.md) 58 | - [sync](functions/sync.md) 59 | - [withCodePush](functions/withCodePush.md) 60 | 61 | ## References 62 | 63 | ### default 64 | 65 | Renames and re-exports [withCodePush](functions/withCodePush.md) 66 | -------------------------------------------------------------------------------- /docs/api-js/enumerations/CheckFrequency.md: -------------------------------------------------------------------------------- 1 | [**@appzung/react-native-code-push v11.0.0-rc8**](../README.md) 2 | 3 | --- 4 | 5 | [@appzung/react-native-code-push](../README.md) / CheckFrequency 6 | 7 | # Enumeration: CheckFrequency 8 | 9 | Indicates when you would like to check for (and install) updates from the CodePush server. 10 | 11 | ## Enumeration Members 12 | 13 | ### MANUAL 14 | 15 | > **MANUAL**: `2` 16 | 17 | Don't automatically check for updates, but only do it when `sync()` is manually called in app code. 18 | 19 | --- 20 | 21 | ### ON_APP_RESUME 22 | 23 | > **ON_APP_RESUME**: `1` 24 | 25 | When the app re-enters the foreground after being "backgrounded" (user pressed the home button, app launches a separate payment process, etc.) 26 | 27 | --- 28 | 29 | ### ON_APP_START 30 | 31 | > **ON_APP_START**: `0` 32 | 33 | When the app is fully initialized (or more specifically, when the root component is mounted). 34 | -------------------------------------------------------------------------------- /docs/api-js/enumerations/DeploymentStatus.md: -------------------------------------------------------------------------------- 1 | [**@appzung/react-native-code-push v11.0.0-rc8**](../README.md) 2 | 3 | --- 4 | 5 | [@appzung/react-native-code-push](../README.md) / DeploymentStatus 6 | 7 | # Enumeration: DeploymentStatus 8 | 9 | Indicates the status of a deployment (after installing and restarting). 10 | 11 | ## Enumeration Members 12 | 13 | ### FAILED 14 | 15 | > **FAILED**: `"DeploymentFailed"` 16 | 17 | The deployment failed (and was rolled back). 18 | 19 | --- 20 | 21 | ### SUCCEEDED 22 | 23 | > **SUCCEEDED**: `"DeploymentSucceeded"` 24 | 25 | The deployment succeeded. 26 | -------------------------------------------------------------------------------- /docs/api-js/enumerations/InstallMode.md: -------------------------------------------------------------------------------- 1 | [**@appzung/react-native-code-push v11.0.0-rc8**](../README.md) 2 | 3 | --- 4 | 5 | [@appzung/react-native-code-push](../README.md) / InstallMode 6 | 7 | # Enumeration: InstallMode 8 | 9 | Indicates when you would like an installed update to actually be applied. 10 | 11 | ## Enumeration Members 12 | 13 | ### IMMEDIATE 14 | 15 | > **IMMEDIATE**: `number` 16 | 17 | Indicates that you want to install the update and restart the app immediately. 18 | 19 | This value is appropriate for debugging scenarios as well as when displaying an update prompt to the user, since they would expect to see the changes immediately after accepting the installation. Additionally, this mode can be used to enforce mandatory updates, since it removes the potentially undesired latency between the update installation and the next time the end user restarts or resumes the app. 20 | 21 | --- 22 | 23 | ### ON_NEXT_RESTART 24 | 25 | > **ON_NEXT_RESTART**: `number` 26 | 27 | Indicates that you want to install the update, but not forcibly restart the app. 28 | 29 | When the app is "naturally" restarted (due the OS or end user killing it), the update will be seamlessly picked up. This value is appropriate when performing silent updates, since it would likely be disruptive to the end user if the app suddenly restarted out of nowhere, since they wouldn't have realized an update was even downloaded. This is the default mode used for both the `sync` and `LocalPackage.install` methods. 30 | 31 | --- 32 | 33 | ### ON_NEXT_RESUME 34 | 35 | > **ON_NEXT_RESUME**: `number` 36 | 37 | Indicates that you want to install the update, but don't want to restart the app until the next time the end user resumes it from the background. 38 | 39 | This way, you don't disrupt their current session,but you can get the update in front of them sooner than having to wait for the next natural restart. 40 | This value is appropriate for silent installs that can be applied on resume in a non-invasive way. 41 | 42 | --- 43 | 44 | ### ON_NEXT_SUSPEND 45 | 46 | > **ON_NEXT_SUSPEND**: `number` 47 | 48 | Indicates that you want to install the update when the app is in the background, 49 | but only after it has been in the background for "minimumBackgroundDuration" seconds (0 by default), 50 | so that user context isn't lost unless the app suspension is long enough to not matter. 51 | -------------------------------------------------------------------------------- /docs/api-js/enumerations/LogLevel.md: -------------------------------------------------------------------------------- 1 | [**@appzung/react-native-code-push v11.0.0-rc8**](../README.md) 2 | 3 | --- 4 | 5 | [@appzung/react-native-code-push](../README.md) / LogLevel 6 | 7 | # Enumeration: LogLevel 8 | 9 | Used to categorize log messages by their severity and importance. 10 | 11 | ## Enumeration Members 12 | 13 | ### DEBUG 14 | 15 | > **DEBUG**: `0` 16 | 17 | --- 18 | 19 | ### ERROR 20 | 21 | > **ERROR**: `3` 22 | 23 | --- 24 | 25 | ### INFO 26 | 27 | > **INFO**: `1` 28 | 29 | --- 30 | 31 | ### WARN 32 | 33 | > **WARN**: `2` 34 | -------------------------------------------------------------------------------- /docs/api-js/enumerations/SyncStatus.md: -------------------------------------------------------------------------------- 1 | [**@appzung/react-native-code-push v11.0.0-rc8**](../README.md) 2 | 3 | --- 4 | 5 | [@appzung/react-native-code-push](../README.md) / SyncStatus 6 | 7 | # Enumeration: SyncStatus 8 | 9 | Indicates the current status of a sync operation. 10 | 11 | ## Enumeration Members 12 | 13 | ### AWAITING_USER_ACTION 14 | 15 | > **AWAITING_USER_ACTION**: `6` 16 | 17 | An update is available, and a confirmation dialog was shown 18 | to the end user. (This is only applicable when the `updateDialog` is used) 19 | 20 | --- 21 | 22 | ### CHECKING_FOR_UPDATE 23 | 24 | > **CHECKING_FOR_UPDATE**: `5` 25 | 26 | The CodePush server is being queried for an update. 27 | 28 | --- 29 | 30 | ### DOWNLOADING_PACKAGE 31 | 32 | > **DOWNLOADING_PACKAGE**: `7` 33 | 34 | An available update is being downloaded from the CodePush server. 35 | 36 | --- 37 | 38 | ### INSTALLING_UPDATE 39 | 40 | > **INSTALLING_UPDATE**: `8` 41 | 42 | An available update was downloaded and is about to be installed. 43 | 44 | --- 45 | 46 | ### SYNC_IN_PROGRESS 47 | 48 | > **SYNC_IN_PROGRESS**: `4` 49 | 50 | There is an ongoing `sync` operation running which prevents the current call from being executed. 51 | 52 | --- 53 | 54 | ### UNKNOWN_ERROR 55 | 56 | > **UNKNOWN_ERROR**: `3` 57 | 58 | The `sync` operation encountered an unknown error. 59 | 60 | --- 61 | 62 | ### UP_TO_DATE 63 | 64 | > **UP_TO_DATE**: `0` 65 | 66 | The app is fully up-to-date with the configured release channel. 67 | 68 | --- 69 | 70 | ### UPDATE_IGNORED 71 | 72 | > **UPDATE_IGNORED**: `2` 73 | 74 | The app had an optional update which the end user chose to ignore. 75 | (This is only applicable when the `updateDialog` is used) 76 | 77 | --- 78 | 79 | ### UPDATE_INSTALLED 80 | 81 | > **UPDATE_INSTALLED**: `1` 82 | 83 | An available update has been installed and will be run either immediately after the 84 | `syncStatusChangedCallback` function returns or the next time the app resumes/restarts, 85 | depending on the `InstallMode` specified in `SyncOptions` 86 | -------------------------------------------------------------------------------- /docs/api-js/enumerations/UpdateState.md: -------------------------------------------------------------------------------- 1 | [**@appzung/react-native-code-push v11.0.0-rc8**](../README.md) 2 | 3 | --- 4 | 5 | [@appzung/react-native-code-push](../README.md) / UpdateState 6 | 7 | # Enumeration: UpdateState 8 | 9 | Indicates the state that an update is currently in. 10 | 11 | ## Enumeration Members 12 | 13 | ### LATEST 14 | 15 | > **LATEST**: `number` 16 | 17 | Indicates than an update represents the latest available release, and can be either currently running or pending. 18 | 19 | --- 20 | 21 | ### PENDING 22 | 23 | > **PENDING**: `number` 24 | 25 | Indicates than an update has been installed, but the app hasn't been restarted yet in order to apply it. 26 | 27 | This can be useful for determining whether there is a pending update, which you may want to force a programmatic restart (via `restartApp`) in order to apply. 28 | 29 | --- 30 | 31 | ### RUNNING 32 | 33 | > **RUNNING**: `number` 34 | 35 | Indicates that an update represents the version of the app that is currently running. 36 | 37 | This can be useful for identifying attributes about the app, for scenarios such as displaying the release description in a "what's new?" dialog or reporting the latest version to an analytics and/or crash reporting service. 38 | -------------------------------------------------------------------------------- /docs/api-js/functions/allowRestart.md: -------------------------------------------------------------------------------- 1 | [**@appzung/react-native-code-push v11.0.0-rc8**](../README.md) 2 | 3 | --- 4 | 5 | [@appzung/react-native-code-push](../README.md) / allowRestart 6 | 7 | # Function: allowRestart() 8 | 9 | > **allowRestart**(): `Promise`\<`void`\> 10 | 11 | Allow CodePush to restart the app. 12 | 13 | This is an advanced API and is only necessary if your app explicitly disallowed restarts via the `disallowRestart` method. 14 | 15 | ## Returns 16 | 17 | `Promise`\<`void`\> 18 | -------------------------------------------------------------------------------- /docs/api-js/functions/checkForUpdate.md: -------------------------------------------------------------------------------- 1 | [**@appzung/react-native-code-push v11.0.0-rc8**](../README.md) 2 | 3 | --- 4 | 5 | [@appzung/react-native-code-push](../README.md) / checkForUpdate 6 | 7 | # Function: checkForUpdate() 8 | 9 | > **checkForUpdate**(`releaseChannelPublicId`?, `handleBinaryVersionMismatchCallback`?): `Promise`\<`null` \| [`RemotePackage`](../interfaces/RemotePackage.md)\> 10 | 11 | Asks the CodePush service whether the configured app release channel has an update available. 12 | 13 | ## Parameters 14 | 15 | ### releaseChannelPublicId? 16 | 17 | `string` 18 | 19 | The release channel public ID to use to query the CodePush server for an update. 20 | 21 | ### handleBinaryVersionMismatchCallback? 22 | 23 | [`HandleBinaryVersionMismatchCallback`](../type-aliases/HandleBinaryVersionMismatchCallback.md) 24 | 25 | An optional callback for handling target binary version mismatch 26 | 27 | ## Returns 28 | 29 | `Promise`\<`null` \| [`RemotePackage`](../interfaces/RemotePackage.md)\> 30 | -------------------------------------------------------------------------------- /docs/api-js/functions/clearUpdates.md: -------------------------------------------------------------------------------- 1 | [**@appzung/react-native-code-push v11.0.0-rc8**](../README.md) 2 | 3 | --- 4 | 5 | [@appzung/react-native-code-push](../README.md) / clearUpdates 6 | 7 | # Function: clearUpdates() 8 | 9 | > **clearUpdates**(): `void` 10 | 11 | Clears all downloaded CodePush updates. 12 | 13 | This is useful when switching to a different release channel which may have an older release than the current package. 14 | Note: we don’t recommend using this method in scenarios other than that (CodePush will call 15 | this method automatically when needed in other cases) as it could lead to unpredictable behavior. 16 | 17 | ## Returns 18 | 19 | `void` 20 | -------------------------------------------------------------------------------- /docs/api-js/functions/disallowRestart.md: -------------------------------------------------------------------------------- 1 | [**@appzung/react-native-code-push v11.0.0-rc8**](../README.md) 2 | 3 | --- 4 | 5 | [@appzung/react-native-code-push](../README.md) / disallowRestart 6 | 7 | # Function: disallowRestart() 8 | 9 | > **disallowRestart**(): `Promise`\<`void`\> 10 | 11 | Forbid CodePush to restart the app. 12 | 13 | This is an advanced API, and is useful when a component within your app (for example an onboarding process) needs to ensure that no end-user interruptions can occur during its lifetime. 14 | 15 | ## Returns 16 | 17 | `Promise`\<`void`\> 18 | -------------------------------------------------------------------------------- /docs/api-js/functions/getClientUniqueId.md: -------------------------------------------------------------------------------- 1 | [**@appzung/react-native-code-push v11.0.0-rc8**](../README.md) 2 | 3 | --- 4 | 5 | [@appzung/react-native-code-push](../README.md) / getClientUniqueId 6 | 7 | # Function: getClientUniqueId() 8 | 9 | > **getClientUniqueId**(): `Promise`\<`string`\> 10 | 11 | Gets the client's unique ID set by the module. You may also see `resetClientUniqueId`. 12 | 13 | ## Returns 14 | 15 | `Promise`\<`string`\> 16 | -------------------------------------------------------------------------------- /docs/api-js/functions/getDataTransmissionEnabled.md: -------------------------------------------------------------------------------- 1 | [**@appzung/react-native-code-push v11.0.0-rc8**](../README.md) 2 | 3 | --- 4 | 5 | [@appzung/react-native-code-push](../README.md) / getDataTransmissionEnabled 6 | 7 | # Function: getDataTransmissionEnabled() 8 | 9 | > **getDataTransmissionEnabled**(): `Promise`\<`boolean`\> 10 | 11 | Gets the current data transmission status. 12 | 13 | When setDataTransmissionEnabled has never been called, returns the default value set in your configuration. 14 | 15 | ## Returns 16 | 17 | `Promise`\<`boolean`\> 18 | -------------------------------------------------------------------------------- /docs/api-js/functions/getLogLevel.md: -------------------------------------------------------------------------------- 1 | [**@appzung/react-native-code-push v11.0.0-rc8**](../README.md) 2 | 3 | --- 4 | 5 | [@appzung/react-native-code-push](../README.md) / getLogLevel 6 | 7 | # Function: getLogLevel() 8 | 9 | > **getLogLevel**(): [`LogLevel`](../enumerations/LogLevel.md) 10 | 11 | ## Returns 12 | 13 | [`LogLevel`](../enumerations/LogLevel.md) 14 | -------------------------------------------------------------------------------- /docs/api-js/functions/getTelemetryEnabled.md: -------------------------------------------------------------------------------- 1 | [**@appzung/react-native-code-push v11.0.0-rc8**](../README.md) 2 | 3 | --- 4 | 5 | [@appzung/react-native-code-push](../README.md) / getTelemetryEnabled 6 | 7 | # Function: getTelemetryEnabled() 8 | 9 | > **getTelemetryEnabled**(): `Promise`\<`boolean`\> 10 | 11 | Gets the current telemetry enabled status. 12 | 13 | When setTelemetryEnabled has never been enabled, returns the default value set in your configuration. 14 | 15 | ## Returns 16 | 17 | `Promise`\<`boolean`\> 18 | -------------------------------------------------------------------------------- /docs/api-js/functions/getUpdateMetadata.md: -------------------------------------------------------------------------------- 1 | [**@appzung/react-native-code-push v11.0.0-rc8**](../README.md) 2 | 3 | --- 4 | 5 | [@appzung/react-native-code-push](../README.md) / getUpdateMetadata 6 | 7 | # Function: getUpdateMetadata() 8 | 9 | > **getUpdateMetadata**(`updateState`?): `Promise`\<`null` \| [`LocalPackage`](../interfaces/LocalPackage.md)\> 10 | 11 | Retrieves the metadata for an installed update (e.g. description, mandatory). 12 | 13 | ## Parameters 14 | 15 | ### updateState? 16 | 17 | [`UpdateState`](../enumerations/UpdateState.md) 18 | 19 | The state of the update you want to retrieve the metadata for. Defaults to UpdateState.RUNNING. 20 | 21 | ## Returns 22 | 23 | `Promise`\<`null` \| [`LocalPackage`](../interfaces/LocalPackage.md)\> 24 | -------------------------------------------------------------------------------- /docs/api-js/functions/notifyAppReady.md: -------------------------------------------------------------------------------- 1 | [**@appzung/react-native-code-push v11.0.0-rc8**](../README.md) 2 | 3 | --- 4 | 5 | [@appzung/react-native-code-push](../README.md) / notifyAppReady 6 | 7 | # Function: notifyAppReady() 8 | 9 | > **notifyAppReady**(): `Promise`\<`void` \| [`StatusReport`](../interfaces/StatusReport.md)\> 10 | 11 | Notifies the CodePush runtime that an installed update is considered successful. 12 | 13 | If you are manually checking for and installing updates (i.e. not using the `sync` method to handle it all for you), then this method **MUST** be called; otherwise CodePush will treat the update as failed and rollback to the previous version when the app next restarts. 14 | 15 | ## Returns 16 | 17 | `Promise`\<`void` \| [`StatusReport`](../interfaces/StatusReport.md)\> 18 | -------------------------------------------------------------------------------- /docs/api-js/functions/resetClientUniqueId.md: -------------------------------------------------------------------------------- 1 | [**@appzung/react-native-code-push v11.0.0-rc8**](../README.md) 2 | 3 | --- 4 | 5 | [@appzung/react-native-code-push](../README.md) / resetClientUniqueId 6 | 7 | # Function: resetClientUniqueId() 8 | 9 | > **resetClientUniqueId**(): `Promise`\<`string`\> 10 | 11 | Resets the client's unique ID. You may use this in some GDPR compliance scenarios. Note that this will create a new MAU if a new request is sent later. 12 | 13 | ## Returns 14 | 15 | `Promise`\<`string`\> 16 | -------------------------------------------------------------------------------- /docs/api-js/functions/resetLogger.md: -------------------------------------------------------------------------------- 1 | [**@appzung/react-native-code-push v11.0.0-rc8**](../README.md) 2 | 3 | --- 4 | 5 | [@appzung/react-native-code-push](../README.md) / resetLogger 6 | 7 | # Function: resetLogger() 8 | 9 | > **resetLogger**(): `void` 10 | 11 | Reset the logger to the default implementation 12 | 13 | ## Returns 14 | 15 | `void` 16 | -------------------------------------------------------------------------------- /docs/api-js/functions/restartApp.md: -------------------------------------------------------------------------------- 1 | [**@appzung/react-native-code-push v11.0.0-rc8**](../README.md) 2 | 3 | --- 4 | 5 | [@appzung/react-native-code-push](../README.md) / restartApp 6 | 7 | # Function: restartApp() 8 | 9 | > **restartApp**(`onlyIfUpdateIsPending`): `Promise`\<`void`\> 10 | 11 | Immediately restarts the app. 12 | 13 | If there is an update pending, it will be immediately displayed to the end user. Otherwise, calling this method simply has the same behavior as the end user killing and restarting the process. 14 | 15 | ## Parameters 16 | 17 | ### onlyIfUpdateIsPending 18 | 19 | `boolean` = `false` 20 | 21 | Indicates whether you want the restart to no-op if there isn't currently a pending update. 22 | 23 | ## Returns 24 | 25 | `Promise`\<`void`\> 26 | -------------------------------------------------------------------------------- /docs/api-js/functions/setDataTransmissionEnabled.md: -------------------------------------------------------------------------------- 1 | [**@appzung/react-native-code-push v11.0.0-rc8**](../README.md) 2 | 3 | --- 4 | 5 | [@appzung/react-native-code-push](../README.md) / setDataTransmissionEnabled 6 | 7 | # Function: setDataTransmissionEnabled() 8 | 9 | > **setDataTransmissionEnabled**(`enabled`): `Promise`\<`void`\> 10 | 11 | Controls data transmission for CodePush. This may be used for privacy optIn. 12 | 13 | ## Parameters 14 | 15 | ### enabled 16 | 17 | `boolean` 18 | 19 | When false, disables all external API calls to CodePush servers. Checking for updates will be disabled. 20 | 21 | ## Returns 22 | 23 | `Promise`\<`void`\> 24 | -------------------------------------------------------------------------------- /docs/api-js/functions/setLogLevel.md: -------------------------------------------------------------------------------- 1 | [**@appzung/react-native-code-push v11.0.0-rc8**](../README.md) 2 | 3 | --- 4 | 5 | [@appzung/react-native-code-push](../README.md) / setLogLevel 6 | 7 | # Function: setLogLevel() 8 | 9 | > **setLogLevel**(`level`): `void` 10 | 11 | ## Parameters 12 | 13 | ### level 14 | 15 | [`LogLevel`](../enumerations/LogLevel.md) 16 | 17 | ## Returns 18 | 19 | `void` 20 | -------------------------------------------------------------------------------- /docs/api-js/functions/setLogger.md: -------------------------------------------------------------------------------- 1 | [**@appzung/react-native-code-push v11.0.0-rc8**](../README.md) 2 | 3 | --- 4 | 5 | [@appzung/react-native-code-push](../README.md) / setLogger 6 | 7 | # Function: setLogger() 8 | 9 | > **setLogger**(`logger`): `void` 10 | 11 | Set a custom logger function to handle all CodePush logs 12 | 13 | ## Parameters 14 | 15 | ### logger 16 | 17 | [`LoggerFunction`](../type-aliases/LoggerFunction.md) 18 | 19 | A function that takes a log level and message and handles the logging 20 | 21 | ## Returns 22 | 23 | `void` 24 | 25 | ## Example 26 | 27 | ``` 28 | import { setLogger, LogLevel } from '@appzung/react-native-code-push'; 29 | 30 | // Custom logger that sends critical logs to a crash reporting service 31 | setLogger((level, message) => { 32 | // Always log to console 33 | console.log(`[CodePush] ${message}`); 34 | 35 | // Send error logs to crash reporting 36 | if (level === LogLevel.ERROR) { 37 | MyCrashReportingService.log(`CodePush error: ${message}`); 38 | } 39 | }); 40 | ``` 41 | -------------------------------------------------------------------------------- /docs/api-js/functions/setTelemetryEnabled.md: -------------------------------------------------------------------------------- 1 | [**@appzung/react-native-code-push v11.0.0-rc8**](../README.md) 2 | 3 | --- 4 | 5 | [@appzung/react-native-code-push](../README.md) / setTelemetryEnabled 6 | 7 | # Function: setTelemetryEnabled() 8 | 9 | > **setTelemetryEnabled**(`enabled`): `Promise`\<`void`\> 10 | 11 | Controls telemetry reporting. 12 | 13 | ## Parameters 14 | 15 | ### enabled 16 | 17 | `boolean` 18 | 19 | When false, updates on this device will stop appearing as failed, pending or succeeded in analytics. 20 | 21 | ## Returns 22 | 23 | `Promise`\<`void`\> 24 | -------------------------------------------------------------------------------- /docs/api-js/functions/sync.md: -------------------------------------------------------------------------------- 1 | [**@appzung/react-native-code-push v11.0.0-rc8**](../README.md) 2 | 3 | --- 4 | 5 | [@appzung/react-native-code-push](../README.md) / sync 6 | 7 | # Function: sync() 8 | 9 | > **sync**(`options`?, `syncStatusChangedCallback`?, `downloadProgressCallback`?, `handleBinaryVersionMismatchCallback`?): `Promise`\<[`SyncStatus`](../enumerations/SyncStatus.md)\> 10 | 11 | Allows checking for an update, downloading it and installing it, all with a single call. 12 | 13 | Unless you need custom UI and/or behavior, we recommend most developers to use this method when integrating CodePush into their apps, if they are not using the `withCodePush` HOC. 14 | 15 | ## Parameters 16 | 17 | ### options? 18 | 19 | [`SyncOptions`](../interfaces/SyncOptions.md) 20 | 21 | Options used to configure the end-user update experience (e.g. show a prompt?, install the update immediately?). 22 | 23 | ### syncStatusChangedCallback? 24 | 25 | [`SyncStatusChangedCallback`](../type-aliases/SyncStatusChangedCallback.md) 26 | 27 | An optional callback that allows tracking the status of the sync operation, as opposed to simply checking the resolved state via the returned Promise. 28 | 29 | ### downloadProgressCallback? 30 | 31 | [`DownloadProgressCallback`](../type-aliases/DownloadProgressCallback.md) 32 | 33 | An optional callback that allows tracking the progress of an update while it is being downloaded. 34 | 35 | ### handleBinaryVersionMismatchCallback? 36 | 37 | [`HandleBinaryVersionMismatchCallback`](../type-aliases/HandleBinaryVersionMismatchCallback.md) 38 | 39 | An optional callback for handling target binary version mismatch 40 | 41 | ## Returns 42 | 43 | `Promise`\<[`SyncStatus`](../enumerations/SyncStatus.md)\> 44 | -------------------------------------------------------------------------------- /docs/api-js/functions/withCodePush.md: -------------------------------------------------------------------------------- 1 | [**@appzung/react-native-code-push v11.0.0-rc8**](../README.md) 2 | 3 | --- 4 | 5 | [@appzung/react-native-code-push](../README.md) / withCodePush 6 | 7 | # Function: withCodePush() 8 | 9 | ## Call Signature 10 | 11 | > **withCodePush**\<`P`\>(`component`): `ComponentType` 12 | 13 | Wraps a React component inside a "higher order" React component that knows how to synchronize your app's JavaScript bundle and image assets when it is mounted. 14 | 15 | Internally, the higher-order component calls `sync` inside its `componentDidMount` lifecycle handle, which in turns performs an update check, downloads the update if it exists and installs the update for you. 16 | 17 | ### Type Parameters 18 | 19 | #### P 20 | 21 | `P` _extends_ `object` \| `Record`\<`string`, `unknown`\> 22 | 23 | ### Parameters 24 | 25 | #### component 26 | 27 | `ComponentType`\<`P`\> 28 | 29 | the React Component that will be decorated 30 | 31 | ### Returns 32 | 33 | `ComponentType` 34 | 35 | ## Call Signature 36 | 37 | > **withCodePush**\<`P`\>(`options`): (`component`) => `ComponentType` 38 | 39 | Wraps a React component inside a "higher order" React component that knows how to synchronize your app's JavaScript bundle and image assets when it is mounted. 40 | 41 | Internally, the higher-order component calls `sync` inside its `componentDidMount` lifecycle handle, which in turns performs an update check, downloads the update if it exists and installs the update for you. 42 | 43 | ### Type Parameters 44 | 45 | #### P 46 | 47 | `P` _extends_ `object` \| `Record`\<`string`, `unknown`\> 48 | 49 | ### Parameters 50 | 51 | #### options 52 | 53 | [`CodePushOptions`](../interfaces/CodePushOptions.md) 54 | 55 | Options used to configure the end-user sync and update experience (e.g. when to check for updates?, show a prompt?, install the update immediately?). 56 | 57 | ### Returns 58 | 59 | `Function` 60 | 61 | #### Parameters 62 | 63 | ##### component 64 | 65 | `ComponentType`\<`P`\> 66 | 67 | #### Returns 68 | 69 | `ComponentType` 70 | -------------------------------------------------------------------------------- /docs/api-js/interfaces/DownloadProgress.md: -------------------------------------------------------------------------------- 1 | [**@appzung/react-native-code-push v11.0.0-rc8**](../README.md) 2 | 3 | --- 4 | 5 | [@appzung/react-native-code-push](../README.md) / DownloadProgress 6 | 7 | # Interface: DownloadProgress 8 | 9 | ## Properties 10 | 11 | ### receivedBytes 12 | 13 | > **receivedBytes**: `number` 14 | 15 | The number of bytes downloaded thus far. 16 | 17 | --- 18 | 19 | ### totalBytes 20 | 21 | > **totalBytes**: `number` 22 | 23 | The total number of bytes expected to be received for this update. 24 | -------------------------------------------------------------------------------- /docs/api-js/interfaces/Package.md: -------------------------------------------------------------------------------- 1 | [**@appzung/react-native-code-push v11.0.0-rc8**](../README.md) 2 | 3 | --- 4 | 5 | [@appzung/react-native-code-push](../README.md) / Package 6 | 7 | # Interface: Package 8 | 9 | ## Extended by 10 | 11 | - [`LocalPackage`](LocalPackage.md) 12 | - [`RemotePackage`](RemotePackage.md) 13 | 14 | ## Properties 15 | 16 | ### appVersion 17 | 18 | > **appVersion**: `string` 19 | 20 | The app binary version that this update is dependent on. This is the value that was 21 | specified via the --target-binary-version parameter when calling the CLI's release command. 22 | 23 | --- 24 | 25 | ### description 26 | 27 | > **description**: `string` 28 | 29 | The description of the update. This is the same value that you specified in the CLI when you released the update. 30 | 31 | --- 32 | 33 | ### failedInstall 34 | 35 | > **failedInstall**: `boolean` 36 | 37 | Indicates whether this update has been previously installed but was rolled back. 38 | 39 | The `sync` method will automatically ignore updates which have previously failed, so you only need to worry about this property if using `checkForUpdate`. 40 | 41 | --- 42 | 43 | ### isFirstRun 44 | 45 | > **isFirstRun**: `boolean` 46 | 47 | Indicates whether this is the first time the update has been run after being installed. 48 | 49 | This is useful for determining whether you would like to show a "What's New?" UI to the end user after installing an update. 50 | 51 | --- 52 | 53 | ### isMandatory 54 | 55 | > **isMandatory**: `boolean` 56 | 57 | Indicates whether the update is considered mandatory. This is the value that was specified in the CLI when the update was released. 58 | 59 | --- 60 | 61 | ### isPending 62 | 63 | > **isPending**: `boolean` 64 | 65 | Indicates whether this update is in a "pending" state. When true, that means the update has been downloaded and installed, but the app restart 66 | needed to apply it hasn't occurred yet, and therefore, its changes aren't currently visible to the end-user. 67 | 68 | --- 69 | 70 | ### label 71 | 72 | > **label**: `string` 73 | 74 | The internal label automatically given to the update by the CodePush server. This value uniquely identifies the update within its release channel. 75 | 76 | --- 77 | 78 | ### packageHash 79 | 80 | > **packageHash**: `string` 81 | 82 | The SHA hash value of the update. 83 | 84 | --- 85 | 86 | ### packageSize 87 | 88 | > **packageSize**: `number` 89 | 90 | The size of the code contained within the update, in bytes. 91 | 92 | --- 93 | 94 | ### releaseChannelPublicId 95 | 96 | > **releaseChannelPublicId**: `string` 97 | 98 | The release channel public ID that was used to originally download this update. 99 | -------------------------------------------------------------------------------- /docs/api-js/interfaces/RollbackRetryOptions.md: -------------------------------------------------------------------------------- 1 | [**@appzung/react-native-code-push v11.0.0-rc8**](../README.md) 2 | 3 | --- 4 | 5 | [@appzung/react-native-code-push](../README.md) / RollbackRetryOptions 6 | 7 | # Interface: RollbackRetryOptions 8 | 9 | ## Properties 10 | 11 | ### delayInHours? 12 | 13 | > `optional` **delayInHours**: `number` 14 | 15 | Specifies the minimum time in hours that the app will wait after the latest rollback before attempting to reinstall same rolled-back package. 16 | 17 | Defaults to `24`. 18 | 19 | --- 20 | 21 | ### maxRetryAttempts? 22 | 23 | > `optional` **maxRetryAttempts**: `number` 24 | 25 | Specifies the maximum number of retry attempts that the app can make before it stops trying. 26 | Cannot be less than `1`. 27 | 28 | Defaults to `1`. 29 | -------------------------------------------------------------------------------- /docs/api-js/interfaces/StatusReport.md: -------------------------------------------------------------------------------- 1 | [**@appzung/react-native-code-push v11.0.0-rc8**](../README.md) 2 | 3 | --- 4 | 5 | [@appzung/react-native-code-push](../README.md) / StatusReport 6 | 7 | # Interface: StatusReport 8 | 9 | ## Properties 10 | 11 | ### appVersion? 12 | 13 | > `optional` **appVersion**: `string` 14 | 15 | The version of the app that was deployed (for a native app upgrade). 16 | 17 | --- 18 | 19 | ### package? 20 | 21 | > `optional` **package**: [`Package`](Package.md) 22 | 23 | Details of the package that was deployed (or attempted to). 24 | 25 | --- 26 | 27 | ### previousLabelOrAppVersion? 28 | 29 | > `optional` **previousLabelOrAppVersion**: `string` 30 | 31 | The label (v#) of the package that was upgraded from. 32 | 33 | --- 34 | 35 | ### previousReleaseChannelPublicId? 36 | 37 | > `optional` **previousReleaseChannelPublicId**: `string` 38 | 39 | Release channel used when deploying the previous package. 40 | 41 | --- 42 | 43 | ### status 44 | 45 | > **status**: [`DeploymentStatus`](../enumerations/DeploymentStatus.md) 46 | 47 | Whether the deployment succeeded or failed. 48 | -------------------------------------------------------------------------------- /docs/api-js/interfaces/UpdateDialog.md: -------------------------------------------------------------------------------- 1 | [**@appzung/react-native-code-push v11.0.0-rc8**](../README.md) 2 | 3 | --- 4 | 5 | [@appzung/react-native-code-push](../README.md) / UpdateDialog 6 | 7 | # Interface: UpdateDialog 8 | 9 | ## Properties 10 | 11 | ### appendReleaseDescription? 12 | 13 | > `optional` **appendReleaseDescription**: `boolean` 14 | 15 | Indicates whether you would like to append the description of an available release to the 16 | notification message which is displayed to the end user. 17 | 18 | Defaults to false. 19 | 20 | --- 21 | 22 | ### descriptionPrefix? 23 | 24 | > `optional` **descriptionPrefix**: `string` 25 | 26 | Indicates the string you would like to prefix the release description with, if any, when 27 | displaying the update notification to the end user. 28 | 29 | Defaults to " Description: " 30 | 31 | --- 32 | 33 | ### mandatoryContinueButtonLabel? 34 | 35 | > `optional` **mandatoryContinueButtonLabel**: `string` 36 | 37 | The text to use for the button the end user must press in order to install a mandatory update. 38 | 39 | Defaults to "Continue". 40 | 41 | --- 42 | 43 | ### mandatoryUpdateMessage? 44 | 45 | > `optional` **mandatoryUpdateMessage**: `string` 46 | 47 | The text used as the body of an update notification, when the update is specified as mandatory. 48 | 49 | Defaults to "An update is available that must be installed.". 50 | 51 | --- 52 | 53 | ### optionalIgnoreButtonLabel? 54 | 55 | > `optional` **optionalIgnoreButtonLabel**: `string` 56 | 57 | The text to use for the button the end user can press in order to ignore an optional update that is available. 58 | 59 | Defaults to "Ignore". 60 | 61 | --- 62 | 63 | ### optionalInstallButtonLabel? 64 | 65 | > `optional` **optionalInstallButtonLabel**: `string` 66 | 67 | The text to use for the button the end user can press in order to install an optional update. 68 | 69 | Defaults to "Install". 70 | 71 | --- 72 | 73 | ### optionalUpdateMessage? 74 | 75 | > `optional` **optionalUpdateMessage**: `string` 76 | 77 | The text used as the body of an update notification, when the update is optional. 78 | 79 | Defaults to "An update is available. Would you like to install it?". 80 | 81 | --- 82 | 83 | ### title? 84 | 85 | > `optional` **title**: `string` 86 | 87 | The text used as the header of an update notification that is displayed to the end user. 88 | 89 | Defaults to "Update available". 90 | -------------------------------------------------------------------------------- /docs/api-js/type-aliases/DownloadProgressCallback.md: -------------------------------------------------------------------------------- 1 | [**@appzung/react-native-code-push v11.0.0-rc8**](../README.md) 2 | 3 | --- 4 | 5 | [@appzung/react-native-code-push](../README.md) / DownloadProgressCallback 6 | 7 | # Type Alias: DownloadProgressCallback() 8 | 9 | > **DownloadProgressCallback** = (`progress`) => `void` 10 | 11 | Called periodically when an available update is being downloaded from the CodePush server. 12 | 13 | ## Parameters 14 | 15 | ### progress 16 | 17 | [`DownloadProgress`](../interfaces/DownloadProgress.md) 18 | 19 | ## Returns 20 | 21 | `void` 22 | -------------------------------------------------------------------------------- /docs/api-js/type-aliases/HandleBinaryVersionMismatchCallback.md: -------------------------------------------------------------------------------- 1 | [**@appzung/react-native-code-push v11.0.0-rc8**](../README.md) 2 | 3 | --- 4 | 5 | [@appzung/react-native-code-push](../README.md) / HandleBinaryVersionMismatchCallback 6 | 7 | # Type Alias: HandleBinaryVersionMismatchCallback() 8 | 9 | > **HandleBinaryVersionMismatchCallback** = (`update`) => `void` 10 | 11 | Called when there are any binary update available. 12 | 13 | ## Parameters 14 | 15 | ### update 16 | 17 | #### appVersion 18 | 19 | `string` 20 | 21 | ## Returns 22 | 23 | `void` 24 | -------------------------------------------------------------------------------- /docs/api-js/type-aliases/LoggerFunction.md: -------------------------------------------------------------------------------- 1 | [**@appzung/react-native-code-push v11.0.0-rc8**](../README.md) 2 | 3 | --- 4 | 5 | [@appzung/react-native-code-push](../README.md) / LoggerFunction 6 | 7 | # Type Alias: LoggerFunction() 8 | 9 | > **LoggerFunction** = (`level`, `message`) => `void` 10 | 11 | ## Parameters 12 | 13 | ### level 14 | 15 | [`LogLevel`](../enumerations/LogLevel.md) 16 | 17 | ### message 18 | 19 | `string` 20 | 21 | ## Returns 22 | 23 | `void` 24 | -------------------------------------------------------------------------------- /docs/api-js/type-aliases/SyncStatusChangedCallback.md: -------------------------------------------------------------------------------- 1 | [**@appzung/react-native-code-push v11.0.0-rc8**](../README.md) 2 | 3 | --- 4 | 5 | [@appzung/react-native-code-push](../README.md) / SyncStatusChangedCallback 6 | 7 | # Type Alias: SyncStatusChangedCallback() 8 | 9 | > **SyncStatusChangedCallback** = (`status`) => `void` 10 | 11 | Called when the sync process moves from one stage to another in the overall update process. 12 | 13 | The method is called with a status code which represents the current state, and can be any of the `SyncStatus` values. 14 | 15 | ## Parameters 16 | 17 | ### status 18 | 19 | [`SyncStatus`](../enumerations/SyncStatus.md) 20 | 21 | ## Returns 22 | 23 | `void` 24 | -------------------------------------------------------------------------------- /docs/api-js/variables/DEFAULT_UPDATE_DIALOG.md: -------------------------------------------------------------------------------- 1 | [**@appzung/react-native-code-push v11.0.0-rc8**](../README.md) 2 | 3 | --- 4 | 5 | [@appzung/react-native-code-push](../README.md) / DEFAULT_UPDATE_DIALOG 6 | 7 | # Variable: DEFAULT_UPDATE_DIALOG 8 | 9 | > `const` **DEFAULT_UPDATE_DIALOG**: [`UpdateDialog`](../interfaces/UpdateDialog.md) 10 | 11 | Represents the default settings that will be used by the sync method if 12 | an update dialog is configured to be displayed. 13 | -------------------------------------------------------------------------------- /docs/code-signing.md: -------------------------------------------------------------------------------- 1 | ## Code signing 2 | 3 | - [Configure your release process](#configure-your-release-process) 4 | - [Setup Android](#setup-android) 5 | - [Setup iOS](#setup-ios) 6 | 7 | Code signing is a security feature that helps ensure the integrity and authenticity of your app updates. 8 | It means no attacker can alter your bundled code sent to AppZung. 9 | 10 | ### Configure your release process 11 | 12 | Generate the key pair: 13 | 14 | ```shell 15 | # generate private RSA key 16 | openssl genrsa -out private_codepush_signing_key.pem 17 | # export public key 18 | openssl rsa -pubout -in private_codepush_signing_key.pem -out public_codepush_signing_key.pem 19 | ``` 20 | 21 | Store the private key securely. 22 | 23 | In the `appzung releases deploy-react-native` command that you run during your release process, add the `--private-key-path` flag pointing to the private key path. 24 | You should see `Code signing: true` in the confirmation text in interactive mode. 25 | 26 | After following the setup for your app below, if you previously sent a CodePush release without code-signing (the `--private-key-path` CLI flag), it is expected that when you check for updates CodePush doesn't present you this update, since it now expects a code signed release. Make sure when you test your integration that you sent a code-signed release. 27 | 28 | ### Setup Android 29 | 30 | Add the `CodePushSigningPublicKey` string resource in `/android/app/src/main/res/values/strings.xml`. It may look like this: 31 | 32 | ```xml 33 | 34 | my_app 35 | -----BEGIN PUBLIC KEY----- 36 | MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtPSR9lkGzZ4FR0lxF+ZA 37 | P6jJ8+Xi5L601BPN4QESoRVSrJM08roOCVrs4qoYqYJy3Of2cQWvNBEh8ti3FhHu 38 | tiuLFpNdfzM4DjAw0Ti5hOTfTixqVBXTJPYpSjDh7K6tUvp9MV0l5q/Ps3se1vud 39 | M1/X6g54lIX/QoEXTdMgR+SKXvlUIC13T7GkDHT6Z4RlwxkWkOmf2tGguRcEBL6j 40 | ww7w/3g0kWILz7nNPtXyDhIB9WLH7MKSJWdVCZm+cAqabUfpCFo7sHiyHLnUxcVY 41 | OTw3sz9ceaci7z2r8SZdsfjyjiDJrq69eWtvKVUpredy9HtyALtNuLjDITahdh8A 42 | zwIDAQAB 43 | -----END PUBLIC KEY----- 44 | 45 | ``` 46 | 47 | ### Setup iOS 48 | 49 | Add record in `Info.plist` with name `CodePushSigningPublicKey` and string value of public key content. Example: 50 | 51 | ```xml 52 | 53 | 54 | 55 | 56 | CodePushSigningPublicKey 57 | -----BEGIN PUBLIC KEY----- 58 | MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANkWYydPuyOumR/sn2agNBVDnzyRpM16NAUpYPGxNgjSEp0etkDNgzzdzyvyl+OsAGBYF3jCxYOXozum+uV5hQECAwEAAQ== 59 | -----END PUBLIC KEY----- 60 | 61 | 62 | 63 | 64 | ``` 65 | -------------------------------------------------------------------------------- /docs/migrating-to-v10.md: -------------------------------------------------------------------------------- 1 | ## Migration steps to @appzung/react-native-code-push v10+ 2 | 3 | If you are less in a hurry, you can migrate to `@appzung/react-native-code-push` v10+ where we will add new features in the future and actively support the module. 4 | 5 | ### Switch to @appzung/react-native-code-push npm package 6 | 7 | 1. Replace `react-native-code-push` in your package.json with `@appzung/react-native-code-push`: `@appzung/react-native-code-push: "^10.0.0"` 8 | 2. Run `npm install` (or `yarn` depending on your project) 9 | 10 | ### Change your JS code 11 | 12 | 1. Replace every `react-native-code-push` imports with `@appzung/react-native-code-push` imports 13 | 2. (optional) As the package is now compatible with ESM, if you call CodePush functions like `CodePush.sync()` or import types/interfaces, you may have to replace your imports `import CodePush from` to selective imports `import withCodePush, { sync, DownloadProgress } from` (or `import * as CodePush from`) 14 | 3. (optional) If you use a jest global mock, move the mock from `__mocks__/react-native-code-push.ts` to `__mocks__/@appzung/react-native-code-push.ts` 15 | 4. (optional) If you use dynamic deployment assignation, rename `deploymentKey` option to `releaseChannelPublicId` (TypeScript should catch that) 16 | 17 | ### Change your iOS setup 18 | 19 | 1. Run `bundle exec pod install` 20 | 2. Rename `CodePushDeploymentKey` to `CodePushReleaseChannelPublicId` in your `Info.plist` 21 | 3. (optional) If you already use code signing, rename `CodePushPublicKey` to `CodePushSigningPublicKey` in your `Info.plist` 22 | 23 | ### Change your Android setup 24 | 25 | 1. In `android/settings.gradle` remove the lines about CodePush : `include ':react-native-code-push'` and `project(':react-native-code-push').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-code-push/android/app')` 26 | 2. In `android/app/build.gradle` change the line about CodePush: `apply from: "../../node_modules/@appzung/react-native-code-push/android/codepush.gradle"` 27 | 3. In your Android files (eg. `MainApplication.kt`), rename every `com.microsoft.codepush` prefix imports with `com.appzung.codepush` 28 | 4. Rename `CodePushDeploymentKey` to `CodePushReleaseChannelPublicId` in your strings resources (located either at strings.xml or app/build.gradle). 29 | 5. (optional) If you already use code signing, rename `CodePushPublicKey` to `CodePushSigningPublicKey` in your strings resources 30 | 6. (optional) If you used `CodePushBuilder` to instantiate CodePush manually, it has been removed, consider using the standard way or contact us if you really need this 31 | 7. (optional) If you used a custom CodePush `packageInstance` in your `react-native.config.js` file, it is no longer possible, consider using the standard way or contact us if you really need this 32 | -------------------------------------------------------------------------------- /docs/setup-windows.md: -------------------------------------------------------------------------------- 1 | ## Windows Setup 2 | 3 | Once you've acquired the CodePush plugin, you need to integrate it into the Visual Studio project of your React Native app and configure it correctly. To do this, take the following steps: 4 | 5 | ### Plugin Installation (Windows-npx) 6 | 7 | Once the plugin has been downloaded, run `npx react-native autolink-windows` in your application's root directory to automatically add the CodePush c++ project to your application's windows solution file. 8 | 9 | ### Plugin Configuration (Windows) 10 | 11 | 1. Replace the following files located at `windows/` with those in the CodePushDemoAppCpp example app in this repo found at `Examples/CodePushDemoAppCpp/windows/CodePushDemoAppCpp`: 12 | 13 | 1. app.h 14 | 2. app.cpp 15 | 3. app.xaml 16 | 17 | 2. In the above files, replace any occurance of `CodePushDemoAppCpp` with the name of your application 18 | 19 | 3. Enter your application's app version and release channel public ID to the `configMap` object at the top of your app's `OnLaunched` method in `App.cpp`: 20 | 21 | ```c++ 22 | ... 23 | void App::OnLaunched(activation::LaunchActivatedEventArgs const& e) 24 | { 25 | winrt::Microsoft::CodePush::ReactNative::CodePushConfig::SetHost(Host()); 26 | auto configMap{ winrt::single_threaded_map() }; 27 | configMap.Insert(L"appVersion", L"1.0.0"); 28 | configMap.Insert(L"releaseChannelPublicId", L""); 29 | winrt::Microsoft::CodePush::ReactNative::CodePushConfig::Init(configMap); 30 | ... 31 | } 32 | ... 33 | ``` 34 | 35 | ### Plugin Configuration (Windows) C# 36 | 37 | 1. add name space `Microsoft.CodePush` to `App.xaml.cs` 38 | 39 | 2. add app version and release channel public ID to `configMap` at the start of your app's `OnLaunched` method in `App.xaml.cs`. 40 | 41 | ```c# 42 | using Microsoft.CodePush; 43 | 44 | ... 45 | protected override void OnLaunched(LaunchActivatedEventArgs e) 46 | { 47 | Microsoft.CodePush.ReactNative.CodePushConfig.SetHost(Host); 48 | IDictionary configMap = new Dictionary(); 49 | configMap.Add("appVersion", "1.0.0"); 50 | configMap.Add("releaseChannelPublicId", "release channel public id"); 51 | Microsoft.CodePush.ReactNative.CodePushConfig.Init(configMap); 52 | ... 53 | } 54 | ... 55 | ``` 56 | -------------------------------------------------------------------------------- /eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import { fixupConfigRules } from '@eslint/compat'; 2 | import { FlatCompat } from '@eslint/eslintrc'; 3 | import js from '@eslint/js'; 4 | import prettier from 'eslint-plugin-prettier'; 5 | import { defineConfig } from 'eslint/config'; 6 | import path from 'node:path'; 7 | import { fileURLToPath } from 'node:url'; 8 | 9 | const __filename = fileURLToPath(import.meta.url); 10 | const __dirname = path.dirname(__filename); 11 | const compat = new FlatCompat({ 12 | baseDirectory: __dirname, 13 | recommendedConfig: js.configs.recommended, 14 | allConfig: js.configs.all, 15 | }); 16 | 17 | export default defineConfig([ 18 | { 19 | extends: fixupConfigRules(compat.extends('@react-native', 'prettier')), 20 | plugins: { prettier }, 21 | rules: { 22 | 'react/react-in-jsx-scope': 'off', 23 | 'prettier/prettier': 'error', 24 | }, 25 | }, 26 | { 27 | ignores: ['node_modules/', 'lib/', 'test', 'Examples', 'code-push-plugin-testing-framework'], 28 | }, 29 | ]); 30 | -------------------------------------------------------------------------------- /ios/CodePush.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ios/CodePush.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/CodePush/CodePushErrorUtils.m: -------------------------------------------------------------------------------- 1 | #import "CodePush.h" 2 | 3 | @implementation CodePushErrorUtils 4 | 5 | static NSString *const CodePushErrorDomain = @"CodePushError"; 6 | static const int CodePushErrorCode = -1; 7 | 8 | + (NSError *)errorWithMessage:(NSString *)errorMessage 9 | { 10 | return [NSError errorWithDomain:CodePushErrorDomain 11 | code:CodePushErrorCode 12 | userInfo:@{ NSLocalizedDescriptionKey: NSLocalizedString(errorMessage, nil) }]; 13 | } 14 | 15 | + (BOOL)isCodePushError:(NSError *)err 16 | { 17 | return err != nil && [CodePushErrorDomain isEqualToString:err.domain]; 18 | } 19 | 20 | @end -------------------------------------------------------------------------------- /ios/CodePush/CodePushUtils.m: -------------------------------------------------------------------------------- 1 | #import "CodePush.h" 2 | 3 | void CPLog(NSString *formatString, ...) { 4 | va_list args; 5 | va_start(args, formatString); 6 | NSString *prependedFormatString = [NSString stringWithFormat:@"\n[CodePush] %@", formatString]; 7 | NSLogv(prependedFormatString, args); 8 | va_end(args); 9 | } -------------------------------------------------------------------------------- /ios/CodePush/RCTConvert+CodePushInstallMode.m: -------------------------------------------------------------------------------- 1 | #import "CodePush.h" 2 | 3 | #if __has_include() 4 | #import 5 | #else 6 | #import "RCTConvert.h" 7 | #endif 8 | 9 | // Extending the RCTConvert class allows the React Native 10 | // bridge to handle args of type "CodePushInstallMode" 11 | @implementation RCTConvert (CodePushInstallMode) 12 | 13 | RCT_ENUM_CONVERTER(CodePushInstallMode, (@{ @"codePushInstallModeImmediate": @(CodePushInstallModeImmediate), 14 | @"codePushInstallModeOnNextRestart": @(CodePushInstallModeOnNextRestart), 15 | @"codePushInstallModeOnNextResume": @(CodePushInstallModeOnNextResume), 16 | @"codePushInstallModeOnNextSuspend": @(CodePushInstallModeOnNextSuspend) }), 17 | CodePushInstallModeImmediate, // Default enum value 18 | integerValue) 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /ios/CodePush/RCTConvert+CodePushUpdateState.m: -------------------------------------------------------------------------------- 1 | #import "CodePush.h" 2 | 3 | #if __has_include() 4 | #import 5 | #else 6 | #import "RCTConvert.h" 7 | #endif 8 | 9 | // Extending the RCTConvert class allows the React Native 10 | // bridge to handle args of type "CodePushUpdateState" 11 | @implementation RCTConvert (CodePushUpdateState) 12 | 13 | RCT_ENUM_CONVERTER(CodePushUpdateState, (@{ @"codePushUpdateStateRunning": @(CodePushUpdateStateRunning), 14 | @"codePushUpdateStatePending": @(CodePushUpdateStatePending), 15 | @"codePushUpdateStateLatest": @(CodePushUpdateStateLatest) 16 | }), 17 | CodePushUpdateStateRunning, // Default enum value 18 | integerValue) 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /ios/PrivacyInfo.xcprivacy: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NSPrivacyTracking 6 | 7 | NSPrivacyCollectedDataTypes 8 | 9 | NSPrivacyTrackingDomains 10 | 11 | NSPrivacyAccessedAPITypes 12 | 13 | 14 | NSPrivacyAccessedAPIType 15 | NSPrivacyAccessedAPICategoryFileTimestamp 16 | NSPrivacyAccessedAPITypeReasons 17 | 18 | 0A2A.1 19 | 20 | 21 | 22 | NSPrivacyAccessedAPIType 23 | NSPrivacyAccessedAPICategoryUserDefaults 24 | NSPrivacyAccessedAPITypeReasons 25 | 26 | CA92.1 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /react-native.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | dependency: { 3 | platforms: { 4 | android: { 5 | packageInstance: 'CodePush.getInstance(getApplicationContext())', 6 | sourceDir: './android/app', 7 | }, 8 | }, 9 | }, 10 | }; 11 | -------------------------------------------------------------------------------- /scripts/getFilesInFolder.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | var path = require('path'); 3 | 4 | // Utility function that collects the stats of every file in a directory 5 | // as well as in its subdirectories. 6 | function getFilesInFolder(folderName, fileList) { 7 | var folderFiles = fs.readdirSync(folderName); 8 | folderFiles.forEach(function (file) { 9 | var fileStats = fs.statSync(path.join(folderName, file)); 10 | if (fileStats.isDirectory()) { 11 | getFilesInFolder(path.join(folderName, file), fileList); 12 | } else { 13 | fileStats.path = path.join(folderName, file); 14 | fileList.push(fileStats); 15 | } 16 | }); 17 | } 18 | 19 | module.exports = getFilesInFolder; 20 | -------------------------------------------------------------------------------- /scripts/recordFilesBeforeBundleCommand.js: -------------------------------------------------------------------------------- 1 | /* 2 | * This script creates a snapshot of the contents in the resource directory 3 | * by creating a map with the modified time of all the files in the directory 4 | * and saving it to a temp file. This snapshot is later referenced in 5 | * "generatePackageHash.js" to figure out which files have changed or were 6 | * newly generated by the "react-native bundle" command. 7 | */ 8 | 9 | var fs = require('fs'); 10 | var path = require('path'); 11 | 12 | var getFilesInFolder = require('./getFilesInFolder'); 13 | 14 | var resourcesDir = process.argv[2]; 15 | var tempFileName = process.argv[3]; 16 | 17 | var tempFileLocalPath = path.join(require('os').tmpdir(), tempFileName); 18 | var resourceFiles = []; 19 | 20 | try { 21 | getFilesInFolder(resourcesDir, resourceFiles); 22 | } catch (error) { 23 | var targetPathNotFoundExceptionMessage = '\nResources directory path does not exist.\n'; 24 | targetPathNotFoundExceptionMessage += "Unable to find '" + resourcesDir; 25 | targetPathNotFoundExceptionMessage += "' directory. Please check version of Android Plugin for Gradle."; 26 | error.message += targetPathNotFoundExceptionMessage; 27 | throw error; 28 | } 29 | 30 | var fileToModifiedTimeMap = {}; 31 | 32 | resourceFiles.forEach(function (resourceFile) { 33 | fileToModifiedTimeMap[resourceFile.path.substring(resourcesDir.length)] = resourceFile.mtime.getTime(); 34 | }); 35 | 36 | fs.writeFile(tempFileLocalPath, JSON.stringify(fileToModifiedTimeMap), function (err) { 37 | if (err) { 38 | throw err; 39 | } 40 | }); 41 | -------------------------------------------------------------------------------- /src/allowRestart.ts: -------------------------------------------------------------------------------- 1 | import { NativeRNAppZungCodePushModule } from './internals/NativeRNAppZungCodePushModule'; 2 | 3 | /** 4 | * Allow CodePush to restart the app. 5 | * 6 | * This is an advanced API and is only necessary if your app explicitly disallowed restarts via the `disallowRestart` method. 7 | */ 8 | export function allowRestart() { 9 | return NativeRNAppZungCodePushModule.allow(); 10 | } 11 | -------------------------------------------------------------------------------- /src/clearUpdates.ts: -------------------------------------------------------------------------------- 1 | import { NativeRNAppZungCodePushModule } from './internals/NativeRNAppZungCodePushModule'; 2 | 3 | /** 4 | * Clears all downloaded CodePush updates. 5 | * 6 | * This is useful when switching to a different release channel which may have an older release than the current package. 7 | * Note: we don’t recommend using this method in scenarios other than that (CodePush will call 8 | * this method automatically when needed in other cases) as it could lead to unpredictable behavior. 9 | */ 10 | export function clearUpdates() { 11 | return NativeRNAppZungCodePushModule.clearUpdates(); 12 | } 13 | -------------------------------------------------------------------------------- /src/dataTransmission.ts: -------------------------------------------------------------------------------- 1 | import { NativeRNAppZungCodePushModule } from './internals/NativeRNAppZungCodePushModule'; 2 | import { reloadCachedConfiguration } from './internals/getConfiguration'; 3 | 4 | /** 5 | * Controls data transmission for CodePush. This may be used for privacy optIn. 6 | * 7 | * @param enabled - When false, disables all external API calls to CodePush servers. Checking for updates will be disabled. 8 | */ 9 | export async function setDataTransmissionEnabled(enabled: boolean): Promise { 10 | await NativeRNAppZungCodePushModule.setDataTransmissionEnabled(enabled); 11 | await reloadCachedConfiguration(); 12 | } 13 | 14 | /** 15 | * Gets the current data transmission status. 16 | * 17 | * When setDataTransmissionEnabled has never been called, returns the default value set in your configuration. 18 | */ 19 | export function getDataTransmissionEnabled(): Promise { 20 | return NativeRNAppZungCodePushModule.getDataTransmissionEnabled(); 21 | } 22 | -------------------------------------------------------------------------------- /src/disallowRestart.ts: -------------------------------------------------------------------------------- 1 | import { NativeRNAppZungCodePushModule } from './internals/NativeRNAppZungCodePushModule'; 2 | 3 | /** 4 | * Forbid CodePush to restart the app. 5 | * 6 | * This is an advanced API, and is useful when a component within your app (for example an onboarding process) needs to ensure that no end-user interruptions can occur during its lifetime. 7 | */ 8 | export function disallowRestart() { 9 | return NativeRNAppZungCodePushModule.disallow(); 10 | } 11 | -------------------------------------------------------------------------------- /src/enums/CheckFrequency.enum.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Indicates when you would like to check for (and install) updates from the CodePush server. 3 | */ 4 | export enum CheckFrequency { 5 | /** 6 | * When the app is fully initialized (or more specifically, when the root component is mounted). 7 | */ 8 | ON_APP_START, 9 | 10 | /** 11 | * When the app re-enters the foreground after being "backgrounded" (user pressed the home button, app launches a separate payment process, etc.) 12 | */ 13 | ON_APP_RESUME, 14 | 15 | /** 16 | * Don't automatically check for updates, but only do it when `sync()` is manually called in app code. 17 | */ 18 | MANUAL, 19 | } 20 | -------------------------------------------------------------------------------- /src/enums/InstallMode.enum.ts: -------------------------------------------------------------------------------- 1 | import { NativeRNAppZungCodePushModule } from '../internals/NativeRNAppZungCodePushModule'; 2 | 3 | /** 4 | * Indicates when you would like an installed update to actually be applied. 5 | */ 6 | export enum InstallMode { 7 | /** 8 | * Indicates that you want to install the update and restart the app immediately. 9 | * 10 | * This value is appropriate for debugging scenarios as well as when displaying an update prompt to the user, since they would expect to see the changes immediately after accepting the installation. Additionally, this mode can be used to enforce mandatory updates, since it removes the potentially undesired latency between the update installation and the next time the end user restarts or resumes the app. 11 | */ 12 | IMMEDIATE = NativeRNAppZungCodePushModule.getConstants().codePushInstallModeImmediate, 13 | 14 | /** 15 | * Indicates that you want to install the update, but not forcibly restart the app. 16 | * 17 | * When the app is "naturally" restarted (due the OS or end user killing it), the update will be seamlessly picked up. This value is appropriate when performing silent updates, since it would likely be disruptive to the end user if the app suddenly restarted out of nowhere, since they wouldn't have realized an update was even downloaded. This is the default mode used for both the `sync` and `LocalPackage.install` methods. 18 | */ 19 | ON_NEXT_RESTART = NativeRNAppZungCodePushModule.getConstants().codePushInstallModeOnNextRestart, 20 | 21 | /** 22 | * Indicates that you want to install the update, but don't want to restart the app until the next time the end user resumes it from the background. 23 | * 24 | * This way, you don't disrupt their current session,but you can get the update in front of them sooner than having to wait for the next natural restart. 25 | * This value is appropriate for silent installs that can be applied on resume in a non-invasive way. 26 | */ 27 | ON_NEXT_RESUME = NativeRNAppZungCodePushModule.getConstants().codePushInstallModeOnNextResume, 28 | 29 | /** 30 | * Indicates that you want to install the update when the app is in the background, 31 | * but only after it has been in the background for "minimumBackgroundDuration" seconds (0 by default), 32 | * so that user context isn't lost unless the app suspension is long enough to not matter. 33 | */ 34 | ON_NEXT_SUSPEND = NativeRNAppZungCodePushModule.getConstants().codePushInstallModeOnNextSuspend, 35 | } 36 | -------------------------------------------------------------------------------- /src/enums/LogLevel.enum.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Used to categorize log messages by their severity and importance. 3 | */ 4 | export enum LogLevel { 5 | DEBUG, 6 | INFO, 7 | WARN, 8 | ERROR, 9 | } 10 | -------------------------------------------------------------------------------- /src/enums/SyncStatus.enum.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Indicates the current status of a sync operation. 3 | */ 4 | export enum SyncStatus { 5 | /** 6 | * The app is fully up-to-date with the configured release channel. 7 | */ 8 | UP_TO_DATE, 9 | 10 | /** 11 | * An available update has been installed and will be run either immediately after the 12 | * `syncStatusChangedCallback` function returns or the next time the app resumes/restarts, 13 | * depending on the `InstallMode` specified in `SyncOptions` 14 | */ 15 | UPDATE_INSTALLED, 16 | 17 | /** 18 | * The app had an optional update which the end user chose to ignore. 19 | * (This is only applicable when the `updateDialog` is used) 20 | */ 21 | UPDATE_IGNORED, 22 | 23 | /** 24 | * The `sync` operation encountered an unknown error. 25 | */ 26 | UNKNOWN_ERROR, 27 | 28 | /** 29 | * There is an ongoing `sync` operation running which prevents the current call from being executed. 30 | */ 31 | SYNC_IN_PROGRESS, 32 | 33 | /** 34 | * The CodePush server is being queried for an update. 35 | */ 36 | CHECKING_FOR_UPDATE, 37 | 38 | /** 39 | * An update is available, and a confirmation dialog was shown 40 | * to the end user. (This is only applicable when the `updateDialog` is used) 41 | */ 42 | AWAITING_USER_ACTION, 43 | 44 | /** 45 | * An available update is being downloaded from the CodePush server. 46 | */ 47 | DOWNLOADING_PACKAGE, 48 | 49 | /** 50 | * An available update was downloaded and is about to be installed. 51 | */ 52 | INSTALLING_UPDATE, 53 | } 54 | -------------------------------------------------------------------------------- /src/enums/UpdateState.enum.ts: -------------------------------------------------------------------------------- 1 | import { NativeRNAppZungCodePushModule } from '../internals/NativeRNAppZungCodePushModule'; 2 | 3 | /** 4 | * Indicates the state that an update is currently in. 5 | */ 6 | export enum UpdateState { 7 | /** 8 | * Indicates that an update represents the version of the app that is currently running. 9 | * 10 | * This can be useful for identifying attributes about the app, for scenarios such as displaying the release description in a "what's new?" dialog or reporting the latest version to an analytics and/or crash reporting service. 11 | */ 12 | RUNNING = NativeRNAppZungCodePushModule.getConstants().codePushUpdateStateRunning, 13 | 14 | /** 15 | * Indicates than an update has been installed, but the app hasn't been restarted yet in order to apply it. 16 | * 17 | * This can be useful for determining whether there is a pending update, which you may want to force a programmatic restart (via `restartApp`) in order to apply. 18 | */ 19 | PENDING = NativeRNAppZungCodePushModule.getConstants().codePushUpdateStatePending, 20 | 21 | /** 22 | * Indicates than an update represents the latest available release, and can be either currently running or pending. 23 | */ 24 | LATEST = NativeRNAppZungCodePushModule.getConstants().codePushUpdateStateLatest, 25 | } 26 | -------------------------------------------------------------------------------- /src/getClientUniqueId.ts: -------------------------------------------------------------------------------- 1 | import { getConfiguration } from './internals/getConfiguration'; 2 | 3 | /** 4 | * Gets the client's unique ID set by the module. You may also see `resetClientUniqueId`. 5 | */ 6 | export const getClientUniqueId = async () => { 7 | const nativeConfig = await getConfiguration(); 8 | return nativeConfig.clientUniqueId; 9 | }; 10 | -------------------------------------------------------------------------------- /src/getUpdateMetadata.ts: -------------------------------------------------------------------------------- 1 | import { UpdateState } from './enums/UpdateState.enum'; 2 | import { LocalPackageImplementation } from './internals/LocalPackageImplementation'; 3 | import { NativeRNAppZungCodePushModule } from './internals/NativeRNAppZungCodePushModule'; 4 | import type { LocalPackage } from './types'; 5 | 6 | /** 7 | * Retrieves the metadata for an installed update (e.g. description, mandatory). 8 | * 9 | * @param updateState The state of the update you want to retrieve the metadata for. Defaults to UpdateState.RUNNING. 10 | */ 11 | export async function getUpdateMetadata(updateState?: UpdateState): Promise { 12 | const nativeUpdateMetadata = await NativeRNAppZungCodePushModule.getUpdateMetadata( 13 | updateState || UpdateState.RUNNING, 14 | ); 15 | if (!nativeUpdateMetadata) { 16 | return null; 17 | } 18 | 19 | const localPackage = new LocalPackageImplementation(nativeUpdateMetadata); 20 | localPackage.failedInstall = await NativeRNAppZungCodePushModule.isFailedUpdate(nativeUpdateMetadata.packageHash); 21 | localPackage.isFirstRun = await NativeRNAppZungCodePushModule.isFirstRun(nativeUpdateMetadata.packageHash); 22 | return localPackage; 23 | } 24 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './allowRestart'; 2 | export * from './checkForUpdates'; 3 | export * from './clearUpdates'; 4 | export * from './CodePush'; 5 | export { default } from './CodePush'; 6 | export * from './disallowRestart'; 7 | export * from './getUpdateMetadata'; 8 | export * from './notifyAppReady'; 9 | export * from './restartApp'; 10 | export * from './sync'; 11 | export * from './getClientUniqueId'; 12 | export * from './resetClientUniqueId'; 13 | export * from './logLevel'; 14 | export * from './logger'; 15 | export * from './telemetry'; 16 | export * from './dataTransmission'; 17 | 18 | export * from './types'; 19 | 20 | export * from './enums/SyncStatus.enum'; 21 | export * from './enums/InstallMode.enum'; 22 | export * from './enums/UpdateState.enum'; 23 | export { DeploymentStatus } from './internals/CodePushApiSdk.types'; 24 | export * from './enums/CheckFrequency.enum'; 25 | export * from './enums/LogLevel.enum'; 26 | -------------------------------------------------------------------------------- /src/internals/CodePushApiSdk.errors.ts: -------------------------------------------------------------------------------- 1 | export class CodePushError extends Error { 2 | constructor(message: string) { 3 | super(message); 4 | this.name = 'CodePushError'; 5 | } 6 | } 7 | 8 | export class CodePushHttpError extends CodePushError { 9 | constructor( 10 | readonly url: string, 11 | readonly statusCode: number, 12 | message: string, 13 | ) { 14 | super(message); 15 | 16 | if (statusCode === 0) { 17 | this.message = `Couldn't send request to ${url}, xhr.statusCode = 0 was returned. One of the possible reasons for that might be connection problems. Please, check your internet connection.`; 18 | } 19 | 20 | this.name = 'CodePushHttpError'; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/internals/CodePushEventEmitter.ts: -------------------------------------------------------------------------------- 1 | import { NativeEventEmitter } from 'react-native'; 2 | import { NativeRNAppZungCodePushModule } from './NativeRNAppZungCodePushModule'; 3 | 4 | export const CodePushEventEmitter = new NativeEventEmitter(NativeRNAppZungCodePushModule); 5 | -------------------------------------------------------------------------------- /src/internals/LocalPackageImplementation.ts: -------------------------------------------------------------------------------- 1 | import type { InstallMode } from '../enums/InstallMode.enum'; 2 | import type { LocalPackage } from '../types'; 3 | import { NativeRNAppZungCodePushModule } from './NativeRNAppZungCodePushModule'; 4 | 5 | export class LocalPackageImplementation implements LocalPackage { 6 | constructor(localPackageData: Omit) { 7 | Object.assign(this, localPackageData); 8 | 9 | this.install = async ( 10 | installMode = NativeRNAppZungCodePushModule.getConstants().codePushInstallModeOnNextRestart, 11 | minimumBackgroundDuration = 0, 12 | updateInstalledCallback?: () => Promise | void, 13 | ) => { 14 | const { ...localPackageCopy } = localPackageData; 15 | await NativeRNAppZungCodePushModule.installUpdate(localPackageCopy, installMode, minimumBackgroundDuration); 16 | 17 | if (installMode === NativeRNAppZungCodePushModule.getConstants().codePushInstallModeImmediate) { 18 | await updateInstalledCallback?.(); 19 | await NativeRNAppZungCodePushModule.restartApp(false); 20 | return; 21 | } 22 | 23 | await NativeRNAppZungCodePushModule.clearPendingRestart(); 24 | this.isPending = true; // Mark the package as pending since it hasn't been applied yet 25 | await updateInstalledCallback?.(); 26 | }; 27 | } 28 | 29 | appVersion!: string; 30 | description!: string; 31 | failedInstall!: boolean; 32 | isFirstRun!: boolean; 33 | isMandatory!: boolean; 34 | isPending = false; // A local package wouldn't be pending until it was installed 35 | label!: string; 36 | packageHash!: string; 37 | packageSize!: number; 38 | releaseChannelPublicId!: string; 39 | 40 | install: ( 41 | installMode?: InstallMode, 42 | minimumBackgroundDuration?: number, 43 | onUpdateInstalled?: () => Promise | void, 44 | ) => Promise; 45 | } 46 | -------------------------------------------------------------------------------- /src/internals/NativeRNAppZungCodePushModule.ts: -------------------------------------------------------------------------------- 1 | import { type Spec } from './RNAppZungCodePushModuleSpec'; 2 | 3 | export const NativeRNAppZungCodePushModule = require('react-native').NativeModules.CodePush as Spec; 4 | -------------------------------------------------------------------------------- /src/internals/RNAppZungCodePushModuleSpec.ts: -------------------------------------------------------------------------------- 1 | import { type TurboModule } from 'react-native'; 2 | import type { InstallMode } from '../enums/InstallMode.enum'; 3 | import type { UpdateState } from '../enums/UpdateState.enum'; 4 | import type { LocalPackage, RemotePackage, StatusReport } from '../types'; 5 | import type { Configuration, LatestRollbackInfo, OmitFunctions } from './types'; 6 | 7 | export interface Spec extends TurboModule { 8 | addListener: (eventName: string) => void; 9 | removeListeners: (count: number) => void; 10 | 11 | getConstants(): { 12 | codePushInstallModeImmediate: number; 13 | codePushInstallModeOnNextRestart: number; 14 | codePushInstallModeOnNextResume: number; 15 | codePushInstallModeOnNextSuspend: number; 16 | 17 | codePushUpdateStateLatest: number; 18 | codePushUpdateStatePending: number; 19 | codePushUpdateStateRunning: number; 20 | }; 21 | 22 | getConfiguration(): Promise; 23 | resetClientUniqueId(): Promise; 24 | 25 | getUpdateMetadata(updateState: UpdateState): Promise>; 26 | installUpdate( 27 | localPackage: OmitFunctions, 28 | installMode: InstallMode, 29 | minimumBackgroundDuration: number, 30 | ): Promise; 31 | downloadUpdate( 32 | remotePackage: OmitFunctions, 33 | notifyProgress: boolean, 34 | ): Promise>; 35 | 36 | restartApp(onlyIfUpdateIsPending: boolean): Promise; 37 | clearPendingRestart(): Promise; 38 | 39 | disallow(): Promise; 40 | allow(): Promise; 41 | 42 | clearUpdates(): void; 43 | 44 | notifyApplicationReady(): Promise; 45 | setLatestRollbackInfo(packageHash: string): Promise; 46 | 47 | getNewStatusReport(): Promise; 48 | recordStatusReported(statusReport: StatusReport): void; 49 | saveStatusReportForRetry(statusReport: StatusReport): void; 50 | 51 | getLatestRollbackInfo(): Promise; 52 | 53 | isFirstRun(packageHash: string): Promise; 54 | isFailedUpdate(packageHash: string): Promise; 55 | 56 | setTelemetryEnabled(enabled: boolean): Promise; 57 | getTelemetryEnabled(): Promise; 58 | 59 | setDataTransmissionEnabled(enabled: boolean): Promise; 60 | getDataTransmissionEnabled(): Promise; 61 | } 62 | -------------------------------------------------------------------------------- /src/internals/getConfiguration.ts: -------------------------------------------------------------------------------- 1 | import { NativeRNAppZungCodePushModule } from './NativeRNAppZungCodePushModule'; 2 | import type { Configuration } from './types'; 3 | 4 | let config: Configuration; 5 | 6 | export async function getConfiguration() { 7 | if (!config) { 8 | config = await NativeRNAppZungCodePushModule.getConfiguration(); 9 | } 10 | 11 | return config; 12 | } 13 | 14 | export async function reloadCachedConfiguration() { 15 | config = await NativeRNAppZungCodePushModule.getConfiguration(); 16 | } 17 | -------------------------------------------------------------------------------- /src/internals/getCurrentPackage.ts: -------------------------------------------------------------------------------- 1 | import { UpdateState } from '../enums/UpdateState.enum'; 2 | import { getUpdateMetadata } from '../getUpdateMetadata'; 3 | 4 | export async function getCurrentPackage() { 5 | return await getUpdateMetadata(UpdateState.LATEST); 6 | } 7 | -------------------------------------------------------------------------------- /src/internals/logger.ts: -------------------------------------------------------------------------------- 1 | import type { LogLevel } from '../enums/LogLevel.enum'; 2 | 3 | export type LoggerFunction = (level: LogLevel, message: string) => void; 4 | 5 | const defaultLogger: LoggerFunction = (_level: LogLevel, message: string): void => { 6 | console.log(`[CodePush] ${message}`); 7 | }; 8 | 9 | let currentLogger: LoggerFunction = defaultLogger; 10 | 11 | /** 12 | * Set a custom logger function to handle all CodePush logs 13 | * 14 | * @param logger A function that takes a log level and message and handles the logging 15 | * @example 16 | * ``` 17 | * import { setLogger, LogLevel } from '@appzung/react-native-code-push'; 18 | * 19 | * // Custom logger that sends critical logs to a crash reporting service 20 | * setLogger((level, message) => { 21 | * // Always log to console 22 | * console.log(`[CodePush] ${message}`); 23 | * 24 | * // Send error logs to crash reporting 25 | * if (level === LogLevel.ERROR) { 26 | * MyCrashReportingService.log(`CodePush error: ${message}`); 27 | * } 28 | * }); 29 | * ``` 30 | */ 31 | export const setLogger = (logger: LoggerFunction): void => { 32 | currentLogger = logger; 33 | }; 34 | 35 | /** 36 | * Get the current logger function 37 | * @returns The current logger function 38 | */ 39 | export const getLogger = (): LoggerFunction => currentLogger; 40 | 41 | /** 42 | * Reset the logger to the default implementation 43 | */ 44 | export const resetLogger = (): void => { 45 | currentLogger = defaultLogger; 46 | }; 47 | -------------------------------------------------------------------------------- /src/internals/types.ts: -------------------------------------------------------------------------------- 1 | import type { ApiSdkConfiguration } from './CodePushApiSdk.types'; 2 | 3 | export interface Configuration extends ApiSdkConfiguration { 4 | releaseChannelPublicId: string; 5 | packageHash?: string; 6 | } 7 | 8 | export interface LatestRollbackInfo { 9 | time: number; 10 | count: number; 11 | packageHash: string; 12 | } 13 | 14 | type FunctionPropertyNames = { 15 | [K in keyof T]: T[K] extends Function ? K : never; 16 | }[keyof T]; 17 | 18 | export type OmitFunctions = Omit>; 19 | -------------------------------------------------------------------------------- /src/internals/utils/fetchRetry.ts: -------------------------------------------------------------------------------- 1 | export async function fetchRetry(url: string, options: FetchRetryOptions = {}, attempt = 0): Promise { 2 | const { 3 | maxRetries = 3, 4 | initialBackoff = 1000, 5 | backoffMultiplier = 2, 6 | maxRetryDelay = 30000, 7 | ...fetchOptions 8 | } = options; 9 | 10 | try { 11 | const response = await fetch(url, fetchOptions); 12 | if (response.ok || !(response.status === 429 || response.status >= 500)) { 13 | return response; 14 | } 15 | 16 | if (attempt >= maxRetries) { 17 | return response; 18 | } 19 | 20 | const retryAfter = parseRetryAfterHeader(response); 21 | if (retryAfter && retryAfter > maxRetryDelay) { 22 | return response; 23 | } 24 | 25 | const delay = retryAfter ?? addJitter(initialBackoff * Math.pow(backoffMultiplier, attempt)); 26 | 27 | await new Promise((resolve) => setTimeout(resolve, delay)); 28 | 29 | return fetchRetry(url, options, attempt + 1); 30 | } catch (error) { 31 | if (attempt >= maxRetries) { 32 | throw error; 33 | } 34 | 35 | const delay = addJitter(initialBackoff * Math.pow(backoffMultiplier, attempt)); 36 | 37 | await new Promise((resolve) => setTimeout(resolve, delay)); 38 | 39 | return fetchRetry(url, options, attempt + 1); 40 | } 41 | } 42 | 43 | interface FetchRetryOptions extends RequestInit { 44 | maxRetries?: number; 45 | initialBackoff?: number; 46 | backoffMultiplier?: number; 47 | maxRetryDelay?: number; 48 | } 49 | 50 | function parseRetryAfterHeader(response: Response): number | null { 51 | const retryAfter = response.headers.get('Retry-After'); 52 | if (!retryAfter) { 53 | return null; 54 | } 55 | 56 | if (!isNaN(Number(retryAfter))) { 57 | return parseInt(retryAfter, 10) * 1000; 58 | } 59 | 60 | try { 61 | const retryDate = new Date(retryAfter).getTime(); 62 | const now = Date.now(); 63 | return retryDate > now ? retryDate - now : 0; 64 | } catch (e) { 65 | return null; 66 | } 67 | } 68 | 69 | function addJitter(delay: number): number { 70 | const jitterFactor = 0.5 + Math.random() * 0.5; 71 | return Math.floor(delay * jitterFactor); 72 | } 73 | -------------------------------------------------------------------------------- /src/internals/utils/log.ts: -------------------------------------------------------------------------------- 1 | import type { LogLevel } from '../../enums/LogLevel.enum'; 2 | import { getLogLevel } from '../../logLevel'; 3 | import { getLogger } from '../logger'; 4 | 5 | /* Logs messages using the configured logger */ 6 | export function log(level: LogLevel, message: string): void { 7 | const currentLogLevel = getLogLevel(); 8 | if (level < currentLogLevel) { 9 | return; 10 | } 11 | 12 | const logger = getLogger(); 13 | logger(level, message); 14 | } 15 | -------------------------------------------------------------------------------- /src/internals/utils/queryStringify.ts: -------------------------------------------------------------------------------- 1 | export function queryStringify(object: { [key: string]: any }): string { 2 | let queryString = ''; 3 | let isFirst = true; 4 | 5 | for (const property in object) { 6 | if (object.hasOwnProperty(property)) { 7 | const value = object[property]; 8 | if (value !== null && typeof value !== 'undefined') { 9 | if (!isFirst) { 10 | queryString += '&'; 11 | } 12 | 13 | queryString += encodeURIComponent(property) + '='; 14 | queryString += encodeURIComponent(value); 15 | } 16 | 17 | isFirst = false; 18 | } 19 | } 20 | 21 | return queryString; 22 | } 23 | -------------------------------------------------------------------------------- /src/internals/utils/requestFetchAdapter.ts: -------------------------------------------------------------------------------- 1 | import { LogLevel } from '../../enums/LogLevel.enum'; 2 | import type { Http } from '../CodePushApiSdk.types'; 3 | import { version } from '../version'; 4 | import { fetchRetry } from './fetchRetry'; 5 | import { log } from './log'; 6 | 7 | export const requestFetchAdapter: Http.Requester = { 8 | async request(method, url, requestBody) { 9 | const headers = { 10 | Accept: 'application/json', 11 | 'Content-Type': 'application/json', 12 | 'X-CodePush-Plugin-Name': '@appzung/react-native-code-push', 13 | 'X-CodePush-Plugin-Version': version, 14 | }; 15 | 16 | if (requestBody && typeof requestBody === 'object') { 17 | requestBody = JSON.stringify(requestBody); 18 | } 19 | 20 | const requestId = Math.round(Math.random() * 10000); 21 | log(LogLevel.DEBUG, `[${requestId}] Will fetch ${method} ${url}`); 22 | 23 | const response = await fetchRetry(url, { 24 | method, 25 | headers, 26 | body: requestBody, 27 | }); 28 | 29 | const statusCode = response.status; 30 | 31 | log(LogLevel.DEBUG, `[${requestId}] Done fetching with status code ${statusCode}`); 32 | 33 | const body = await response.text(); 34 | return { statusCode, body }; 35 | }, 36 | }; 37 | -------------------------------------------------------------------------------- /src/logLevel.ts: -------------------------------------------------------------------------------- 1 | import { LogLevel } from './enums/LogLevel.enum'; 2 | 3 | let logLevel = LogLevel.INFO; 4 | 5 | export const setLogLevel = (level: LogLevel) => { 6 | logLevel = level; 7 | }; 8 | 9 | export const getLogLevel = () => logLevel; 10 | -------------------------------------------------------------------------------- /src/logger.ts: -------------------------------------------------------------------------------- 1 | export { setLogger, resetLogger } from './internals/logger'; 2 | export type { LoggerFunction } from './internals/logger'; 3 | -------------------------------------------------------------------------------- /src/reactNative.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'react-native' { 2 | export type PlatformStatic = { 3 | OS: 'ios' | 'android' | 'windows'; 4 | }; 5 | export const Platform: PlatformStatic; 6 | 7 | export interface NativeEventSubscription { 8 | remove(): void; 9 | } 10 | export class NativeEventEmitter { 11 | constructor(nativeModule?: any); 12 | addListener(eventType: string, listener: (event: any) => void, context?: Object): NativeEventSubscription; 13 | } 14 | 15 | type AppStateStatus = string; 16 | export interface AppStateStatic { 17 | currentState: AppStateStatus; 18 | addEventListener(type: AppStateEvent, listener: (state: AppStateStatus) => void): NativeEventSubscription; 19 | } 20 | export const AppState: AppStateStatic; 21 | 22 | export interface AlertButton { 23 | text?: string; 24 | onPress?: () => void; 25 | } 26 | interface AlertStatic { 27 | alert(title: string, message?: string, buttons?: AlertButton[]): void; 28 | } 29 | export const Alert: AlertStatic; 30 | 31 | export interface TurboModule { 32 | getConstants?(): {}; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/resetClientUniqueId.ts: -------------------------------------------------------------------------------- 1 | import { NativeRNAppZungCodePushModule } from './internals/NativeRNAppZungCodePushModule'; 2 | import { reloadCachedConfiguration } from './internals/getConfiguration'; 3 | 4 | /** 5 | * Resets the client's unique ID. You may use this in some GDPR compliance scenarios. Note that this will create a new MAU if a new request is sent later. 6 | */ 7 | export const resetClientUniqueId = async () => { 8 | const newId = await NativeRNAppZungCodePushModule.resetClientUniqueId(); 9 | await reloadCachedConfiguration(); 10 | return newId; 11 | }; 12 | -------------------------------------------------------------------------------- /src/restartApp.ts: -------------------------------------------------------------------------------- 1 | import { NativeRNAppZungCodePushModule } from './internals/NativeRNAppZungCodePushModule'; 2 | 3 | /** 4 | * Immediately restarts the app. 5 | * 6 | * If there is an update pending, it will be immediately displayed to the end user. Otherwise, calling this method simply has the same behavior as the end user killing and restarting the process. 7 | * 8 | * @param onlyIfUpdateIsPending Indicates whether you want the restart to no-op if there isn't currently a pending update. 9 | */ 10 | export function restartApp(onlyIfUpdateIsPending = false) { 11 | return NativeRNAppZungCodePushModule.restartApp(onlyIfUpdateIsPending); 12 | } 13 | -------------------------------------------------------------------------------- /src/telemetry.ts: -------------------------------------------------------------------------------- 1 | import { NativeRNAppZungCodePushModule } from './internals/NativeRNAppZungCodePushModule'; 2 | import { reloadCachedConfiguration } from './internals/getConfiguration'; 3 | 4 | /** 5 | * Controls telemetry reporting. 6 | * 7 | * @param enabled - When false, updates on this device will stop appearing as failed, pending or succeeded in analytics. 8 | */ 9 | export async function setTelemetryEnabled(enabled: boolean): Promise { 10 | await NativeRNAppZungCodePushModule.setTelemetryEnabled(enabled); 11 | await reloadCachedConfiguration(); 12 | } 13 | 14 | /** 15 | * Gets the current telemetry enabled status. 16 | * 17 | * When setTelemetryEnabled has never been enabled, returns the default value set in your configuration. 18 | */ 19 | export function getTelemetryEnabled(): Promise { 20 | return NativeRNAppZungCodePushModule.getTelemetryEnabled(); 21 | } 22 | -------------------------------------------------------------------------------- /test/template/android/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | TestCodePush 3 | CODE_PUSH_ANDROID_RELEASE_CHANNEL_PUBLIC_ID 4 | CODE_PUSH_SERVER_URL 5 | 6 | -------------------------------------------------------------------------------- /test/template/ios/TestCodePush/AppDelegate.mm: -------------------------------------------------------------------------------- 1 | #import "AppDelegate.h" 2 | 3 | #import 4 | 5 | #import 6 | #import 7 | #import 8 | 9 | @implementation AppDelegate 10 | 11 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 12 | { 13 | RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions]; 14 | RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge 15 | moduleName:@"CODE_PUSH_TEST_APP_NAME" 16 | initialProperties:nil]; 17 | 18 | self.moduleName = @"TestCodePush"; 19 | // You can add your custom initial props in the dictionary below. 20 | // They will be passed down to the ViewController used by React Native. 21 | self.initialProps = @{}; 22 | 23 | return [super application:application didFinishLaunchingWithOptions:launchOptions]; 24 | } 25 | 26 | - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge 27 | { 28 | return [CodePush bundleURL]; 29 | } 30 | 31 | /// This method controls whether the `concurrentRoot`feature of React18 is turned on or off. 32 | /// 33 | /// @see: https://reactjs.org/blog/2022/03/29/react-v18.html 34 | /// @note: This requires to be rendering on Fabric (i.e. on the New Architecture). 35 | /// @return: `true` if the `concurrentRoot` feature is enabled. Otherwise, it returns `false`. 36 | - (BOOL)concurrentRootEnabled 37 | { 38 | return true; 39 | } 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /test/template/scenarios/scenarioCheckForUpdate.js: -------------------------------------------------------------------------------- 1 | var CodePushWrapper = require("../codePushWrapper.js"); 2 | 3 | module.exports = { 4 | startTest: function (testApp) { 5 | CodePushWrapper.checkForUpdate(testApp); 6 | }, 7 | 8 | getScenarioName: function () { 9 | return "Check for Update"; 10 | } 11 | }; -------------------------------------------------------------------------------- /test/template/scenarios/scenarioCheckForUpdateCustomKey.js: -------------------------------------------------------------------------------- 1 | var CodePushWrapper = require("../codePushWrapper.js"); 2 | 3 | module.exports = { 4 | startTest: function (testApp) { 5 | CodePushWrapper.checkForUpdate(testApp, undefined, undefined, "CUSTOM-RELEASE-CHANNEL-PUBLIC-ID"); 6 | }, 7 | 8 | getScenarioName: function () { 9 | return "Check for Update Custom Key"; 10 | } 11 | }; 12 | -------------------------------------------------------------------------------- /test/template/scenarios/scenarioDisallowRestartImmediate.js: -------------------------------------------------------------------------------- 1 | var CodePushWrapper = require("../codePushWrapper.js"); 2 | import CodePush from "react-native-code-push"; 3 | 4 | module.exports = { 5 | startTest: function (testApp) { 6 | CodePush.disallowRestart(); 7 | CodePushWrapper.checkAndInstall(testApp, 8 | () => { 9 | CodePush.allowRestart(); 10 | }, 11 | undefined, 12 | CodePush.InstallMode.IMMEDIATE, 13 | undefined, 14 | true 15 | ); 16 | }, 17 | 18 | getScenarioName: function () { 19 | return "disallowRestart"; 20 | } 21 | }; 22 | -------------------------------------------------------------------------------- /test/template/scenarios/scenarioDisallowRestartOnResume.js: -------------------------------------------------------------------------------- 1 | var CodePushWrapper = require("../codePushWrapper.js"); 2 | import CodePush from "react-native-code-push"; 3 | 4 | module.exports = { 5 | startTest: function (testApp) { 6 | CodePush.disallowRestart(); 7 | CodePushWrapper.checkAndInstall(testApp, 8 | undefined, 9 | undefined, 10 | CodePush.InstallMode.ON_NEXT_RESUME, 11 | undefined, 12 | true 13 | ); 14 | }, 15 | 16 | getScenarioName: function () { 17 | return "disallowRestart"; 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /test/template/scenarios/scenarioDisallowRestartOnSuspend.js: -------------------------------------------------------------------------------- 1 | var CodePushWrapper = require("../codePushWrapper.js"); 2 | import CodePush from "react-native-code-push"; 3 | 4 | module.exports = { 5 | startTest: function (testApp) { 6 | CodePush.disallowRestart(); 7 | CodePushWrapper.checkAndInstall(testApp, 8 | undefined, 9 | undefined, 10 | CodePush.InstallMode.ON_NEXT_SUSPEND, 11 | undefined, 12 | true 13 | ); 14 | }, 15 | 16 | getScenarioName: function () { 17 | return "disallowRestart"; 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /test/template/scenarios/scenarioDownloadUpdate.js: -------------------------------------------------------------------------------- 1 | var CodePushWrapper = require("../codePushWrapper.js"); 2 | 3 | module.exports = { 4 | startTest: function (testApp) { 5 | CodePushWrapper.checkForUpdate(testApp, 6 | CodePushWrapper.download.bind(undefined, testApp, undefined, undefined)); 7 | }, 8 | 9 | getScenarioName: function () { 10 | return "Download Update"; 11 | } 12 | }; -------------------------------------------------------------------------------- /test/template/scenarios/scenarioInstall.js: -------------------------------------------------------------------------------- 1 | var CodePushWrapper = require("../codePushWrapper.js"); 2 | import CodePush from "react-native-code-push"; 3 | 4 | module.exports = { 5 | startTest: function (testApp) { 6 | CodePushWrapper.checkAndInstall(testApp, undefined, undefined, CodePush.InstallMode.IMMEDIATE); 7 | }, 8 | 9 | getScenarioName: function () { 10 | return "Install"; 11 | } 12 | }; -------------------------------------------------------------------------------- /test/template/scenarios/scenarioInstallOnRestartWithRevert.js: -------------------------------------------------------------------------------- 1 | var CodePushWrapper = require("../codePushWrapper.js"); 2 | import CodePush from "react-native-code-push"; 3 | 4 | module.exports = { 5 | startTest: function (testApp) { 6 | CodePushWrapper.checkAndInstall(testApp, undefined, undefined, CodePush.InstallMode.ON_NEXT_RESTART); 7 | }, 8 | 9 | getScenarioName: function () { 10 | return "Install on Restart with Revert"; 11 | } 12 | }; -------------------------------------------------------------------------------- /test/template/scenarios/scenarioInstallOnResumeWithRevert.js: -------------------------------------------------------------------------------- 1 | var CodePushWrapper = require("../codePushWrapper.js"); 2 | import CodePush from "react-native-code-push"; 3 | 4 | module.exports = { 5 | startTest: function (testApp) { 6 | CodePushWrapper.checkAndInstall(testApp, undefined, undefined, CodePush.InstallMode.ON_NEXT_RESUME); 7 | }, 8 | 9 | getScenarioName: function () { 10 | return "Install on Resume with Revert"; 11 | } 12 | }; -------------------------------------------------------------------------------- /test/template/scenarios/scenarioInstallOnSuspendWithRevert.js: -------------------------------------------------------------------------------- 1 | var CodePushWrapper = require("../codePushWrapper.js"); 2 | import CodePush from "react-native-code-push"; 3 | 4 | module.exports = { 5 | startTest: function (testApp) { 6 | CodePushWrapper.checkAndInstall(testApp, undefined, undefined, CodePush.InstallMode.ON_NEXT_SUSPEND); 7 | }, 8 | 9 | getScenarioName: function () { 10 | return "Install on Suspend with Revert"; 11 | } 12 | }; 13 | -------------------------------------------------------------------------------- /test/template/scenarios/scenarioInstallRestart2x.js: -------------------------------------------------------------------------------- 1 | var CodePushWrapper = require("../codePushWrapper.js"); 2 | import CodePush from "react-native-code-push"; 3 | 4 | module.exports = { 5 | startTest: function (testApp) { 6 | CodePushWrapper.checkAndInstall(testApp, 7 | () => { 8 | CodePush.restartApp(); 9 | CodePush.restartApp(); 10 | } 11 | ); 12 | }, 13 | 14 | getScenarioName: function () { 15 | return "Install and Restart 2x"; 16 | } 17 | }; -------------------------------------------------------------------------------- /test/template/scenarios/scenarioInstallWithRevert.js: -------------------------------------------------------------------------------- 1 | var CodePushWrapper = require("../codePushWrapper.js"); 2 | import CodePush from "react-native-code-push"; 3 | 4 | module.exports = { 5 | startTest: function (testApp) { 6 | CodePushWrapper.checkAndInstall(testApp, undefined, undefined, CodePush.InstallMode.IMMEDIATE); 7 | }, 8 | 9 | getScenarioName: function () { 10 | return "Install with Revert"; 11 | } 12 | }; -------------------------------------------------------------------------------- /test/template/scenarios/scenarioRestart.js: -------------------------------------------------------------------------------- 1 | var CodePushWrapper = require("../codePushWrapper.js"); 2 | import CodePush from "react-native-code-push"; 3 | 4 | module.exports = { 5 | startTest: function (testApp) { 6 | testApp.sendCurrentAndPendingPackage() 7 | .then(() => { 8 | CodePushWrapper.sync(testApp, (status) => { 9 | if (status === CodePush.SyncStatus.UPDATE_INSTALLED) { 10 | testApp.sendCurrentAndPendingPackage().then(CodePush.restartApp); 11 | } 12 | }, undefined, { installMode: CodePush.InstallMode.ON_NEXT_RESTART }); 13 | }); 14 | }, 15 | 16 | getScenarioName: function () { 17 | return "Restart"; 18 | } 19 | }; -------------------------------------------------------------------------------- /test/template/scenarios/scenarioRestart2x.js: -------------------------------------------------------------------------------- 1 | var CodePushWrapper = require("../codePushWrapper.js"); 2 | import CodePush from "react-native-code-push"; 3 | 4 | module.exports = { 5 | startTest: function (testApp) { 6 | CodePush.restartApp(true); 7 | CodePushWrapper.checkAndInstall(testApp, 8 | () => { 9 | CodePush.restartApp(true); 10 | } 11 | ); 12 | }, 13 | 14 | getScenarioName: function () { 15 | return "Restart2x"; 16 | } 17 | }; -------------------------------------------------------------------------------- /test/template/scenarios/scenarioSync.js: -------------------------------------------------------------------------------- 1 | var CodePushWrapper = require("../codePushWrapper.js"); 2 | import CodePush from "react-native-code-push"; 3 | 4 | module.exports = { 5 | startTest: function (testApp) { 6 | CodePushWrapper.sync(testApp, undefined, undefined, { installMode: CodePush.InstallMode.IMMEDIATE }); 7 | }, 8 | 9 | getScenarioName: function () { 10 | return "Sync"; 11 | } 12 | }; -------------------------------------------------------------------------------- /test/template/scenarios/scenarioSync2x.js: -------------------------------------------------------------------------------- 1 | var CodePushWrapper = require("../codePushWrapper.js"); 2 | import CodePush from "react-native-code-push"; 3 | 4 | module.exports = { 5 | startTest: function (testApp) { 6 | CodePushWrapper.sync(testApp, undefined, undefined, { installMode: CodePush.InstallMode.IMMEDIATE }); 7 | CodePushWrapper.sync(testApp, undefined, undefined, { installMode: CodePush.InstallMode.IMMEDIATE }); 8 | }, 9 | 10 | getScenarioName: function () { 11 | return "Sync 2x"; 12 | } 13 | }; -------------------------------------------------------------------------------- /test/template/scenarios/scenarioSyncMandatoryDefault.js: -------------------------------------------------------------------------------- 1 | var CodePushWrapper = require("../codePushWrapper.js"); 2 | import CodePush from "react-native-code-push"; 3 | 4 | module.exports = { 5 | startTest: function (testApp) { 6 | CodePushWrapper.sync(testApp, undefined, undefined, { installMode: CodePush.InstallMode.ON_NEXT_RESTART }); 7 | }, 8 | 9 | getScenarioName: function () { 10 | return "Sync Mandatory Default"; 11 | } 12 | }; -------------------------------------------------------------------------------- /test/template/scenarios/scenarioSyncMandatoryRestart.js: -------------------------------------------------------------------------------- 1 | var CodePushWrapper = require("../codePushWrapper.js"); 2 | import CodePush from "react-native-code-push"; 3 | 4 | module.exports = { 5 | startTest: function (testApp) { 6 | CodePushWrapper.sync(testApp, undefined, undefined, 7 | { 8 | installMode: CodePush.InstallMode.IMMEDIATE, 9 | mandatoryInstallMode: CodePush.InstallMode.ON_NEXT_RESTART 10 | }); 11 | }, 12 | 13 | getScenarioName: function () { 14 | return "Sync Mandatory Restart"; 15 | } 16 | }; -------------------------------------------------------------------------------- /test/template/scenarios/scenarioSyncMandatoryResume.js: -------------------------------------------------------------------------------- 1 | var CodePushWrapper = require("../codePushWrapper.js"); 2 | import CodePush from "react-native-code-push"; 3 | 4 | module.exports = { 5 | startTest: function (testApp) { 6 | CodePushWrapper.sync(testApp, undefined, undefined, 7 | { 8 | installMode: CodePush.InstallMode.ON_NEXT_RESTART, 9 | mandatoryInstallMode: CodePush.InstallMode.ON_NEXT_RESUME 10 | }); 11 | }, 12 | 13 | getScenarioName: function () { 14 | return "Sync Mandatory Resume"; 15 | } 16 | }; -------------------------------------------------------------------------------- /test/template/scenarios/scenarioSyncMandatorySuspend.js: -------------------------------------------------------------------------------- 1 | var CodePushWrapper = require("../codePushWrapper.js"); 2 | import CodePush from "react-native-code-push"; 3 | 4 | module.exports = { 5 | startTest: function (testApp) { 6 | CodePushWrapper.sync(testApp, undefined, undefined, 7 | { 8 | installMode: CodePush.InstallMode.IMMEDIATE, 9 | mandatoryInstallMode: CodePush.InstallMode.ON_NEXT_SUSPEND 10 | }); 11 | }, 12 | 13 | getScenarioName: function () { 14 | return "Sync Mandatory Suspend"; 15 | } 16 | }; 17 | -------------------------------------------------------------------------------- /test/template/scenarios/scenarioSyncRestartDelay.js: -------------------------------------------------------------------------------- 1 | var CodePushWrapper = require("../codePushWrapper.js"); 2 | import CodePush from "react-native-code-push"; 3 | 4 | module.exports = { 5 | startTest: function (testApp) { 6 | CodePushWrapper.sync(testApp, undefined, undefined, 7 | { 8 | installMode: CodePush.InstallMode.ON_NEXT_RESTART, 9 | minimumBackgroundDuration: 15 10 | }); 11 | }, 12 | 13 | getScenarioName: function () { 14 | return "Sync Restart Delay"; 15 | } 16 | }; -------------------------------------------------------------------------------- /test/template/scenarios/scenarioSyncResume.js: -------------------------------------------------------------------------------- 1 | var CodePushWrapper = require("../codePushWrapper.js"); 2 | import CodePush from "react-native-code-push"; 3 | 4 | module.exports = { 5 | startTest: function (testApp) { 6 | CodePushWrapper.sync(testApp, undefined, undefined, 7 | { installMode: CodePush.InstallMode.ON_NEXT_RESUME }); 8 | }, 9 | 10 | getScenarioName: function () { 11 | return "Sync Resume"; 12 | } 13 | }; -------------------------------------------------------------------------------- /test/template/scenarios/scenarioSyncResumeDelay.js: -------------------------------------------------------------------------------- 1 | var CodePushWrapper = require("../codePushWrapper.js"); 2 | import CodePush from "react-native-code-push"; 3 | 4 | module.exports = { 5 | startTest: function (testApp) { 6 | CodePushWrapper.sync(testApp, undefined, undefined, 7 | { 8 | installMode: CodePush.InstallMode.ON_NEXT_RESUME, 9 | minimumBackgroundDuration: 5 10 | }); 11 | }, 12 | 13 | getScenarioName: function () { 14 | return "Sync Resume Delay"; 15 | } 16 | }; -------------------------------------------------------------------------------- /test/template/scenarios/scenarioSyncSuspend.js: -------------------------------------------------------------------------------- 1 | var CodePushWrapper = require("../codePushWrapper.js"); 2 | import CodePush from "react-native-code-push"; 3 | 4 | module.exports = { 5 | startTest: function (testApp) { 6 | CodePushWrapper.sync(testApp, undefined, undefined, 7 | { installMode: CodePush.InstallMode.ON_NEXT_SUSPEND }); 8 | }, 9 | 10 | getScenarioName: function () { 11 | return "Sync Suspend"; 12 | } 13 | }; 14 | -------------------------------------------------------------------------------- /test/template/scenarios/scenarioSyncSuspendDelay.js: -------------------------------------------------------------------------------- 1 | var CodePushWrapper = require("../codePushWrapper.js"); 2 | import CodePush from "react-native-code-push"; 3 | 4 | module.exports = { 5 | startTest: function (testApp) { 6 | CodePushWrapper.sync(testApp, undefined, undefined, 7 | { 8 | installMode: CodePush.InstallMode.ON_NEXT_SUSPEND, 9 | minimumBackgroundDuration: 5 10 | }); 11 | }, 12 | 13 | getScenarioName: function () { 14 | return "Sync Suspend Delay"; 15 | } 16 | }; 17 | -------------------------------------------------------------------------------- /test/template/scenarios/updateDeviceReady.js: -------------------------------------------------------------------------------- 1 | var CodePushWrapper = require("../codePushWrapper.js"); 2 | 3 | module.exports = { 4 | startTest: function (testApp) { 5 | testApp.readyAfterUpdate(); 6 | }, 7 | 8 | getScenarioName: function () { 9 | return "Bad Update"; 10 | } 11 | }; -------------------------------------------------------------------------------- /test/template/scenarios/updateNARConditional.js: -------------------------------------------------------------------------------- 1 | var CodePushWrapper = require("../codePushWrapper.js"); 2 | import CodePush from "react-native-code-push"; 3 | 4 | module.exports = { 5 | startTest: function (testApp) { 6 | testApp.readyAfterUpdate((responseBody) => { 7 | if (responseBody !== "SKIP_NOTIFY_APPLICATION_READY") { 8 | CodePush.notifyAppReady(); 9 | CodePushWrapper.checkAndInstall(testApp, undefined, undefined, CodePush.InstallMode.ON_NEXT_RESTART); 10 | } else { 11 | testApp.setStateAndSendMessage("Skipping notifyApplicationReady!", "SKIPPED_NOTIFY_APPLICATION_READY"); 12 | } 13 | }); 14 | }, 15 | 16 | getScenarioName: function () { 17 | return "Conditional Update"; 18 | } 19 | }; -------------------------------------------------------------------------------- /test/template/scenarios/updateNotifyApplicationReady.js: -------------------------------------------------------------------------------- 1 | var CodePushWrapper = require("../codePushWrapper.js"); 2 | import CodePush from "react-native-code-push"; 3 | 4 | module.exports = { 5 | startTest: function (testApp) { 6 | testApp.readyAfterUpdate(); 7 | CodePush.notifyAppReady(); 8 | }, 9 | 10 | getScenarioName: function () { 11 | return "Good Update"; 12 | } 13 | }; -------------------------------------------------------------------------------- /test/template/scenarios/updateSync.js: -------------------------------------------------------------------------------- 1 | var CodePushWrapper = require("../codePushWrapper.js"); 2 | 3 | module.exports = { 4 | startTest: function (testApp) { 5 | testApp.readyAfterUpdate(); 6 | CodePushWrapper.sync(testApp); 7 | }, 8 | 9 | getScenarioName: function () { 10 | return "Good Update (w/ Sync)"; 11 | } 12 | }; -------------------------------------------------------------------------------- /test/template/scenarios/updateSync2x.js: -------------------------------------------------------------------------------- 1 | var CodePushWrapper = require("../codePushWrapper.js"); 2 | 3 | module.exports = { 4 | startTest: function (testApp) { 5 | testApp.readyAfterUpdate(); 6 | CodePushWrapper.sync(testApp); 7 | CodePushWrapper.sync(testApp); 8 | }, 9 | 10 | getScenarioName: function () { 11 | return "Good Update (w/ Sync 2x)"; 12 | } 13 | }; -------------------------------------------------------------------------------- /tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig", 3 | "exclude": ["Examples", "lib", "test"] 4 | } 5 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "exclude": ["test"], 3 | "compilerOptions": { 4 | "rootDir": ".", 5 | "paths": { 6 | "@appzung/react-native-code-push": ["./src/index"] 7 | }, 8 | "allowUnreachableCode": false, 9 | "allowUnusedLabels": false, 10 | "esModuleInterop": true, 11 | "forceConsistentCasingInFileNames": true, 12 | "jsx": "react-jsx", 13 | "lib": ["ESNext"], 14 | "module": "ESNext", 15 | "moduleResolution": "Bundler", 16 | "noEmit": true, 17 | "noFallthroughCasesInSwitch": true, 18 | "noImplicitReturns": true, 19 | "noImplicitUseStrict": false, 20 | "noStrictGenericChecks": false, 21 | "noUncheckedIndexedAccess": true, 22 | "noUnusedLocals": true, 23 | "noUnusedParameters": true, 24 | "resolveJsonModule": true, 25 | "resolvePackageJsonImports": false, 26 | "skipLibCheck": true, 27 | "strict": true, 28 | "target": "ESNext", 29 | "verbatimModuleSyntax": true 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /typedoc.json: -------------------------------------------------------------------------------- 1 | { 2 | "plugin": ["typedoc-plugin-markdown"], 3 | "entryPoints": ["./src/index.ts"], 4 | "out": "./docs/api-js", 5 | "readme": "none", 6 | "formatWithPrettier": true, 7 | "includeVersion": true, 8 | "disableSources": true 9 | } 10 | -------------------------------------------------------------------------------- /windows/.npmignore: -------------------------------------------------------------------------------- 1 | # Make sure we don't publish build artifacts to NPM 2 | ARM/ 3 | Debug/ 4 | x64/ 5 | x86/ 6 | bin/ 7 | obj/ 8 | .vs/ 9 | 10 | # Don't publish settings used for developement 11 | Directory.Build.props 12 | -------------------------------------------------------------------------------- /windows/CodePush/.npmignore: -------------------------------------------------------------------------------- 1 | # Make sure we don't publish build artifacts to NPM 2 | .vs/ 3 | ARM/ 4 | ARM64/ 5 | x64/ 6 | x86/ 7 | Debug/ 8 | Release/ 9 | bin/ 10 | obj/ 11 | Generated Files/ 12 | -------------------------------------------------------------------------------- /windows/CodePush/CodePush.def: -------------------------------------------------------------------------------- 1 | EXPORTS 2 | DllCanUnloadNow = WINRT_CanUnloadNow PRIVATE 3 | DllGetActivationFactory = WINRT_GetActivationFactory PRIVATE 4 | -------------------------------------------------------------------------------- /windows/CodePush/CodePushConfig.idl: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. 2 | // Licensed under the MIT License. 3 | 4 | namespace Microsoft.CodePush.ReactNative 5 | { 6 | [webhosthidden] 7 | [default_interface] 8 | runtimeclass CodePushConfig { 9 | static void Init(IMap configMap); 10 | static void SetHost(Microsoft.ReactNative.ReactNativeHost host); 11 | }; 12 | } // namespace CppModule 13 | -------------------------------------------------------------------------------- /windows/CodePush/CodePushDownloadHandler.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. 2 | // Licensed under the MIT License. 3 | 4 | #pragma once 5 | 6 | #include "winrt/Windows.Storage.h" 7 | #include "winrt/Windows.Foundation.h" 8 | #include "winrt/Windows.Data.Json.h" 9 | #include 10 | #include 11 | 12 | namespace Microsoft::CodePush::ReactNative 13 | { 14 | struct CodePushDownloadHandler 15 | { 16 | winrt::Windows::Storage::StorageFile downloadFile; 17 | int64_t expectedContentLength; 18 | int64_t receivedContentLength; 19 | std::function progressCallback; 20 | std::wstring_view downloadUrl; 21 | 22 | CodePushDownloadHandler( 23 | winrt::Windows::Storage::StorageFile downloadFile, 24 | std::function progressCallback); 25 | 26 | // Returns true if the downloaded file is a zip file 27 | winrt::Windows::Foundation::IAsyncOperation Download(std::wstring_view url); 28 | 29 | private: 30 | static constexpr uint32_t BufferSize{ 256 * 1024 }; 31 | }; 32 | } 33 | -------------------------------------------------------------------------------- /windows/CodePush/CodePushTelemetryManager.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. 2 | // Licensed under the MIT License. 3 | 4 | #pragma once 5 | 6 | #include "winrt/Windows.Data.Json.h" 7 | #include 8 | 9 | namespace Microsoft::CodePush::ReactNative 10 | { 11 | struct CodePushTelemetryManager 12 | { 13 | static winrt::Windows::Data::Json::JsonObject GetBinaryUpdateReport(std::wstring_view appVersion); 14 | static winrt::Windows::Data::Json::JsonObject GetRetryStatusReport(); 15 | static winrt::Windows::Data::Json::JsonObject GetRollbackReport(const winrt::Windows::Data::Json::JsonObject& lastFailedPackage); 16 | static winrt::Windows::Data::Json::JsonObject GetUpdateReport(const winrt::Windows::Data::Json::JsonObject& currentPackage); 17 | static void RecordStatusReported(const winrt::Windows::Data::Json::JsonObject& statusReport); 18 | static void SaveStatusReportForRetry(const winrt::Windows::Data::Json::JsonObject& statusReport); 19 | 20 | private: 21 | static void ClearRetryStatusReport(); 22 | static std::wstring_view GetReleaseChannelPublicIdFromStatusReportIdentifier(std::wstring_view statusReportIdentifier); 23 | static winrt::hstring GetPackageStatusReportIdentifier(const winrt::Windows::Data::Json::JsonObject& package); 24 | static winrt::hstring GetPreviousStatusReportIdentifier(); 25 | static std::wstring_view GetVersionLabelFromStatusReportIdentifier(std::wstring_view statusReportIdentifier); 26 | static bool IsStatusReportIdentifierCodePushLabel(std::wstring_view statusReportIdentifier); 27 | static void SaveStatusReportedForIdentifier(std::wstring_view appVersionOrPackageIdentifier); 28 | }; 29 | } 30 | -------------------------------------------------------------------------------- /windows/CodePush/CodePushUpdateUtils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "winrt/Windows.Data.Json.h" 4 | #include "winrt/Windows.Foundation.h" 5 | #include "winrt/Windows.Storage.h" 6 | 7 | // Copyright (c) Microsoft Corporation. 8 | // Licensed under the MIT License. 9 | 10 | #include 11 | 12 | namespace Microsoft::CodePush::ReactNative 13 | { 14 | struct CodePushUpdateUtils 15 | { 16 | static constexpr std::wstring_view AssetsFolderName{ L"assets" }; 17 | static constexpr std::wstring_view BinaryHashKey{ L"CodePushBinaryHash" }; 18 | static constexpr std::wstring_view ManifestFolderPrefix{ L"CodePush" }; 19 | static constexpr std::wstring_view BundleJWTFile{ L".codepushrelease" }; 20 | 21 | static winrt::Windows::Foundation::IAsyncOperation CopyEntriesInFolderAsync( 22 | winrt::Windows::Storage::StorageFolder& sourceFolder, 23 | winrt::Windows::Storage::StorageFolder& destFolder); 24 | 25 | static winrt::Windows::Foundation::IAsyncOperation ModifiedDateStringOfFileAsync(const winrt::Windows::Storage::StorageFile& file); 26 | 27 | static winrt::Windows::Foundation::IAsyncOperation GetSignatureFileAsync( 28 | const winrt::Windows::Storage::StorageFolder& rootFolder); 29 | 30 | private: 31 | /* 32 | Ignore list for hashing 33 | */ 34 | static constexpr std::wstring_view IgnoreMacOSX{ L"__MACOSX/" }; 35 | static constexpr std::wstring_view IgnoreDSStore{ L".DS_Store" }; 36 | static constexpr std::wstring_view IgnoreCodePushMetadata{ L".codepushrelease" }; 37 | }; 38 | } 39 | -------------------------------------------------------------------------------- /windows/CodePush/CodePushUtils.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. 2 | // Licensed under the MIT License. 3 | 4 | #include "pch.h" 5 | #include "CodePushUtils.h" 6 | 7 | namespace Microsoft::CodePush::ReactNative 8 | { 9 | using namespace winrt::Windows::Storage; 10 | 11 | /*static*/ void CodePushUtils::Log(winrt::hstring message) 12 | { 13 | OutputDebugStringW(L"[CodePush] "); 14 | OutputDebugStringW(message.c_str()); 15 | OutputDebugStringW(L"\n"); 16 | } 17 | 18 | /*static*/ void CodePushUtils::Log(const winrt::hresult_error& ex) 19 | { 20 | OutputDebugStringW(L"[CodePush] Exception "); 21 | OutputDebugStringW(ex.message().c_str()); 22 | OutputDebugStringW(L"\n"); 23 | } 24 | 25 | /*static*/ void CodePushUtils::LogBundleUrl(const IStorageFile& bundle) 26 | { 27 | CodePushUtils::Log(L"Loading JS bundle from \"" + bundle.Path() + L"\""); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /windows/CodePush/CodePushUtils.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. 2 | // Licensed under the MIT License. 3 | 4 | #pragma once 5 | 6 | #include "winrt/base.h" 7 | #include "winrt/Windows.Storage.h" 8 | #include 9 | 10 | namespace Microsoft::CodePush::ReactNative 11 | { 12 | struct CodePushUtils 13 | { 14 | static void Log(winrt::hstring message); 15 | static void Log(const winrt::hresult_error& ex); 16 | static void LogBundleUrl(const winrt::Windows::Storage::IStorageFile& bundle); 17 | }; 18 | } 19 | -------------------------------------------------------------------------------- /windows/CodePush/FileUtils.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. 2 | // Licensed under the MIT License. 3 | 4 | #pragma once 5 | 6 | #include "winrt/Windows.Storage.h" 7 | #include "winrt/Windows.Foundation.h" 8 | 9 | #include 10 | #include 11 | 12 | namespace Microsoft::CodePush::ReactNative 13 | { 14 | struct FileUtils 15 | { 16 | static winrt::Windows::Foundation::IAsyncOperation CreateFileFromPathAsync( 17 | winrt::Windows::Storage::StorageFolder rootFolder, 18 | const std::filesystem::path& relativePath); 19 | 20 | static winrt::Windows::Foundation::IAsyncOperation FindFilePathAsync( 21 | const winrt::Windows::Storage::StorageFolder& rootFolder, 22 | std::wstring_view fileName); 23 | 24 | static winrt::Windows::Foundation::IAsyncAction UnzipAsync( 25 | const winrt::Windows::Storage::StorageFile& zipFile, 26 | const winrt::Windows::Storage::StorageFolder& destination); 27 | }; 28 | } 29 | -------------------------------------------------------------------------------- /windows/CodePush/PropertySheet.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /windows/CodePush/ReactPackageProvider.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "ReactPackageProvider.h" 3 | #include "ReactPackageProvider.g.cpp" 4 | 5 | #include "CodePushNativeModule.h" 6 | 7 | using namespace winrt::Microsoft::ReactNative; 8 | 9 | namespace winrt::Microsoft::CodePush::ReactNative::implementation { 10 | 11 | void ReactPackageProvider::CreatePackage(IReactPackageBuilder const &packageBuilder) noexcept { 12 | AddAttributedModules(packageBuilder); 13 | } 14 | 15 | } // namespace winrt::Microsoft::CodePush::ReactNative::implementation 16 | -------------------------------------------------------------------------------- /windows/CodePush/ReactPackageProvider.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "winrt/Microsoft.CodePush.ReactNative.h" 3 | 4 | #include "ReactPackageProvider.g.h" 5 | 6 | using namespace winrt::Microsoft::ReactNative; 7 | 8 | namespace winrt::Microsoft::CodePush::ReactNative::implementation { 9 | 10 | struct ReactPackageProvider : ReactPackageProviderT { 11 | ReactPackageProvider() = default; 12 | 13 | void CreatePackage(IReactPackageBuilder const &packageBuilder) noexcept; 14 | }; 15 | 16 | } // namespace winrt::RNFS::implementation 17 | 18 | namespace winrt::Microsoft::CodePush::ReactNative::factory_implementation { 19 | 20 | struct ReactPackageProvider : ReactPackageProviderT {}; 21 | 22 | } // namespace winrt::RNFS::factory_implementation 23 | -------------------------------------------------------------------------------- /windows/CodePush/ReactPackageProvider.idl: -------------------------------------------------------------------------------- 1 | namespace Microsoft.CodePush.ReactNative 2 | { 3 | [webhosthidden] 4 | [default_interface] 5 | runtimeclass ReactPackageProvider 6 | : Microsoft.ReactNative.IReactPackageProvider { 7 | ReactPackageProvider(); 8 | }; 9 | } // namespace CppModule 10 | -------------------------------------------------------------------------------- /windows/CodePush/miniz/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2013-2014 RAD Game Tools and Valve Software 2 | Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC 3 | 4 | All Rights Reserved. 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /windows/CodePush/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /windows/CodePush/pch.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | -------------------------------------------------------------------------------- /windows/CodePush/pch.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | -------------------------------------------------------------------------------- /windows/Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | $([MSBuild]::NormalizeDirectory('$(SolutionDir)\..\node_modules\react-native-windows\')) 6 | 7 | 8 | --------------------------------------------------------------------------------