react-native-code-push
Advanced tools
Comparing version 5.6.0 to 5.6.1
@@ -42,3 +42,3 @@ import { AcquisitionManager as Sdk } from "code-push/script/acquisition-sdk"; | ||
* to send the app version to the server, since we are interested | ||
* in any updates for current app store version, regardless of hash. | ||
* in any updates for current binary version, regardless of hash. | ||
*/ | ||
@@ -62,3 +62,3 @@ let queryPackage; | ||
* 2) The server said there is an update but it requires a newer binary version. | ||
* This would occur when end-users are running an older app store version than | ||
* This would occur when end-users are running an older binary version than | ||
* is available, and CodePush is making sure they don't get an update that | ||
@@ -65,0 +65,0 @@ * potentially wouldn't be compatible with what they are running. |
@@ -61,3 +61,3 @@ ### Java API Reference (Android) | ||
- __getBundleUrl(String bundleName)__ - Returns the path to the most recent version of your app's JS bundle file, using the specified resource name (e.g. `index.android.bundle`). This method has the same resolution behavior as the Objective-C equivalent described above. | ||
- __getBundleUrl(String bundleName)__ - Returns the path to the most recent version of your app's JS bundle file, using the specified resource name (like `index.android.bundle`). This method has the same resolution behavior as the Objective-C equivalent described above. | ||
@@ -64,0 +64,0 @@ - __getPackageFolder()__ - Returns the path to the current update folder. |
@@ -11,7 +11,7 @@ ### Objective-C API Reference (iOS) | ||
1. When an end-user installs your app from the store (e.g. `1.0.0`), they will get the JS bundle that is contained within the binary. This is the behavior you would get without using CodePush, but we make sure it doesn't break :) | ||
1. When an end-user installs your app from the store (like `1.0.0`), they will get the JS bundle that is contained within the binary. This is the behavior you would get without using CodePush, but we make sure it doesn't break :) | ||
2. As soon as you begin releasing CodePush updates, your end-users will get the JS bundle that represents the latest release for the configured deployment. This is the behavior that allows you to iterate beyond what you shipped to the store. | ||
3. As soon as you release an update to the app store (e.g. `1.1.0`), and your end-users update it, they will once again get the JS bundle that is contained within the binary. This behavior ensures that CodePush updates that targetted a previous app store version aren't used (since we don't know if they would work), and your end-users always have a working version of your app. | ||
3. As soon as you release an update to the app store (like `1.1.0`), and your end-users update it, they will once again get the JS bundle that is contained within the binary. This behavior ensures that CodePush updates that targetted a previous binary version aren't used (since we don't know if they would work), and your end-users always have a working version of your app. | ||
@@ -18,0 +18,0 @@ 4. Repeat #2 and #3 as the CodePush releases and app store releases continue on into infinity (and beyond?) |
@@ -5,3 +5,3 @@ ## API Reference | ||
1. A JavaScript module, which can be imported/required, and allows the app to interact with the service during runtime (e.g. check for updates, inspect the metadata about the currently running app update). | ||
1. A JavaScript module, which can be imported/required, and allows the app to interact with the service during runtime (for example check for updates, inspect the metadata about the currently running app update). | ||
@@ -20,7 +20,7 @@ 2. A native API (Objective-C and Java) which allows the React Native app host to bootstrap itself with the right JS bundle location. | ||
* [disallowRestart](#codepushdisallowrestart): Temporarily disallows any programmatic restarts to occur as a result of a CodePush update being installed. This is an advanced API, and is useful when a component within your app (e.g. an onboarding process) needs to ensure that no end-user interruptions can occur during its lifetime. | ||
* [disallowRestart](#codepushdisallowrestart): Temporarily disallows any programmatic restarts to occur as a result of a CodePush update being installed. 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. | ||
* [getCurrentPackage](#codepushgetcurrentpackage): Retrieves the metadata about the currently installed update (e.g. description, installation time, size). *NOTE: As of `v1.10.3-beta` of the CodePush module, this method is deprecated in favor of [`getUpdateMetadata`](#codepushgetupdatemetadata)*. | ||
* [getCurrentPackage](#codepushgetcurrentpackage): Retrieves the metadata about the currently installed update (like description, installation time, size). *NOTE: As of `v1.10.3-beta` of the CodePush module, this method is deprecated in favor of [`getUpdateMetadata`](#codepushgetupdatemetadata)*. | ||
* [getUpdateMetadata](#codepushgetupdatemetadata): Retrieves the metadata for an installed update (e.g. description, mandatory). | ||
* [getUpdateMetadata](#codepushgetupdatemetadata): Retrieves the metadata for an installed update (like description, mandatory). | ||
@@ -54,3 +54,3 @@ * [notifyAppReady](#codepushnotifyappready): Notifies the CodePush runtime that an installed update is considered successful. If you are manually checking for and installing updates (i.e. not using the [sync](#codepushsync) 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. | ||
1. **Silent sync on app start** *(the simplest, default behavior)*. Your app will automatically download available updates, and apply them the next time the app restarts (e.g. the OS or end user killed it, or the device was restarted). This way, the entire update experience is "silent" to the end user, since they don't see any update prompt and/or "synthetic" app restarts. | ||
1. **Silent sync on app start** *(the simplest, default behavior)*. Your app will automatically download available updates, and apply them the next time the app restarts (like the OS or end user killed it, or the device was restarted). This way, the entire update experience is "silent" to the end user, since they don't see any update prompt and/or "synthetic" app restarts. | ||
@@ -182,3 +182,3 @@ ```javascript | ||
If a CodePush update is currently pending, which attempted to restart the app (e.g. it used `InstallMode.IMMEDIATE`), but was blocked due to `disallowRestart` having been called, then calling `allowRestart` will result in an immediate restart. This allows the update to be applied as soon as possible, without interrupting the end user during critical workflows (e.g. an onboarding process). | ||
If a CodePush update is currently pending, which attempted to restart the app (for example it used `InstallMode.IMMEDIATE`), but was blocked due to `disallowRestart` having been called, then calling `allowRestart` will result in an immediate restart. This allows the update to be applied as soon as possible, without interrupting the end user during critical workflows (for example an onboarding process). | ||
@@ -255,3 +255,3 @@ For example, calling `allowRestart` would trigger an immediate restart if either of the three scenarios mentioned in the [`disallowRestart` docs](#codepushdisallowrestart) occured after `disallowRestart` was called. However, calling `allowRestart` wouldn't trigger a restart if the following were true: | ||
This is an advanced API, and is primarily useful when individual components within your app (e.g. an onboarding process) need to ensure that no end-user interruptions can occur during their lifetime, while continuing to allow the app to keep syncing with the CodePush server at its own pace and using whatever install modes are appropriate. This has the benefit of allowing the app to discover and download available updates as soon as possible, while also preventing any disruptions during key end-user experiences. | ||
This is an advanced API, and is primarily useful when individual components within your app (like an onboarding process) need to ensure that no end-user interruptions can occur during their lifetime, while continuing to allow the app to keep syncing with the CodePush server at its own pace and using whatever install modes are appropriate. This has the benefit of allowing the app to discover and download available updates as soon as possible, while also preventing any disruptions during key end-user experiences. | ||
@@ -291,3 +291,3 @@ As an alternative, you could also choose to simply use `InstallMode.ON_NEXT_RESTART` whenever calling `sync` (which will never attempt to programmatically restart the app), and then explicity calling `restartApp` at points in your app that you know it is "safe" to do so. `disallowRestart` provides an alternative approach to this when the code that synchronizes with the CodePush server is separate from the code/components that want to enforce a no-restart policy. | ||
Retrieves the metadata about the currently installed "package" (e.g. description, installation time). This can be useful for scenarios such as displaying a "what's new?" dialog after an update has been applied or checking whether there is a pending update that is waiting to be applied via a resume or restart. | ||
Retrieves the metadata about the currently installed "package" (like description, installation time). This can be useful for scenarios such as displaying a "what's new?" dialog after an update has been applied or checking whether there is a pending update that is waiting to be applied via a resume or restart. | ||
@@ -299,3 +299,3 @@ This method returns a `Promise` which resolves to one of two possible values: | ||
1. The end-user installed the app binary and has yet to install a CodePush update | ||
1. The end-user installed an update of the binary (e.g. from the store), which cleared away the old CodePush updates, and gave precedence back to the JS binary in the binary. | ||
1. The end-user installed an update of the binary (for example from the store), which cleared away the old CodePush updates, and gave precedence back to the JS binary in the binary. | ||
@@ -324,3 +324,3 @@ 2. A [`LocalPackage`](#localpackage) instance which represents the metadata for the currently running CodePush update. | ||
Retrieves the metadata for an installed update (e.g. description, mandatory) whose state matches the specified `updateState` parameter. This can be useful for scenarios such as displaying a "what's new?" dialog after an update has been applied or checking whether there is a pending update that is waiting to be applied via a resume or restart. For more details about the possible update states, and what they represent, refer to the [UpdateState reference](#updatestate). | ||
Retrieves the metadata for an installed update (for example description, mandatory) whose state matches the specified `updateState` parameter. This can be useful for scenarios such as displaying a "what's new?" dialog after an update has been applied or checking whether there is a pending update that is waiting to be applied via a resume or restart. For more details about the possible update states, and what they represent, refer to the [UpdateState reference](#updatestate). | ||
@@ -333,3 +333,3 @@ This method returns a `Promise` which resolves to one of two possible values: | ||
2. The end-user installed an update of the binary (e.g. from the store), which cleared away the old CodePush updates, and gave precedence back to the JS binary in the binary. Therefore, it would exhibit the same behavior as #1 | ||
2. The end-user installed an update of the binary (for example from the store), which cleared away the old CodePush updates, and gave precedence back to the JS binary in the binary. Therefore, it would exhibit the same behavior as #1 | ||
@@ -386,3 +386,3 @@ 3. The `updateState` parameter is set to `UpdateState.RUNNING`, but the app isn't currently running a CodePush update. There may be a pending update, but the app hasn't been restarted yet in order to make it active. | ||
2. You have an app-specific user event (e.g. the end user navigated back to the app's home route) that allows you to apply the update in an unobtrusive way, and potentially gets the update in front of the end user sooner then waiting until the next restart or resume. | ||
2. You have an app-specific user event (like the end user navigated back to the app's home route) that allows you to apply the update in an unobtrusive way, and potentially gets the update in front of the end user sooner then waiting until the next restart or resume. | ||
@@ -399,3 +399,3 @@ #### codePush.sync | ||
1. **Silent mode** *(the default behavior)*, which automatically downloads available updates, and applies them the next time the app restarts (e.g. the OS or end user killed it, or the device was restarted). This way, the entire update experience is "silent" to the end user, since they don't see any update prompt and/or "synthetic" app restarts. | ||
1. **Silent mode** *(the default behavior)*, which automatically downloads available updates, and applies them the next time the app restarts (for example the OS or end user killed it, or the device was restarted). This way, the entire update experience is "silent" to the end user, since they don't see any update prompt and/or "synthetic" app restarts. | ||
@@ -466,3 +466,3 @@ 2. **Active mode**, which when an update is available, prompts the end user for permission before downloading it, and then immediately applies the update. If an update was released using the `mandatory` flag, the end user would still be notified about the update, but they wouldn't have the choice to ignore it. | ||
In addition to the options, the `sync` method also accepts several optional function parameters which allow you to subscribe to the lifecycle of the `sync` "pipeline" in order to display additional UI as needed (e.g. a "checking for update modal or a download progress modal): | ||
In addition to the options, the `sync` method also accepts several optional function parameters which allow you to subscribe to the lifecycle of the `sync` "pipeline" in order to display additional UI as needed (like a "checking for update modal or a download progress modal): | ||
@@ -516,3 +516,3 @@ * __syncStatusChangedCallback__ *((syncStatus: Number) => void)* - Called when the sync process moves from one stage to another in the overall update process. The method is called with a status code which represents the current state, and can be any of the [`SyncStatus`](#syncstatus) values. | ||
The `checkForUpdate` and `getUpdateMetadata` methods return `Promise` objects, that when resolved, provide acces to "package" objects. The package represents your code update as well as any extra metadata (e.g. description, mandatory?). The CodePush API has the distinction between the following types of packages: | ||
The `checkForUpdate` and `getUpdateMetadata` methods return `Promise` objects, that when resolved, provide acces to "package" objects. The package represents your code update as well as any extra metadata (like description, mandatory?). The CodePush API has the distinction between the following types of packages: | ||
@@ -519,0 +519,0 @@ * [LocalPackage](#localpackage): Represents a downloaded update that is either already running, or has been installed and is pending an app restart. |
@@ -7,7 +7,7 @@ ### Android | ||
The [Android Gradle plugin](http://google.github.io/android-gradle-dsl/current/index.html) allows you to define custom config settings for each "build type" (e.g. debug, release), which in turn are generated as properties on the `BuildConfig` class that you can reference from your Java code. This mechanism allows you to easily configure your debug builds to use your CodePush staging deployment key and your release builds to use your CodePush production deployment key. | ||
The [Android Gradle plugin](http://google.github.io/android-gradle-dsl/current/index.html) allows you to define custom config settings for each "build type" (like debug, release), which in turn are generated as properties on the `BuildConfig` class that you can reference from your Java code. This mechanism allows you to easily configure your debug builds to use your CodePush staging deployment key and your release builds to use your CodePush production deployment key. | ||
To set this up, perform the following steps: | ||
1. Open your app's `build.gradle` file (e.g. `android/app/build.gradle` in standard React Native projects) | ||
1. Open your app's `build.gradle` file (for example `android/app/build.gradle` in standard React Native projects) | ||
@@ -30,2 +30,5 @@ 2. Find the `android { buildTypes {} }` section and define `buildConfigField` entries for both your `debug` and `release` build types, which reference your `Staging` and `Production` deployment keys respectively. If you prefer, you can define the key literals in your `gradle.properties` file, and then reference them here. Either way will work, and it's just a matter of personal preference. | ||
buildConfigField "String", "CODEPUSH_KEY", '"<INSERT_STAGING_KEY>"' | ||
// Note: It is a good idea to provide matchingFallbacks for the new buildType you create to prevent build issues | ||
// Add the following line if not already there | ||
matchingFallbacks = ['release'] | ||
... | ||
@@ -48,3 +51,3 @@ } | ||
4. Pass the deployment key to the `CodePush` constructor via the build config you just defined, as opposed to a string literal. | ||
4. Pass the deployment key to the `CodePush` constructor via the build config you defined, as opposed to a string literal. | ||
@@ -89,3 +92,3 @@ **For React Native >= v0.29** | ||
1. In your `build.gradle` file, specify the [`applicationIdSuffix`](http://google.github.io/android-gradle-dsl/current/com.android.build.gradle.internal.dsl.BuildType.html#com.android.build.gradle.internal.dsl.BuildType:applicationIdSuffix) field for your debug build type, which gives your debug build a unique identity for the OS (e.g. `com.foo` vs. `com.foo.debug`). | ||
1. In your `build.gradle` file, specify the [`applicationIdSuffix`](http://google.github.io/android-gradle-dsl/current/com.android.build.gradle.internal.dsl.BuildType.html#com.android.build.gradle.internal.dsl.BuildType:applicationIdSuffix) field for your debug build type, which gives your debug build a unique identity for the OS (like `com.foo` vs. `com.foo.debug`). | ||
@@ -100,7 +103,7 @@ ```groovy | ||
2. Create the `app/src/debug/res` directory structure in your app, which allows overriding resources (e.g. strings, icons, layouts) for your debug builds | ||
2. Create the `app/src/debug/res` directory structure in your app, which allows overriding resources (like strings, icons, layouts) for your debug builds | ||
3. Create a `values` directory underneath the debug res directory created in #2, and copy the existing `strings.xml` file from the `app/src/main/res/values` directory | ||
4. Open up the new debug `strings.xml` file and change the `<string name="app_name">` element's value to something else (e.g. `foo-debug`). This ensures that your debug build now has a distinct display name, so that you can differentiate it from your release build. | ||
4. Open up the new debug `strings.xml` file and change the `<string name="app_name">` element's value to something else (like `foo-debug`). This ensures that your debug build now has a distinct display name, so that you can differentiate it from your release build. | ||
@@ -107,0 +110,0 @@ 5. Optionally, create "mirrored" directories in the `app/src/debug/res` directory for all of your app's icons that you want to change for your debug build. This part isn't technically critical, but it can make it easier to quickly spot your debug builds on a device if its icon is noticeable different. |
@@ -9,3 +9,3 @@ ### iOS | ||
Xcode allows you to define custom build settings for each "configuration" (e.g. debug, release), which can then be referenced as the value of keys within the `Info.plist` file (e.g. the `CodePushDeploymentKey` setting). This mechanism allows you to easily configure your builds to produce binaries, which are configured to synchronize with different CodePush deployments. | ||
Xcode allows you to define custom build settings for each "configuration" (like debug, release), which can then be referenced as the value of keys within the `Info.plist` file (like the `CodePushDeploymentKey` setting). This mechanism allows you to easily configure your builds to produce binaries, which are configured to synchronize with different CodePush deployments. | ||
@@ -12,0 +12,0 @@ To set this up, perform the following steps: |
@@ -202,3 +202,3 @@ ## Android Setup | ||
In order to update/restart your React Native instance, CodePush must be configured with a `ReactInstanceHolder` before attempting to restart an instance in the background. This is usually done in your `Application` implementation. | ||
In order to update/restart your React Native instance, CodePush must be configured with a `ReactInstanceHolder` before attempting to restart an instance in the background. This is done in your `Application` implementation. | ||
@@ -205,0 +205,0 @@ ##### For React Native >= v0.29 (Background React Instances) |
@@ -102,3 +102,3 @@ ## iOS Setup | ||
2. Find the following line of code, which set source URL for bridge for production releases: | ||
2. Find the following line of code, which sets the source URL for bridge for production releases: | ||
@@ -172,3 +172,3 @@ ```objective-c | ||
To let the CodePush runtime know which deployment it should query for updates against, open your app's `Info.plist` file and add a new entry named `CodePushDeploymentKey`, whose value is the key of the deployment you want to configure this app against (e.g. the key for the `Staging` deployment for the `FooBar` app). You can retrieve this value by running `code-push deployment ls <appName> -k` in the CodePush CLI (the `-k` flag is necessary since keys aren't displayed by default) and copying the value of the `Deployment Key` column which corresponds to the deployment you want to use (see below). Note that using the deployment's name (e.g. Staging) will not work. That "friendly name" is intended only for authenticated management usage from the CLI, and not for public consumption within your app. | ||
To let the CodePush runtime know which deployment it should query for updates against, open your app's `Info.plist` file and add a new entry named `CodePushDeploymentKey`, whose value is the key of the deployment you want to configure this app against (like the key for the `Staging` deployment for the `FooBar` app). You can retrieve this value by running `code-push deployment ls <appName> -k` in the CodePush CLI (the `-k` flag is necessary since keys aren't displayed by default) and copying the value of the `Deployment Key` column which corresponds to the deployment you want to use (see below). Note that using the deployment's name (like Staging) will not work. That "friendly name" is intended only for authenticated management usage from the CLI, and not for public consumption within your app. | ||
@@ -175,0 +175,0 @@ ![Deployment list](https://cloud.githubusercontent.com/assets/116461/11601733/13011d5e-9a8a-11e5-9ce2-b100498ffb34.png) |
{ | ||
"name": "react-native-code-push", | ||
"version": "5.6.0", | ||
"version": "5.6.1", | ||
"description": "React Native plugin for the CodePush service", | ||
@@ -20,6 +20,6 @@ "main": "CodePush.js", | ||
"dependencies": { | ||
"code-push": "2.0.6", | ||
"code-push": "^2.0.7", | ||
"glob": "^5.0.15", | ||
"hoist-non-react-statics": "^2.3.1", | ||
"inquirer": "1.1.2", | ||
"inquirer": "^1.1.2", | ||
"plist": "3.0.1", | ||
@@ -37,8 +37,8 @@ "semver": "^5.6.0", | ||
"gulp-tslint": "latest", | ||
"gulp-typescript": "2.12.2", | ||
"gulp-typescript": "^5.0.1", | ||
"mkdirp": "latest", | ||
"q": "^1.4.1", | ||
"q": "^1.5.1", | ||
"run-sequence": "latest", | ||
"tslint": "^4.3.1", | ||
"typescript": "^2.1.5" | ||
"tslint": "^5.18.0", | ||
"typescript": "^2.9.2" | ||
}, | ||
@@ -55,5 +55,6 @@ "rnpm": { | ||
"commands": { | ||
"postlink": "node node_modules/react-native-code-push/scripts/postlink/run" | ||
"postlink": "node node_modules/react-native-code-push/scripts/postlink/run", | ||
"postunlink": "node node_modules/react-native-code-push/scripts/postunlink/run" | ||
} | ||
} | ||
} |
@@ -0,1 +1,6 @@ | ||
UPDATE: Over the next few months, we will be working on a new version of CodePush that will address some of the most common performance issues our customers are facing. This updated version will allow a better experience, our team to better support CodePush moving forward and have a faster development cycle for new features. | ||
We are prioritizing this work because we believe this to be the most valuable thing we can do for our CodePush customers in the long run. Starting June 11th 2019, support will slow down, bug fixes will be limited to critical bugs, and new feature development will pause until we finish this core update. | ||
--- | ||
[![appcenterbanner](https://user-images.githubusercontent.com/31293287/32969262-3cc5d48a-cb99-11e7-91bf-fa57c67a371c.png)](http://microsoft.github.io/code-push/) | ||
@@ -7,3 +12,3 @@ | ||
![Switching tags](https://cloud.githubusercontent.com/assets/8598682/17350832/ce0dec40-58de-11e6-9c8c-906bb114c34f.png) | ||
![Switching tags](https://user-images.githubusercontent.com/42337914/57237511-0835de80-7030-11e9-88fa-64eb200478d0.png) | ||
@@ -52,3 +57,3 @@ This plugin provides client-side integration for the [CodePush service](https://microsoft.github.io/code-push/), allowing you to easily add a dynamic update experience to your React Native app(s). | ||
- iOS (7+) | ||
- Android (4.1+) | ||
- Android (4.1+) on TLS 1.2 compatible devices | ||
- Windows (UWP) | ||
@@ -126,3 +131,3 @@ | ||
1. When (and how often) to check for an update? (e.g. app start, in response to clicking a button in a settings page, periodically at some fixed interval) | ||
1. When (and how often) to check for an update? (for example app start, in response to clicking a button in a settings page, periodically at some fixed interval) | ||
@@ -169,3 +174,3 @@ 2. When an update is available, how to present it to the end user? | ||
Alternatively, if you want fine-grained control over when the check happens (e.g. a button press or timer interval), you can call [`CodePush.sync()`](docs/api-js.md#codepushsync) at any time with your desired `SyncOptions`, and optionally turn off CodePush's automatic checking by specifying a manual `checkFrequency`: | ||
Alternatively, if you want fine-grained control over when the check happens (like a button press or timer interval), you can call [`CodePush.sync()`](docs/api-js.md#codepushsync) at any time with your desired `SyncOptions`, and optionally turn off CodePush's automatic checking by specifying a manual `checkFrequency`: | ||
@@ -197,3 +202,3 @@ ```javascript | ||
If you would like to display an update confirmation dialog (an "active install"), configure when an available update is installed (e.g. force an immediate restart) or customize the update experience in any other way, refer to the [`codePush()`](docs/api-js.md#codepush) API reference for information on how to tweak this default behavior. | ||
If you would like to display an update confirmation dialog (an "active install"), configure when an available update is installed (like force an immediate restart) or customize the update experience in any other way, refer to the [`codePush()`](docs/api-js.md#codepush) API reference for information on how to tweak this default behavior. | ||
@@ -204,3 +209,3 @@ *NOTE: If you are using [Redux](http://redux.js.org) and [Redux Saga](http://yelouafi.github.io/redux-saga/), you can alternatively use the [react-native-code-push-saga](http://github.com/lostintangent/react-native-code-push-saga) module, which allows you to customize when `sync` is called in a perhaps simpler/more idiomatic way.* | ||
While Google Play and internally distributed apps (e.g. Enterprise, Fabric, HockeyApp) have no limitations over how to publish updates using CodePush, the iOS App Store and its corresponding guidelines have more precise rules you should be aware of before integrating the solution within your application. | ||
While Google Play and internally distributed apps (for example Enterprise, Fabric, HockeyApp) have no limitations over how to publish updates using CodePush, the iOS App Store and its corresponding guidelines have more precise rules you should be aware of before integrating the solution within your application. | ||
@@ -232,3 +237,3 @@ Paragraph **3.3.2**, since back in 2015's [Apple Developer Program License Agreement](https://developer.apple.com/programs/ios/information/) fully allowed performing over-the-air updates of JavaScript and assets - and in its latest version (20170605) [downloadable here](https://developer.apple.com/terms/) this ruling is even broader: | ||
The `release-react` command enables such a simple workflow because it provides many sensible defaults (e.g. generating a release bundle, assuming your app's entry file on iOS is either `index.ios.js` or `index.js`). However, all of these defaults can be customized to allow incremental flexibility as necessary, which makes it a good fit for most scenarios. | ||
The `release-react` command enables such a simple workflow because it provides many sensible defaults (like generating a release bundle, assuming your app's entry file on iOS is either `index.ios.js` or `index.js`). However, all of these defaults can be customized to allow incremental flexibility as necessary, which makes it a good fit for most scenarios. | ||
@@ -276,5 +281,5 @@ ```shell | ||
*NOTE: If you want to get really fancy, you can even choose to perform a "staged rollout" as part of #3, which allows you to mitigate additional potential risk with the update (e.g. did your testing in #2 touch all possible devices/conditions?) by only making the production update available to a percentage of your users (e.g. `code-push promote <APP_NAME> Staging Production -r 20%`). Then, after waiting for a reasonable amount of time to see if any crash reports or customer feedback comes in, you can expand it to your entire audience by running `code-push patch <APP_NAME> Production -r 100%`.* | ||
*NOTE: If you want to get really fancy, you can even choose to perform a "staged rollout" as part of #3, which allows you to mitigate additional potential risk with the update (like did your testing in #2 touch all possible devices/conditions?) by only making the production update available to a percentage of your users (for example `code-push promote <APP_NAME> Staging Production -r 20%`). Then, after waiting for a reasonable amount of time to see if any crash reports or customer feedback comes in, you can expand it to your entire audience by running `code-push patch <APP_NAME> Production -r 100%`.* | ||
You'll notice that the above steps refer to a "staging build" and "production build" of your app. If your build process already generates distinct binaries per "environment", then you don't need to read any further, since swapping out CodePush deployment keys is just like handling environment-specific config for any other service your app uses (e.g. Facebook). However, if you're looking for examples (**including demo projects**) on how to setup your build process to accommodate this, then refer to the following sections, depending on the platform(s) your app is targeting: | ||
You'll notice that the above steps refer to a "staging build" and "production build" of your app. If your build process already generates distinct binaries per "environment", then you don't need to read any further, since swapping out CodePush deployment keys is just like handling environment-specific config for any other service your app uses (like Facebook). However, if you're looking for examples (**including demo projects**) on how to setup your build process to accommodate this, then refer to the following sections, depending on the platform(s) your app is targeting: | ||
@@ -301,3 +306,3 @@ * [Android](docs/multi-deployment-testing-android.md) | ||
2. Annotate the server-side profile of your users with an additional piece of metadata which indicates the deployment they should sync with. By default, your app could just use the binary-embedded key, but after a user has authenticated, your server can choose to "redirect" them to a different deployment, which allows you to incrementally place certain users or groups in different deployments as needed. You could even choose to store the server-response in local storage so that it becomes the new default. How you store the key alongside your user's profiles is entirely up to your authentication solution (e.g. Auth0, Firebase, custom DB + REST API), but is generally pretty trivial to do. | ||
2. Annotate the server-side profile of your users with an additional piece of metadata that indicates the deployment they should sync with. By default, your app could just use the binary-embedded key, but after a user has authenticated, your server can choose to "redirect" them to a different deployment, which allows you to incrementally place certain users or groups in different deployments as needed. You could even choose to store the server-response in local storage so that it becomes the new default. How you store the key alongside your user's profiles is entirely up to your authentication solution (for example Auth0, Firebase, custom DB + REST API), but is generally pretty trivial to do. | ||
@@ -344,3 +349,3 @@ *NOTE: If needed, you could also implement a hybrid solution that allowed your end-users to toggle between different deployments, while also allowing your server to override that decision. This way, you have a hierarchy of "deployment resolution" that ensures your app has the ability to update itself out-of-the-box, your end users can feel rewarded by getting early access to bits, but you also have the ability to run A/B tests on your users as needed.* | ||
The `sync` method includes a lot of diagnostic logging out-of-the-box, so if you're encountering an issue when using it, the best thing to try first is examining the output logs of your app. This will tell you whether the app is configured correctly (e.g. can the plugin find your deployment key?), if the app is able to reach the server, if an available update is being discovered, if the update is being successfully downloaded/installed, etc. We want to continue improving the logging to be as intuitive/comprehensive as possible, so please [let us know](mailto:codepushfeed@microsoft.com) if you find it to be confusing or missing anything. | ||
The `sync` method includes a lot of diagnostic logging out-of-the-box, so if you're encountering an issue when using it, the best thing to try first is examining the output logs of your app. This will tell you whether the app is configured correctly (like can the plugin find your deployment key?), if the app is able to reach the server, if an available update is being discovered, if the update is being successfully downloaded/installed, etc. We want to continue improving the logging to be as intuitive/comprehensive as possible, so please [let us know](mailto:codepushfeed@microsoft.com) if you find it to be confusing or missing anything. | ||
@@ -370,4 +375,4 @@ The simplest way to view these logs is to run the `code-push debug` command for the specific platform you are currently working with (e.g. `code-push debug ios`). This will output a log stream that is filtered to just CodePush messages, for the specified platform. This makes it easy to identify issues, without needing to use a platform-specific tool, or wade through a potentially high volume of logs. | ||
| Server responds with a `404` when calling `sync` or `checkForUpdate` | Double-check that the deployment key you added to your `Info.plist` (iOS), `build.gradle` (Android) or that you're passing to `sync`/`checkForUpdate`, is in fact correct. You can run `code-push deployment ls [APP_NAME] -k` to view the correct keys for your app deployments. | | ||
| Update not being discovered | Double-check that the version of your running app (e.g. `1.0.0`) matches the version you specified when releasing the update to CodePush. Additionally, make sure that you are releasing to the same deployment that your app is configured to sync with. | | ||
| Update not being displayed after restart | If you're not calling `sync` on app start (e.g. within `componentDidMount` of your root component), then you need to explicitly call `notifyApplicationReady` on app start, otherwise, the plugin will think your update failed and roll it back. | | ||
| Update not being discovered | Double-check that the version of your running app (like `1.0.0`) matches the version you specified when releasing the update to CodePush. Additionally, make sure that you are releasing to the same deployment that your app is configured to sync with. | | ||
| Update not being displayed after restart | If you're not calling `sync` on app start (like within `componentDidMount` of your root component), then you need to explicitly call `notifyApplicationReady` on app start, otherwise, the plugin will think your update failed and roll it back. | | ||
| I've released an update for iOS but my Android app also shows an update and it breaks it | Be sure you have different deployment keys for each platform in order to receive updates correctly | | ||
@@ -388,3 +393,3 @@ | I've released new update but changes are not reflected | Be sure that you are running app in modes other than Debug. In Debug mode, React Native app always downloads JS bundle generated by packager, so JS bundle downloaded by CodePush does not apply. | ||
This module ships its `*.d.ts` file as part of its NPM package, which allows you to simply `import` it, and receive intellisense in supporting editors (e.g. Visual Studio Code), as well as compile-time type checking if you're using TypeScript. For the most part, this behavior should just work out of the box, however, if you've specified `es6` as the value for either the `target` or `module` [compiler option](http://www.typescriptlang.org/docs/handbook/compiler-options.html) in your [`tsconfig.json`](http://www.typescriptlang.org/docs/handbook/tsconfig-json.html) file, then just make sure that you also set the `moduleResolution` option to `node`. This ensures that the TypeScript compiler will look within the `node_modules` for the type definitions of imported modules. Otherwise, you'll get an error like the following when trying to import the `react-native-code-push` module: `error TS2307: Cannot find module 'react-native-code-push'`. | ||
This module ships its `*.d.ts` file as part of its NPM package, which allows you to simply `import` it, and receive intellisense in supporting editors (like Visual Studio Code), as well as compile-time type checking if you're using TypeScript. For the most part, this behavior should just work out of the box, however, if you've specified `es6` as the value for either the `target` or `module` [compiler option](http://www.typescriptlang.org/docs/handbook/compiler-options.html) in your [`tsconfig.json`](http://www.typescriptlang.org/docs/handbook/tsconfig-json.html) file, then just make sure that you also set the `moduleResolution` option to `node`. This ensures that the TypeScript compiler will look within the `node_modules` for the type definitions of imported modules. Otherwise, you'll get an error like the following when trying to import the `react-native-code-push` module: `error TS2307: Cannot find module 'react-native-code-push'`. | ||
@@ -391,0 +396,0 @@ --- |
@@ -0,4 +1,3 @@ | ||
var linkTools = require('../../tools/linkToolsAndroid'); | ||
var fs = require("fs"); | ||
var glob = require("glob"); | ||
var path = require("path"); | ||
var inquirer = require('inquirer'); | ||
@@ -10,60 +9,28 @@ | ||
var ignoreFolders = { ignore: ["node_modules/**", "**/build/**"] }; | ||
var buildGradlePath = path.join("android", "app", "build.gradle"); | ||
var manifestPath = glob.sync("**/AndroidManifest.xml", ignoreFolders)[0]; | ||
var buildGradlePath = linkTools.getBuildGradlePath(); | ||
var mainApplicationPath = linkTools.getMainApplicationLocation(); | ||
function findMainApplication() { | ||
if (!manifestPath) { | ||
return null; | ||
} | ||
var manifest = fs.readFileSync(manifestPath, "utf8"); | ||
// Android manifest must include single 'application' element | ||
var matchResult = manifest.match(/application\s+android:name\s*=\s*"(.*?)"/); | ||
if (matchResult) { | ||
var appName = matchResult[1]; | ||
} else { | ||
return null; | ||
} | ||
var nameParts = appName.split('.'); | ||
var searchPath = glob.sync("**/" + nameParts[nameParts.length - 1] + ".java", ignoreFolders)[0]; | ||
return searchPath; | ||
} | ||
var mainApplicationPath = findMainApplication() || glob.sync("**/MainApplication.java", ignoreFolders)[0]; | ||
// 1. Add the getJSBundleFile override | ||
var getJSBundleFileOverride = ` | ||
@Override | ||
protected String getJSBundleFile() { | ||
return CodePush.getJSBundleFile(); | ||
} | ||
`; | ||
var getJSBundleFileOverride = linkTools.getJSBundleFileOverride; | ||
function isAlreadyOverridden(codeContents) { | ||
return /@Override\s*\n\s*protected String getJSBundleFile\(\)\s*\{[\s\S]*?\}/.test(codeContents); | ||
} | ||
if (mainApplicationPath) { | ||
var mainApplicationContents = fs.readFileSync(mainApplicationPath, "utf8"); | ||
if (isAlreadyOverridden(mainApplicationContents)) { | ||
if (linkTools.isJsBundleOverridden(mainApplicationContents)) { | ||
console.log(`"getJSBundleFile" is already overridden`); | ||
} else { | ||
var reactNativeHostInstantiation = "new ReactNativeHost(this) {"; | ||
var reactNativeHostInstantiation = linkTools.reactNativeHostInstantiation; | ||
mainApplicationContents = mainApplicationContents.replace(reactNativeHostInstantiation, | ||
`${reactNativeHostInstantiation}\n${getJSBundleFileOverride}`); | ||
`${reactNativeHostInstantiation}${getJSBundleFileOverride}`); | ||
fs.writeFileSync(mainApplicationPath, mainApplicationContents); | ||
} | ||
} else { | ||
var mainActivityPath = glob.sync("**/MainActivity.java", ignoreFolders)[0]; | ||
var mainActivityPath = linkTools.getMainActivityPath(); | ||
if (mainActivityPath) { | ||
var mainActivityContents = fs.readFileSync(mainActivityPath, "utf8"); | ||
if (isAlreadyOverridden(mainActivityContents)) { | ||
if (linkTools.isJsBundleOverridden(mainActivityContents)) { | ||
console.log(`"getJSBundleFile" is already overridden`); | ||
} else { | ||
var mainActivityClassDeclaration = "public class MainActivity extends ReactActivity {"; | ||
var mainActivityClassDeclaration = linkTools.mainActivityClassDeclaration; | ||
mainActivityContents = mainActivityContents.replace(mainActivityClassDeclaration, | ||
`${mainActivityClassDeclaration}\n${getJSBundleFileOverride}`); | ||
`${mainActivityClassDeclaration}${getJSBundleFileOverride}`); | ||
fs.writeFileSync(mainActivityPath, mainActivityContents); | ||
@@ -87,3 +54,3 @@ } | ||
var reactGradleLink = buildGradleContents.match(/\napply from: ["'].*?react\.gradle["']/)[0]; | ||
var codePushGradleLink = `apply from: "../../node_modules/react-native-code-push/android/codepush.gradle"`; | ||
var codePushGradleLink = linkTools.codePushGradleLink; | ||
if (~buildGradleContents.indexOf(codePushGradleLink)) { | ||
@@ -93,3 +60,3 @@ console.log(`"codepush.gradle" is already linked in the build definition`); | ||
buildGradleContents = buildGradleContents.replace(reactGradleLink, | ||
`${reactGradleLink}\n${codePushGradleLink}`); | ||
`${reactGradleLink}${codePushGradleLink}`); | ||
fs.writeFileSync(buildGradlePath, buildGradleContents); | ||
@@ -99,3 +66,3 @@ } | ||
//3. Add deployment key | ||
var stringsResourcesPath = glob.sync("**/strings.xml", ignoreFolders)[0]; | ||
var stringsResourcesPath = linkTools.getStringsResourcesPath(); | ||
if (!stringsResourcesPath) { | ||
@@ -105,3 +72,3 @@ return Promise.reject(new Error(`Couldn't find strings.xml. You might need to update it manually.`)); | ||
var stringsResourcesContent = fs.readFileSync(stringsResourcesPath, "utf8"); | ||
var deploymentKeyName = "reactNativeCodePush_androidDeploymentKey"; | ||
var deploymentKeyName = linkTools.deploymentKeyName; | ||
if (~stringsResourcesContent.indexOf(deploymentKeyName)) { | ||
@@ -108,0 +75,0 @@ console.log(`${deploymentKeyName} already specified in the strings.xml`); |
@@ -0,7 +1,6 @@ | ||
var linkTools = require('../../tools/linkToolsIos'); | ||
var fs = require("fs"); | ||
var glob = require("glob"); | ||
var inquirer = require('inquirer'); | ||
var path = require("path"); | ||
var plist = require("plist"); | ||
var xcode = require("xcode"); | ||
var semver = require('semver'); | ||
@@ -15,12 +14,4 @@ | ||
var ignoreNodeModules = { ignore: "node_modules/**" }; | ||
var ignoreNodeModulesAndPods = { ignore: ["node_modules/**", "ios/Pods/**"] }; | ||
var appDelegatePaths = glob.sync("**/AppDelegate.+(mm|m)", ignoreNodeModules); | ||
var appDelegatePath = linkTools.getAppDeletePath(); | ||
// Fix for https://github.com/Microsoft/react-native-code-push/issues/477 | ||
// Typical location of AppDelegate.m for newer RN versions: $PROJECT_ROOT/ios/<project_name>/AppDelegate.m | ||
// Let's try to find that path by filtering the whole array for any path containing <project_name> | ||
// If we can't find it there, play dumb and pray it is the first path we find. | ||
var appDelegatePath = findFileByAppName(appDelegatePaths, package ? package.name : null) || appDelegatePaths[0]; | ||
if (!appDelegatePath) { | ||
@@ -35,4 +26,3 @@ return Promise.reject(`Couldn't find AppDelegate. You might need to update it manually \ | ||
// 1. Add the header import statement | ||
var codePushHeaderImportStatement = `#import <CodePush/CodePush.h>`; | ||
if (~appDelegateContents.indexOf(codePushHeaderImportStatement)) { | ||
if (~appDelegateContents.indexOf(linkTools.codePushHeaderImportStatement)) { | ||
console.log(`"CodePush.h" header already imported.`); | ||
@@ -42,3 +32,3 @@ } else { | ||
appDelegateContents = appDelegateContents.replace(appDelegateHeaderImportStatement, | ||
`${appDelegateHeaderImportStatement}\n${codePushHeaderImportStatement}`); | ||
`${appDelegateHeaderImportStatement}${linkTools.codePushHeaderImportStatementFormatted}`); | ||
} | ||
@@ -52,4 +42,4 @@ | ||
} else if (semver.gte(semver.coerce(reactNativeVersion), "0.59.0")) { | ||
var oldBundleUrl = "[[NSBundle mainBundle] URLForResource:@\"main\" withExtension:@\"jsbundle\"]"; | ||
var codePushBundleUrl = "[CodePush bundleURL]"; | ||
var oldBundleUrl = linkTools.oldBundleUrl; | ||
var codePushBundleUrl = linkTools.codePushBundleUrl; | ||
@@ -72,3 +62,3 @@ if (~appDelegateContents.indexOf(codePushBundleUrl)) { | ||
var newJsCodeLocationAssignmentStatement = "jsCodeLocation = [CodePush bundleURL];"; | ||
var newJsCodeLocationAssignmentStatement = linkTools.codePushGradleLink; | ||
if (~appDelegateContents.indexOf(newJsCodeLocationAssignmentStatement)) { | ||
@@ -78,12 +68,7 @@ console.log(`"jsCodeLocation" already pointing to "[CodePush bundleURL]".`); | ||
if (jsCodeLocations.length === 1) { | ||
// If there is one `jsCodeLocation` it means that react-native app version is lower than 0.57.8 | ||
// If there is one `jsCodeLocation` it means that react-native app version is not the 0.57.8 or 0.57.0 and lower than 0.59 | ||
// and we should replace this line with DEBUG ifdef statement and add CodePush call for Release case | ||
var oldJsCodeLocationAssignmentStatement = jsCodeLocations[0]; | ||
var jsCodeLocationPatch = ` | ||
#ifdef DEBUG | ||
${oldJsCodeLocationAssignmentStatement} | ||
#else | ||
${newJsCodeLocationAssignmentStatement} | ||
#endif`; | ||
var jsCodeLocationPatch = linkTools.getJsCodeLocationPatch(oldJsCodeLocationAssignmentStatement); | ||
appDelegateContents = appDelegateContents.replace(oldJsCodeLocationAssignmentStatement, | ||
@@ -103,3 +88,3 @@ jsCodeLocationPatch); | ||
var plistPath = getPlistPath(); | ||
var plistPath = linkTools.getPlistPath(); | ||
@@ -138,101 +123,2 @@ if (!plistPath) { | ||
} | ||
// Helper that filters an array with AppDelegate.m paths for a path with the app name inside it | ||
// Should cover nearly all cases | ||
function findFileByAppName(array, appName) { | ||
if (array.length === 0 || !appName) return null; | ||
for (var i = 0; i < array.length; i++) { | ||
var path = array[i]; | ||
if (path && path.indexOf(appName) !== -1) { | ||
return path; | ||
} | ||
} | ||
return null; | ||
} | ||
function getDefaultPlistPath() { | ||
//this is old logic in case we are unable to find PLIST from xcode/pbxproj - at least we can fallback to default solution | ||
return glob.sync(`**/${package.name}/*Info.plist`, ignoreNodeModules)[0]; | ||
} | ||
// This is enhanced version of standard implementation of xcode 'getBuildProperty' function | ||
// but allows us to narrow results by PRODUCT_NAME property also. | ||
// So we suppose that proj name should be the same as package name, otherwise fallback to default plist path searching logic | ||
function getBuildSettingsPropertyMatchingTargetProductName(parsedXCodeProj, prop, targetProductName, build){ | ||
var target; | ||
var COMMENT_KEY = /_comment$/; | ||
var PRODUCT_NAME_PROJECT_KEY = 'PRODUCT_NAME'; | ||
var TV_OS_DEPLOYMENT_TARGET_PROPERTY_NAME = 'TVOS_DEPLOYMENT_TARGET'; | ||
var TEST_HOST_PROPERTY_NAME = 'TEST_HOST'; | ||
var configs = parsedXCodeProj.pbxXCBuildConfigurationSection(); | ||
for (var configName in configs) { | ||
if (!COMMENT_KEY.test(configName)) { | ||
var config = configs[configName]; | ||
if ( (build && config.name === build) || (build === undefined) ) { | ||
if (targetProductName) { | ||
if (config.buildSettings[prop] !== undefined && config.buildSettings[PRODUCT_NAME_PROJECT_KEY] == targetProductName) { | ||
target = config.buildSettings[prop]; | ||
} | ||
} else { | ||
if (config.buildSettings[prop] !== undefined && | ||
//exclude tvOS projects | ||
config.buildSettings[TV_OS_DEPLOYMENT_TARGET_PROPERTY_NAME] == undefined && | ||
//exclude test app | ||
config.buildSettings[TEST_HOST_PROPERTY_NAME] == undefined) { | ||
target = config.buildSettings[prop]; | ||
} | ||
} | ||
} | ||
} | ||
} | ||
return target; | ||
} | ||
function getPlistPath(){ | ||
var xcodeProjectPaths = glob.sync(`**/*.xcodeproj/project.pbxproj`, ignoreNodeModulesAndPods); | ||
if (!xcodeProjectPaths){ | ||
return getDefaultPlistPath(); | ||
} | ||
if (xcodeProjectPaths.length !== 1) { | ||
console.log('Could not determine correct xcode proj path to retrieve related plist file, there are multiple xcodeproj under the solution.'); | ||
return getDefaultPlistPath(); | ||
} | ||
var xcodeProjectPath = xcodeProjectPaths[0]; | ||
var parsedXCodeProj; | ||
try { | ||
var proj = xcode.project(xcodeProjectPath); | ||
//use sync version because there are some problems with async version of xcode lib as of current version | ||
parsedXCodeProj = proj.parseSync(); | ||
} | ||
catch(e) { | ||
console.log('Couldn\'t read info.plist path from xcode project - error: ' + e.message); | ||
return getDefaultPlistPath(); | ||
} | ||
var INFO_PLIST_PROJECT_KEY = 'INFOPLIST_FILE'; | ||
var RELEASE_BUILD_PROPERTY_NAME = "Release"; | ||
var targetProductName = package ? package.name : null; | ||
//Try to get 'Release' build of ProductName matching the package name first and if it doesn't exist then try to get any other if existing | ||
var plistPathValue = getBuildSettingsPropertyMatchingTargetProductName(parsedXCodeProj, INFO_PLIST_PROJECT_KEY, targetProductName, RELEASE_BUILD_PROPERTY_NAME) || | ||
getBuildSettingsPropertyMatchingTargetProductName(parsedXCodeProj, INFO_PLIST_PROJECT_KEY, targetProductName) || | ||
getBuildSettingsPropertyMatchingTargetProductName(parsedXCodeProj, INFO_PLIST_PROJECT_KEY, null, RELEASE_BUILD_PROPERTY_NAME) || | ||
getBuildSettingsPropertyMatchingTargetProductName(parsedXCodeProj, INFO_PLIST_PROJECT_KEY) || | ||
parsedXCodeProj.getBuildProperty(INFO_PLIST_PROJECT_KEY, RELEASE_BUILD_PROPERTY_NAME) || | ||
parsedXCodeProj.getBuildProperty(INFO_PLIST_PROJECT_KEY); | ||
if (!plistPathValue){ | ||
return getDefaultPlistPath(); | ||
} | ||
//also remove surrounding quotes from plistPathValue to get correct path resolved | ||
//(see https://github.com/Microsoft/react-native-code-push/issues/534#issuecomment-302069326 for details) | ||
return path.resolve(path.dirname(xcodeProjectPath), '..', plistPathValue.replace(/^"(.*)"$/, '$1')); | ||
} | ||
} | ||
} |
Sorry, the diff of this file is not supported yet
1318509
191
4390
387
9
+ Added@tootallnate/once@1.1.2(transitive)
+ Addedagent-base@6.0.2(transitive)
+ Addedast-types@0.13.4(transitive)
+ Addedcode-push@2.0.7(transitive)
+ Addeddata-uri-to-buffer@3.0.1(transitive)
+ Addeddebug@4.4.0(transitive)
+ Addeddegenerator@2.2.0(transitive)
+ Addedfast-safe-stringify@2.1.1(transitive)
+ Addedfile-uri-to-path@2.0.0(transitive)
+ Addedform-data@3.0.2(transitive)
+ Addedfs-extra@8.1.0(transitive)
+ Addedget-uri@3.0.2(transitive)
+ Addedgraceful-fs@4.2.11(transitive)
+ Addedhttp-proxy-agent@4.0.1(transitive)
+ Addedhttps-proxy-agent@5.0.1(transitive)
+ Addedinquirer@1.2.3(transitive)
+ Addedip-address@9.0.5(transitive)
+ Addedjsbn@1.1.0(transitive)
+ Addedjsonfile@4.0.0(transitive)
+ Addedlru-cache@5.1.1(transitive)
+ Addedmime@2.6.0(transitive)
+ Addednetmask@2.0.2(transitive)
+ Addedobject-inspect@1.13.3(transitive)
+ Addedpac-proxy-agent@4.1.0(transitive)
+ Addedpac-resolver@4.2.0(transitive)
+ Addedproxy-agent@4.0.1(transitive)
+ Addedreadable-stream@3.6.2(transitive)
+ Addedrecursive-fs@1.1.2(transitive)
+ Addedsemver@7.7.0(transitive)
+ Addedslash@3.0.0(transitive)
+ Addedsmart-buffer@4.2.0(transitive)
+ Addedsocks@2.8.3(transitive)
+ Addedsocks-proxy-agent@5.0.1(transitive)
+ Addedsprintf-js@1.1.3(transitive)
+ Addedsuperagent@5.3.1(transitive)
+ Addedsuperagent-proxy@2.1.0(transitive)
+ Addeduniversalify@0.1.2(transitive)
+ Addedyallist@3.1.1(transitive)
- Removedagent-base@4.3.0(transitive)
- Removedast-types@0.16.1(transitive)
- Removedco@4.6.0(transitive)
- Removedcode-push@2.0.6(transitive)
- Removeddata-uri-to-buffer@1.2.0(transitive)
- Removeddebug@2.6.93.1.0(transitive)
- Removeddegenerator@1.0.4(transitive)
- Removedes6-promise@4.2.8(transitive)
- Removedes6-promisify@5.0.0(transitive)
- Removedesprima@3.1.3(transitive)
- Removedfile-uri-to-path@1.0.0(transitive)
- Removedform-data@2.5.2(transitive)
- Removedget-uri@2.0.4(transitive)
- Removedhttp-proxy-agent@2.1.0(transitive)
- Removedhttps-proxy-agent@2.2.4(transitive)
- Removedinquirer@1.1.2(transitive)
- Removedlru-cache@4.1.5(transitive)
- Removedmime@1.6.0(transitive)
- Removedms@2.0.0(transitive)
- Removednetmask@1.0.6(transitive)
- Removedobject-inspect@1.13.4(transitive)
- Removedpac-proxy-agent@2.0.2(transitive)
- Removedpac-resolver@3.0.0(transitive)
- Removedproxy-agent@2.3.1(transitive)
- Removedpseudomap@1.0.2(transitive)
- Removedrecursive-fs@0.1.4(transitive)
- Removedsafe-buffer@5.2.1(transitive)
- Removedslash@1.0.0(transitive)
- Removedsmart-buffer@1.1.15(transitive)
- Removedsocks@1.1.10(transitive)
- Removedsocks-proxy-agent@3.0.1(transitive)
- Removedsuperagent@3.8.3(transitive)
- Removedsuperagent-proxy@1.0.3(transitive)
- Removedthunkify@2.1.2(transitive)
- Removedyallist@2.1.2(transitive)
Updatedcode-push@^2.0.7
Updatedinquirer@^1.1.2