# README

[![JavaScript Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://standardjs.com) ![travis ci](https://travis-ci.org/electrode-io/electrode-native.svg?branch=master)

## Installation

* Before installing the platform, make sure that the [prerequisites](/introduction/what-is-ern/prerequisites) are met
* Install the platform by running the following command in a terminal :

```bash
npm install -g electrode-native
```

## Getting Started

* Check out our [Announcement Blog Post](https://medium.com/walmartlabs/electrode-native-the-platform-for-integrating-react-native-into-your-apps-129cbabda7b8)
* Visit our site at <http://www.electrode.io>.
* See [What is Electrode Native](/introduction/what-is-ern) for more details on Electrode Native.
* Read [Electrode Native Case Study](https://www.walmartlabs.com/case-studies/electrode-native) to learn about key facts.

## Contributing

Please see the [CONTRIBUTING guide](/introduction/what-is-ern/contributing)

## Support and Acknowledgment

We'd like to thank our employer, WalmartLabs because we can work on the development of Electrode Native platform as Open Sourced Software for the needs of our internal teams and projects. We love the public community and the support we get, and we address your requests as much as we can. We are always excited to get feedback, bug reports, and pull requests. Thank you.

## License

Copyright 2017 WalmartLabs

Licensed under the [Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0).


# Overview

## What is Electrode Native ?

Electrode Native is a mobile platform, composed of a set of tools, facilitating the integration and delivery of features written in React Native into existing non React Native iOS/Android applications.

The core of Electrode Native platform is written in TypeScript. Some parts also contain native code in the form of [Mustache](https://mustache.github.io/) templates used for native code generation. Some modules of Electrode Native are mainly native projects, such as the [Electrode Native Bridge](https://github.com/electrode-io/react-native-electrode-bridge) being a React Native native module.

Interaction with Electrode Native will mostly be done through the `ern` command line client.

![](/files/-MfJPBLWHxTSBA9NgAKU)

## Why Electrode Native ?

Electrode Native was created to answer the challenges of pluging React Native components in an existing native application code base. Tackling this manually, from scratch, is possible, but is unfortunately minimally documented. Moreover, dealing with this problem is an way that is as univasive as possible for the existing native application, is even more challeging.

Electrode Native takes on those challenges by providing an open source platform that reduces the friction for both React Native developers and mobile application developers. Using the Electrode Native platform, developers can use their knowledge without having to drastically change their workflow to accommodate the integration of multiple React Native components in their mobile application(s).

React Native allows JavaScript developers to leverage their knowledge of React / React Native and to use a single JavaScript code base to develop mobile applications targeting multiple platforms. React Native also give developers the power to transparently update their code as over the air (OTA) updates without having to go through the standard store release process and delays-not to mention actual adoption of updates by the users.

React Native can (seemingly) also be used to build and reuse some components written in React Native--and "plug" them into existing mobile applications. However, this capability is not yet widely adopted--primarily due to the friction of the required infrastructural changes as well as the absence of adequate tooling--either within the React Native platform itself or as third party tools to effectively help deal with this use case. The learning curve and investment required for mobile application developers who are working on a solution that actually works well for their mobile application, is often too much for many developers and development teams.

There are few solutions to this integration challenge and those that are available are not well documented enough-- most require additional tooling as well as infrastructure changes such as switching the mobile code base to a monorepo.

Electrode Native includes a well developed set of open source custom tools that successfully addresses this challenge.

Electrode Native allows JavaScript developers to work on their own React Native based components, called MiniApps--from within their dedicated repository, using their own release lifecycle. The MiniApps can be published and reused within potentially any mobile application. Existing JavaScript React Native developers will experience little change to their workflow.

Electrode Native allows Mobile application developers to easily integrate individual React Native components within their existing mobile application--without changes to their infrastructure or the need to deal with or install any JavaScript based tools--not even Electrode Native itself!

Electrode Native provides mobile application developers a single third-party library known as the "Electrode Native Container". The container includes all their MiniApps and developers interact with it as they would with any other third-party native library. If you need to update a MiniApp version or add new MiniApps to your container, all it takes is triggering a new container generation and publication. Developers only need to update the container version that is to be used within their mobile application.

The bottom line: Using Electrode Native, developers can concentrate on functionality and building their apps--without the hassles of reuse or integration issues.

### Electrode Native CLI (ern)

The Electrode Native (`ern`) CLI is a command line client containing commands that developers / devops, will use to work with the Electrode Native platform and generate artifacts that can be consumed by the mobile application. Some commands are similar to React Native commands. For example, instead of using the `react-native start` command, Electrode Native exposes the `ern start` command. For more information about using the Electrode Native CLI commands, refer to the Electrode Native CLI documentation.

[Learn More about the CLI](/reference/index-6)

### Electrode Native Bridge

The Electrode Native bridge is a cross-platform, low-level bi-directional communication library used to simplify communication between JavaScript and the native mobile application code. It is not part of the Electrode Native platform itself. The [Electrode Native bridge](https://github.com/electrode-io/react-native-electrode-bridge) is actually a React Native native module.

Even though the Electrode Native bridge is a standalone native module that can be used in any React Native projects *(even non Electrode Native based)*, if you are using Electrode Native, you won't have to directly interact with it in your MiniApps or in your mobile applications. Instead, you'll use Electrode Native APIs, that can be generated from a Swagger schema and will generate the code that you would have to write were you using the bridge directly.

[Learn More about the Bridge](/reference/index-5)

### APIs

At some point you'll need one or more React Native features to interact with your mobile application, to access data or to trigger an action. Or, your mobile application may need to interact with your MiniApps. That's where Electrode Native APIs come into play.

Powered by the [Electrode Native Bridge](https://github.com/electrode-io/react-native-electrode-bridge) and automatically generated by Electrode Native from a Swagger schema of your own, Electrode Native APIs provide clearly defined methods of communication between the native Android or iOS application and the JavaScript side.

[Learn More about the APIs](/reference/index-4)

### Container

The Electrode Native container is a native library similar to common third-party libraries that Android and iOS developers are familiar with. The container is generated entirely by the Electrode Native platform and packaged as an Android (AAR) library for Android and as a Framework for iOS.

The container includes Electrode Native engine initialization code as well as all the JavaScript React Native MiniApps that you want to include in your mobile application, along with all their native dependencies and assets.

Each mobile application will have its own custom Electrode Native container.

[Learn More about the Container](https://github.com/electrode-io/electrode-native/tree/4365979177cd88285ea1dabc57c271c54bd4f349/docs/platform-parts/container/index.md)

### Cauldron

A Cauldron is a centralized document database that is used to store information about mobile application versions, native dependencies, and information about MiniApps. There is one Cauldron per mobile application. With appropriate permissions, you can use the Electrode Native CLI commands to access and modify the data stored in a Cauldron.

Setting up a cauldron boils down to creating a Git repository. To host your cauldron, you can use any provider offering Git repository storage. GitHub, GitLab and Bitbucket are some of the most popular providers. In our documentation, we refer to GitHub but you are free to use the provider of your choice.

[Learn More about the Cauldron](/reference/index-1)

### Manifest

While the Electrode Native cauldron makes sure that no misaligned or non-supported native dependency version makes it into your mobile application--the Electrode Native manifest is used to align native dependency versions across multiple MiniApps in the first place.

The Electrode Native platform stores its master manifest in a GitHub repository. The master manifest is public and open sourced so that anyone can add native dependency support. By default, Electrode Native relies on the master manifest. For more advanced use cases, it is possible to override the master manifest with your own.

[Learn More about the Manifest](/reference/index-2)

### Runner

The Electrode Native platform contains two runners, one for each mobile platform (Android and iOS). Both runners are very simple and light-weight mobile applications--similar to new application projects in Android Studio or Xcode.

The Electrode Native runner application is used to run your MiniApp standalone so that you can effectively develop, debug, and test your MiniApp--before releasing a new or updated version of the MiniApp.

An Electrode Native runner application is automatically generated the first time you use the Electrode Native `ern run-ios` or `ern run-android` commands for your MiniApp. Relative to your MiniApp root directory, the runner application is generated in new Android and iOS directories.

[Learn More about the Runner](/reference/index-3)


# What is a MiniApp

A MiniApp is a JavaScript React Native application. That's mostly it!

We made the choice to distinguish a MiniApp from a full-fledged React Native application considering that a MiniApp is not a complete application on its own, but rather a "mini" application that can be composed with other MiniApps to form parts of a mobile application.

* A MiniApp is a JavaScript React native project representing a specific feature or component.
* A MiniApp can be a single, simple UI component with minimal logic or it can be a single page application that includes business logic and can communicate with the native side.
* A MiniApp can be a multi-page application containing a complete application feature.
* A MiniApp can be shipped and updated inside a mobile application, either included as a native container for in-development mobile application version or as an Over The Air (OTA) update for released mobile application versions.
* A MiniApp can be headless, meaning that it can only contain business logic that is invoked by the mobile application through exposed Electrode Native API(s).

## As a JavaScript developer, what does a MiniApp mean to me?

As a JavaScript developer, it means that there is no real change to your workflow or your current knowledge of React Native. You'll continue to write JavaScript, you'll continue to use React Native framework and, you'll be able to use third-party JavaScript packages in your application. In fact, developing a MiniApp is mostly exactly the same as developing an application or component using React Native on its own.

While your actual coding experience won't change, the CLI commands you'll interact with will be slightly different. Some of the commands from the React Native CLI have been replaced with a few Electrode Native CLI commands.

For example, instead of running the `react-native run-ios` command to launch your React Native MiniApp inside an iOS simulator or real device, you will use the `ern run-ios` command.

Instead of using the `react-native start` command, you'll use the `ern start` command. Most of these commands will actually invoke the associated React Native commands, but the Electrode Native CLI commands perform additional platform-specific logic. Also, you won't have to use the React Native `react-native link` command due to the fact that supported native dependencies will be automatically linked.

## As a mobile developer what does a MiniApp mean to me?

As a mobile app developer, you won't directly deal with the JavaScript MiniApps. Selected MiniApps are packaged inside the Electrode Native container library that you'll add to your mobile application project. The container includes the MiniApps as native Views that you can embed inside their own `Activities` on Android and `ViewControllers` on iOS--and launch them when appropriate, based on your overall mobile application UX flow.

Interactions and communication between the MiniApps and your mobile application are conducted using APIs that are also part of your container. The APIs can be consumed in your mobile application in a way that is very intuitive and mobile-development friendly--while also leveraging a high degree of type-safety at compile time.

## Considerations and MiniApp recommendations

There are a few considerations and recommendations that you want to read about before using Electrode Native.

**Navigation**

* Because your MiniApps will be integrated in a mobile application, the navigation flow needs to be natively handled. Every new MiniApp has a dependency on [ern-navigation](https://github.com/electrode-io/ern-navigation).

**Third-party native modules**

* The Electrode Native platform offers support for third-party React Native native modules that do not require JavaScript React Native developers to actually use any command to properly link native modules with their MiniApp.

  However, the Electrode Native platform also does not support "all" third-party native modules. Each native module needs to be listed in the platform manifest and configurations must be modified so that the native modules can be properly injected into any container.

  Considering that the [Electrode Native master manifest](https://github.com/electrode-io/electrode-native-manifest) is a public GitHub repository, and is not bound to a specific platform release lifecycle--anyone can contribute to it in order to add new native module support for their own--as well as any other developer's use!


# Electrode Native workflow

There are three main stages in the Electrode Native workflow:

* Stage 1: Create MiniApps
* Stage 2: Add or Update MiniApps
* Stage 3: Integrate MiniApps in a mobile application

Each stage requires different developer roles and expertise. Depending on the size of your organization or how your teams are structured, some developers may play a key role in one or more stages.

Please note that the worfklows described below are for illustration purposes only, and can serve as a basis to create your own workflow.

## Stage 1: Create MiniApps

**Actor(s)** JavaScript React Native Developer(s)

Everything starts with one or more MiniApps.

MiniApps are typically developed by JavaScript developers--having some experience *(or looking towards gaining experience)* on front-end applications written in JavaScript--using React or React Native.

Experienced React Native developers won't notice much difference compared to their familiar React Native application development workflow. The Electrode Native workflow is very similar to the React Native workflow and most of the Electrode Native CLI commands are the equivalent to React Native commands.

**Workflow for MiniApps development**

* Create a new MiniApp project using the Electrode Native `ern create-miniapp` command. This command is equivalent to the React Native `react-native init` command.
* Add JavaScript and/or native dependencies (platform APIs or supported third party native modules) to the MiniApp using the Electrode Native `ern add` command. This command is equivalent to the `yarn add` or `npm install` commands.
* Launch the MiniApp inside the Electrode Native platform runner mobile application. The runner allows you to develop, debug, and test the MiniApp standalone, using the `ern run-android` and/or the `ern run-ios` commands. These commands are the equivalent of the `react-native run-android` and `react-native run-ios` commands. Ideally you should also test your MiniApp in isolation, using this runner project.
* Propagate your MiniApp releases to the mobile client application(s). You can either publish your MiniApp releases to npm or just let Electrode Native pick the changes from git branches or tags.
* Optionally, debug and test your MiniApp within the target mobile applications and not on its own in the platform runner. Since your MiniApp may co-exist with other MiniApps in the same mobile application, you will use the Electrode Native `ern link` and/or `ern unlink` and the `ern start` commands to help you in this use case.

## Stage 2: Add or Update MiniApps

**Actor(s)** Release Manager(s) / Mobile Application Lead(s) / DevOps

At Stage 2, you choose the MiniApps (and their versions) that you want to add to your mobile application.

Depending on your organizational structure and development operations, Stage 2 might be handled by a dedicated Release Manager or Mobile Application Lead. In some cases, Stage 2 could also be handled by MiniApps Developers.

This stage also includes shipping updated versions of MiniApps using Over The Air (OTA) updates through CodePush.

Most of the dependency versioning control of the platform takes place in Stage 2. This is also when the cauldron, manifest, and container generator also work hand in hand.

Stage 2 involves interacting with the Electrode Native cauldron commands.

**Workflow for adding or updating MiniApps to/in a mobile application version**

* Create new mobile application versions in the cauldron using the Electrode Native `ern cauldron add nativeapp` command. This command needs to be potentially issued for each new mobile application version.
* Add, Remove, and Update MiniApps for a target in-development mobile application version (shipped in a container) using the `ern cauldron [add/del/update] miniapps` commands.
* Add, Remove, and Update native dependencies for target in-development mobile application version using the `ern cauldron [add/del/update] dependencies` commands (shipped in a container)

**Note** Native dependencies that MiniApps directly depends on are automatically added to the container when adding or updating a MiniApp version to a given mobile application version. This workflow item is therefore limited only to native dependencies that no MiniApps are actually depending upon--usually to add standalone native API implementations.

* Update the release status of mobile application versions using the `ern cauldron update nativeapp` command.

Flagging a mobile application version as being released, actually 'freezes' the mobile application version--to disallow any new changes to the native dependencies; you cannot update native code OTA. It will activate a CodePush for this mobile application version, allowing you to effectively push JavaScript changes of MiniApps as OTA updates.

* Add or update MiniApps versions using OTA CodePush updates using the `ern code-push` command.

## Stage 3. Integrate MiniApps in a mobile application

**Actor(s)** Mobile Application Developer(s)

Stage 3 does not require the use of the Electrode Native platform CLI commands. Mobile developers working at this stage do not need to install any JavaScript tools or even Electrode Native itself.

At Stage 3, Mobile Application Developers interact with the Container library only--which is shipped as an AAR file for Android, and as an umbrella Framework for iOS.

The container includes everything that is needed to launch and interact with the MiniApps. In addition to the MiniApps (stored in a composite single JavaScript bundle), the container also includes all the native dependencies needed by the MiniApps--including React Native.

Also included in the container are the MiniApps assets *(images and fonts mostly)* and the initialization code-- to call from your mobile application to initialize the container and get access to the MiniApps stored within.

**Stage 3: Workflow for integrating MiniApps in a mobile application**

* Add a dependency to your container library in your mobile application.
* Add the required code to properly initialize the container.
* Bump the container version every time it gets regenerated--that is any time a new MiniApp (or native dependency) is added, removed, or updated.
* Launch the MiniApps when needed in your mobile application UX flow.
* Implement APIs in the mobile application itself if necessary--this is not the recommended way for implementing native APIs, but might be necessary in some use cases.

## Bonus Stage: Generate and implement APIs

**Actor(s)** JavaScript React Native Developer(s) and Mobile Application Developer(s)

This stage is very similar to Stage 1: Create MiniApps, but it can be performed by either JavaScript React Native Developers or Mobile Application Developers--depending on whether the implementation of the API is done on the JavaScript side or the native side. This stage may be performed by JavaScript React Native Developers--on the JavaScript side, or Mobile Application Developers--on the native side.

APIs facilitate secure interaction and communication between your MiniApps and your mobile application:

* For MiniApps, a native API can be consumed to access data or functionality from the native side or it can be used to trigger actions on the native side.
* For a Mobile Application or another MiniApp, a JavaScript API can be consumed to access data or functionality from the JavaScript side, or it can be used to trigger actions on the JavaScript side.

**Workflow for generating and implementing APIs**

* Create a new API using the `ern create-api` command. The complete JavaScript, Android, and iOS client API code is generated along with optional models. All you need to do is then to published the generated API version on npm. The API code should not be modified. The implementation of the API is kept separate as is the code you actually will need to do on your own. We keep implementation separate from the API itself to ease regeneration and to allow for multiple implementations--that can be easily switched depending on your context, for example, development vs production.
* Update an existing API using the `ern regen-api` command. This should be done if you are adding new requests, events, or models to your existing API. Simply update the Swagger schema accordingly and invoke the command. You can then publish this new version of the API to npm.
* Implement an API. Because API generation and implementation are decoupled, the developer generating the API might not be the developer actually implementing it. You can kickstart an API implementation project using the `ern create-api-impl` command. Then, add the code implementing the API functionality--either as a native implementation (which can then be consumed by any MiniApp depending on this API) or as a JavaScript implementation (which can be consumed by any MiniApp or Mobile Application depending on this API). Implementations can be standalone (not bound to a specific mobile application or MiniApp), which is the recommended approach. Implementations can also be directly done in the mobile application or MiniApp.


# Native dependencies management

The term "native" as used throughout the Electrode Native documentation, means any code that is compiled and executed inside the mobile application itself--not in the JavaScript virtual machine. This is a departure from the common meaning of "native" meaning C/C++ code to most mobile developers.

This means that native app encapsulates code written in C/C++/Java/Kotlin on Android, and C/C++/ObjectiveC/Swift on iOS. This helps us easily distinguish between the JavaScript code itself and the mobile native code.

The JavaScript code itself is executed inside the JavaScript virtual machine and it can be updated using OTA updates. The native code is part of the binary of the application and cannot be updated using OTA updates.

## Why the need for native dependencies management?

Electrode Native includes support for managing, tracking, and controlling the versions of the native dependencies that MiniApps depend on. The reason behind this support is that while JavaScript applications can contain multiple versions of a given dependency in their dependency graph, mobile applications can't achieve the same for their native dependencies.

For example, React Native itself will be a native dependency of the mobile application. It contains some native code that is going to be compiled and shipped within the binary of the application. Given that it is a native dependency, there can be only one version of it included in the mobile application at any given time. An iOS or Android mobile application cannot include two versions of the same native dependency. To illustrate this, A mobile application cannot contain React Native 0.42.0 and React Native 0.43.0 at the same time. This is not a restriction of Electrode Native, nor React Native, but just the way mobile applications work regarding native dependencies.

On top of React Native itself, other native dependencies used by MiniApps can be either third-party React Native native modules supported by the platform (`react-native-code-push`, `react-native-vector-icons`, or `react-native-maps` for example) or can be platform-generated APIs or API implementations.

Because of this constraint and the fact that the Electrode Native platform allows you to package multiple MiniApps from different repositories into a single native library, Electrode Native offer support to help align the native dependency versions across all MiniApps as well as guarantees that no MiniApp with a non-aligned native dependency version will make its way into your mobile application.

This support is provided through two modules of our platform: the Electrode Native manifest and the Electrode Native cauldron.

## The Electrode Native manifest

The manifest is a GitHub repository containing data used by Electrode Native. The data can be updated at any time without having to wait for the next platform release.

This section describes the `manifest.json` file that is stored in the Electrode Native manifest repository.

The `manifest.json` file contains a list of native dependencies along with their versions that all of your MiniApp(s) should be aligned on. When you use the `ern add` command to add a JavaScript or native dependency to a MiniApp, Electrode Native queries the manifest to check if the native dependency is present in the `manifest.json` file. If the dependency is declared in the manifest, Electrode Native installs the specific version listed in the `manifest.json` file. If the dependency is not part of the manifest, then Electrode Native will issue a warrning.

Electrode Native also queries the manifest repository whenever you use the `ern create-miniapp` command to know which version of React Native to use.

Thus any MiniApp developed with Electrode Native and using `ern add` command to add dependencies, will be properly aligned to the same native dependencies versions. Please note that not using `ern add` will not cause issues, as long as you ensure that the native dependencies versions in your MiniApps package.json are aligned.

By default, Electrode Native will query the [master public manifest](https://github.com/electrode-io/electrode-native-manifest/blob/master/manifest.json) that is maintained by our core team for any open source native dependency. Electrode Native also allows to override the master manifest with your own private manifest. This is helpful if you also work with private, non-open sourced native dependencies or if you want to use different dependencies versions alignments.

[Learn more about the manifest](/reference/index-2)

## The Electrode Native cauldron

The Electrode Native cauldron is also a GitHub repository and at its core is the `cauldron.json` file. However, unlike the manifest, the cauldron should not be updated manually. The cauldron should only be accessed and updated using the `ern cauldron` subcommands. The cauldron repository will also be your own, as a cauldron is bound to a mobile application.

The cauldron is a simple document database, which doesn't come with the downside of having to install and set it up on a dedicated box, as it is just hosted in a git repository.

For each mobile application version, there will be a corresponding entry in the cauldron database. For example, `Walmart iOS 17.14` or `Walmart Android 17.10.0`. The cauldron stores specific information pertaining to each version of your mobile application, mostly the following :

* A list of all the MiniApps *(and their versions)* that are part of any given version of your mobile application(s))
* A list of all native dependencies *(and their versions)* used by these MiniApps

This is mainly all what's needed for Electrode Native to generate a container library.

Every MiniApp that needs to be added to your mobile application will first need to be added to the cauldron. The cauldron, in addition of keeping track of what is included in your mobile application versions, also acts as a "gatekeeper" to verify native dependencies versions before adding a MiniApp version to a Container (or deliver it through an OTA update).

Because the cauldron verifies which MiniApps versions and native dependencies versions are part of any given mobile application version, it can perform necessary version control checks whenever a MiniApp needs to be added to a mobile application version. Before allowing entry of the MiniApp in the cauldron, checks are performed to ensure that the versions of the native dependencies used by the MiniApp do not conflict with current native dependencies included in the targeted mobile application version. This should not happen often if MiniApps are correctly created based on a manifest--but this can happen, so we prefer to be extra cautious and perform final checks at the cauldron level.

All OTA MiniApps updates move through the cauldron first as well so that Electrode Native verifies whether or not it contains any conflicting native dependencies versions with the targeted mobile application version.

[Learn more about the cauldron](/reference/index-1)


# JS/Native communication

MiniApps *(written in JavaScript)* are running inside a JavaScript virtual machine. They don't have direct access to the mobile application data and can't directly invoke methods in the mobile application. Likewise, the mobile application doesn't have direct access to the MiniApp(s) code.

React Native offers constructs to communicate between the JavaScript side and the native side using its internal bridge, mostly through native modules.

Electrode Native allows the reuse of existing React Native native modules but also comes with its own bridge, which is just an additional library sitting on top of the existing React Native bridge, to expose simpler constructs and handle type safety.

The [Electrode Native Bridge](https://github.com/electrode-io/react-native-electrode-bridge) offers bi-directional communication constructs exposed as events and requests/response messages. Although the [Electrode Native Bridge](https://github.com/electrode-io/react-native-electrode-bridge) can be used directly in your mobile application or MiniApp to ease communication between the two sides, it is still a low level library. You will primarily use APIs, that are using the bridge under the hood, instead of interacting directly with it.

## Electrode Native APIs

You can create and distribute your own Electrode Native APIs or re-use existing APIs.

While Electrode Native APIs are similar in some way to React Native native modules *(which you can also create -or reuse-)* we don't recommend that you create new native modules if you plan on using Electrode Native. As a best practice, we recommend that you create APIs due to the advantages of using APIs over native modules in the Electrode Native ecosystem.

### Advantages of using APIs

* APIs are fully generated Just define the interactions your API should offer (as events and requests) in a Swagger schema, and the API code will be generated for JavaScript, iOS, and Android.
* APIs support the generation of model classes Just define the models in your Swagger schema and the necessary classes will be generated. Relying on the [Electrode Native bridge](https://github.com/electrode-io/react-native-electrode-bridge) support means that on the mobile application side, developers will be able to work with typed model classes and leverage compile time checks when dealing with Electrode Native APIs.
* APIs decouple the client code of the API from its implementation You can implement the API on the native side or the JavaScript side. Because of this decoupling, it is also possible to write multiple implementations for a single API.
* APIs are not native modules, they are clients of the [Electrode Native bridge](https://github.com/electrode-io/react-native-electrode-bridge) which is the native module. There is no react native linking needed for APIs.
* APIs are generated and therefore will follow a similar file system structure. This means that APIs don't need any customized configuration to be written for Electrode Native to properly add them to a container.
* APIs are expected to follow a certain versioning convention, which offers more flexibility in terms of compatibility checks between different versions.


# Requirements

* Node.js >= 12
* Git
* Android Studio (for Android apps)
* Xcode >= 10 (for iOS apps)
* CocoaPods (if using a version of React Native >= 0.60)

## [Node](https://nodejs.org/en/)

Electrode Native is a Node.js application therefore, Node.js 12+ must be installed on your workstation.

## [Git](https://git-scm.com/downloads)

The `git` command line client must be present on your workstation and declared in your PATH *(i.e running `git` from a terminal, should not fail with "command not found" error)*

Electrode Native is relying on the `git` client for [Cauldron](/reference/index-1) and [Manifest](/reference/index-2) access.

## [Android Studio](https://developer.android.com/studio/index.html)

[Android Studio](https://developer.android.com/studio/index.html) is required if you are targeting Android platform.

After you install Android Studio, set the `ANDROID_SDK env` variable to point to the location of the Android SDK--if it has not been set already. An example of the SDK path is shown below.

```bash
$ export ANDROID_SDK=/Users/[YOUR_USER_NAME]/Library/Android/sdk
```

## [Xcode](https://developer.apple.com/xcode/)

[Xcode](https://developer.apple.com/xcode/) is required if you are targetting iOS platform.

**Xcode 10** or later version is required.

## [CocoaPods](https://cocoapods.org/)

If running Electrode Native on a Mac, and using a version of React Native >= 0.60, CocoaPods install is required even if only targeting Android platform.

## Additional optional requirements

If your workflow involves pushing OTA updates using CodePush, you'll need to have an account setup for CodePush.

## What about React Native ?

You don't need to have React Native installed on your machine. If you have it already installed, that's great--it's not really a problem. The same applies for Yarn and CodePush.


# Upgrading Electrode Native

This section describes how to upgrade and activate a new version of Electrode Native.

## Platform versioning

**Feature releases** We bump the minor version for each of these releases, for example, `0.5.0`, `0.6.0`, `0.7.0`, etc..

**Maintenance releases** Maintenance releases may be released in-between features releases. A maintenance release is identified by a patch version bump, for example: `0.5.1`, `0.5.2`, etc.

The intent of maintenance releases is to fix major bugs, having no workaround, that may impact multiple users. A maintenance release helps users so that they don't need to wait for the next main release.

## Upgrading to a new platform version

Upgrading the platform is actually quite easy, its just a matter of running an `ern` command. That being said, before upgrading to a new platform version, you should always read the [release notes](https://github.com/electrode-io/electrode-native/releases) associated to the version.

Indeed, while we will do our best to retain backward compatibility, some new versions might contain `breaking changes` that could impact your current workflow.

### Before you upgrade

When you upgrade to a newer version of Electrode Native, previous installed versions of Electrode Native remain on your system; an upgrade does not overwrite the older versions.

Before you upgrade to a newer version of Electrode Native, read through the following upgrade guidelines:

* Be sure to read the [release notes](https://github.com/electrode-io/electrode-native/releases) of the new version.
* An upgrade is usually backward compatible although backwards compatibility with every release is not guaranteed. Check to see if upgrading will impact your current workflow.
* Electrode Native contains a built-in platform version management system--similar to what [nvm](https://github.com/creationix/nvm) uses for `Node.js`, allowing to keep multiple versions of the platform installed on the local system. The system allows easy rollback to a previous platform version or to actually switch back to an older version for some use cases.
* Only one version of the platform can be active at any given time.

### To install and switch to a specific version of Electrode Native

* Use the `ern platform use` command to install and switch to a specific version.

## Related commands

`ern platform install` | Used to install a specific version `ern platform uninstall` | Used to uninstall a specific version `ern platform versions` | Used to list all currently available platform versions. Versions that are installed locally and the active version are highlighted.


# Contributing

Please check our main [CONTRIBUTING.md](https://github.com/electrode-io/electrode-native/blob/master/CONTRIBUTING.md) document for details.


# Composite

## Electrode Native Composite

The Composite is a JavaScript project that is used by Electrode Native to combine all MiniApps (and optional JS API Implementations) in a single JS bundle.

A Composite project is created behind the scene, in a temporary directory, every time a Container is generated, and Electrode Native will run `react-native bundle` on this Composite project to create the JS bundle and assets to store in the Container.

Electrode Native will also create a Composite when using [ern start](/cli-commands/start) command, to assemble all MiniApps together and launch the react native local packager (`react-native start` on this Composite).

You can also manually generate a Composite project, with the [ern create-composite](/cli-commands/create-composite) command.

## Babel support

Electrode Native has support for using Babel plugins in MiniApps. Babel support is still in an early phase and will be improved and simplified over time. To enable proper Babel support for a MiniApp, here are the requirements :

* Have a `.babelrc` file at the root of the MiniApp, containing the Babel configuration. Electrode Native doesn't support `babel.config.js` which is appropriate for a top level babel configuration, but given that the MiniApps will end up inside a Composite, they won't be top level anymore.
* Set `useBabelRc` to `true` in the `ern` section of the MiniApp `package.json`, as follow :

  ```javascript
  "ern": {
    "useBabelRc": true
  }
  ```

  This is required so that Electrode Native can let Babel know that this MiniApp should be added to the [babelrcRoots](https://babeljs.io/docs/en/options#babelrcroots).
* Make sure that all Babel plugins used by the MiniApp are inside the `dependencies` sections of the `package.json` rather than `devDependencies`. This is not the standard, and can look unclean, however it won't have any nasty side effects. The reason for this constraint is that when Electrode Native generates a Composite with one or more MiniApp(s) it `yarn add` (`npm install`) each of the MiniApps in the Composite project, which does not install any `devDependencies` of the the MiniApps. Therefore, if Babel plugins are kept inside `devDependencies` they won't be installed during Composite generation, and bundling/packaging will fail when trying to resolve babel plugins.

### Note for [babel-plugin-module-resolver](https://github.com/tleunen/babel-plugin-module-resolver)

If this plugin is being used, in the Babel plugin config (in `.babelrc`) the [`cwd` option](https://github.com/tleunen/babel-plugin-module-resolver/blob/v3.2.0/DOCS.md#cwd) should be set to `babelrc`. This is needed, otherwise the base directory for `root` will resolve to top level composite rather than the MiniApp root directory.

### Note regarding BABEL\_ENV

React Native Metro bundler will [force set `BABEL_ENV`](https://github.com/facebook/metro/blob/fcb096d3286c67cac8a727c23f1e97be98a04cf5/packages/metro-react-native-babel-transformer/src/index.js#L152-L154) environment variable during transpilation to one out of only two values : `development` or `production`. Keep that in mind if using the [`env` option](https://new.babeljs.io/docs/en/next/babelrc.html#env-environment-option) in a Babel configuration. Whatever value is manually set for `BABEL_ENV` will be overwritten during transpilation by Metro bundler.

`development` will be set for any development bundle (local packager for example) and `production` will be set for any production bundle (bundle that we store in Container).

## Selective dependency resolutions support

Because Electrode Native uses [yarn](https://yarnpkg.com) under the hood to generate the Composite project, it also supports yarn [selective dependency resolutions](https://yarnpkg.com/lang/en/docs/selective-version-resolutions/) feature. This feature allows you to force version resolution of selected dependencies to specific versions. It can be very useful in certain context. For example if a deeply nested package that you don't have direct control on is breaking because a newer version has a bug, you can easily force the use of a previous version while waiting for package maintainer to publish a new version of it. Resolutions configuration can be done in the `compositeGenerator` config in the Cauldron. It can also be supplied directly to some commands such as `run-android`/`run-ios` or `create-container` via the `--extra` object option. The `resolutions` field is a 1:1 mapping to the `resolutions` field that will be added to the `package.json` of the composite. Refer to the [selective dependency resolutions](https://yarnpkg.com/lang/en/docs/selective-version-resolutions/) documentation for more information.

```javascript
"config": {
  "compositeGenerator": {
    "resolutions": {
      "d2/left-pad": "1.1.1",
      "c/**/left-pad": "1.1.2"
    }
  }
}
```

Please note that this configuration will be ignored if you are using a custom composite. Because a custom composite offers full control of the Composite project, it is the responsibility of the custom composite project maintainer to manually add `resolutions` to the `package.json` of the custom composite.

### Custom `extraNodeModules` in Metro config

Custom entries to the `resolver.extraNodeModules` property in `metro.config.json` can be added via the `metroExtraNodeModules` field. It supports both relative and absolute paths. Relative paths will resolve to `node_modules` inside the Composite project.

```javascript
"config": {
  "compositeGenerator": {
    "metroExtraNodeModules": {
      "pkg-a": "@scope/new-pkg-a",
      "pkg-b": "/absolute/path/to/new-pkg-b"
    }
  }
}
```

Similar to selective dependency resolutions described above, custom extraNodeModules are only supported for a full composite. When using a custom composite, `metro.config.json` should be modified directly.

## Note in regards to local `.npmrc`

When generating a Composite, Electrode Native will not consider any local `.npmrc` file present in the root of a MiniApp. This is due to the fact that when generating a Composite project, Electrode Native just `yarn add` every MiniApp to the Composite project. Each MiniApp becomes a dependency of the Composite project and is not a top level app anymore. Therefore, when needing a custom `.npmrc` configuration, the `.npmrc` should be global rather than local, or be part of a custom Composite project (see below).

## Using a custom Composite

In the majority of cases, there is no need to create a custom composite, as Electrode Native comes with a built-in one. However in some specific cases, having more control on the Composite project is needed. For example, you might want to add some custom initialization code for the whole bundle, or you might want more control on some configuration files (`rn-cli.config.js`/ `metro.config.js`/`babel.config.js`).

Setting up a custom Composite project (also known as a base Composite) for Electrode Native is relatively straightforward.

This can be achieved in two steps:

1. Create the Composite git repository
2. Configure Electrode Native to use custom Composite rather than the one built-in

### Create the custom Composite git repository

This git repository should just contain a basic React Native project structure. You can create your own, or copy our [starter custom composite](https://github.com/electrode-io/ern-base-composite-starter).

For example this is the basic file structure of our sample bare custom Composite:

```
.
├── babel.config.js
├── composite-imports.js  [GENERATED/OVERWRITTEN]
├── index.js              [REQUIRED]
├── metro.config.js
├── package.json
└── rn-cli.config.js
```

There are two important things -as of now- to be aware of, when creating a custom Composite project :

1. `index.js` is required. This will be the entry file used when running`react-native bundle`/`react-native start`.
2. `composite-imports.js` will be generated by Electrode Native. It will contain all of the MiniApps / JS API Impls imports. You have to import this file in `index.js` at some point, otherwise your MiniApps won't be packaged in the bundle. Keep in mind that this file, if present in the repo, will be overwitten by Electrode Native during composite generation, so don't put custom imports or code in this one.

Also, the `name`/`version` in the `package.json` and other fields that only matter for npm publication can be left to dumnmy values. This Composite project is not meant to be published to npm but solely used to create the Composite JS bundle.

### Configure Electrode Native to use custom Composite

Once the custom Composite project is created, and published to a git repository, the next step is to configure Electrode Native so that it relies on this custom Composite project rather than its own.

#### Through Cauldron

If you want to use a custom Composite repository `custom-composite` stored in GitHub under user `username`, your `compositeGenerator` configuration should be as follow :

```javascript
"config": {
  ...
  "compositeGenerator": {
    "baseComposite": "git+ssh://github.com/username/custom-composite.git"
  }
}
```

It is also possible to specify a specific branch/tag or SHA. For example, using the same repository, but pulling from `mybranch`, the configuration will be the following :

```javascript
"config": {
  ...
  "compositeGenerator": {
    "baseComposite": "git+ssh://github.com/username/custom-composite.git#mybranch"
  }
}
```

As for all configuration stored in the Cauldron, there is no way yet to add or edit the configuration using `ern` commands. You should manually edit your Cauldron. Also, as a reminder, `config` objects can be stored at different levels in the Cauldron, respectively :

```
. Root
|_ Native Application
  |_ Native Application Platform
    |_ Native Application Version
```

depending on the level of granularity you desire. For exmaple, when looking for configuration for `MyApp:android:1.0.0`, Electrode Native will first look for a `config` object at the native application version level, and if not found will bubble up the levels until it finds it (or doesn't).

#### Through Commands

Electrode Native contains a few commands that are generating a Composite as part of their execution, and that can be used without relying on a Cauldron.

* [ern code-push release](/cli-commands/code-push/release)
* [ern create-composite](/cli-commands/create-composite)
* [ern create-container](/cli-commands/create-container)
* [ern run-ios](/cli-commands/run-ios)
* [ern run-android](/cli-commands/run-android)
* [ern start](/cli-commands/start)

These commands are exposing a `baseComposite` option being either a valid git repository path or a local path on the workstation to a custom composite project. Please note that using this option will take precedence over any `baseComposite` configuration stored in Cauldron. If you are using a Cauldron, there is very limited use to explicitly providing the `baseComposite` to these command.

This option can however be very useful for experimentation or to test a custom Composite project before committing it to git / using it in Cauldron. For example, if your custom Composite project is stored in `/etc/custom-composite` you can easily try it out with some of the commands above, before committing it to git / setting it up in Cauldron.

## Electrode Native internal flow with custom Composite

When detecting a custom Composite project, Electrode Native will do the following when generating the Composite :

* Clone the Composite repository to a temporary directory
* Checkout specific branch/tag/sha (if any specified)
* Run `yarn add` for all MiniApps / JS API Implementations part of the Composite (this will update the `package.json` of the Composite)
* Create the `composite-imports.js` file, containing all MiniApps/JS API Implementations imports.

This completes the Composite project generation. Optionally, based on the command used, `react-native bundle` or `react-native start` will be invoked with `index.js` as `entry-file` based on the platform being targeted.


# \[Container]


# Overview

A container is the end product of Electrode Native.

It is a native library, in the form of an AAR library for Android, and a Framework for iOS. It is composed of a single miniapp or a set of miniapps, and includes all of their supporting assets and dependencies *(JS and native)*.

The mobile application will only have to depend/interact with a single container library, as it encapsulates eveything that is needed to launch the miniapps. This is an important point, so let us emphasize it again.

**A mobile application will&#x20;*****(and can)*****&#x20;only depend on a single container. Composition of miniapps and container customization takes place at the container generation level to tailor a container to a specific target mobile application.**

Here is a high level diagram, giving a better idea of what's inside a container, along with some additional details.

![](/files/-MfJPBfbZ42GjOkhj_dh)

* **JavaScript Bundle** The JavaScript bundle is a single file, containing the JavaScript code of all the miniapps part of the container. It also includes all of the JavaScript dependencies *(packages)* that the miniapps depends on. This bundle is generated by Facebook Metro bundler, the default bundler used for packaging React Native applications. Electrode Native offers to package multiple miniapps, coming from different sources, in a single bundle. To achieve this, during container generation, Electrode Native will create a temporary JS project *(ERN composite)* that will include all the required miniapps. It will then run metro bundler on this intermediate composite project.
* **Assets** Represents all of the images, fonts and other assets that are used by the MiniApps. As in React Native projects, assets are not part of the JS bundle but are instead stored in the native project itself *(assets directory for Android, Resources for iOS)*. Also, as in React Native projects, Electrode Native relies on Metro bundler to generate the target file structure for the assets.
* **Native Libraries** All of the native libraries that are used by the miniapps. This includes React Native *(obviously)* along with all its native dependencies, but also the native code of all of the native modules that are being used by the miniapps.
* **ERN APIs** Represents all of the native code of any generated ERN API, as well as any ERN API standalone native implementation, that are being used by the miniapps.
* **ERN Initialization Code** Native Code that is exposed to mobile application to integrate a container. Mostly consist of initialization code, along with some utility code to interact with the miniapps.


# Generation

A container can either be `explicitly` or `implicitly` generated.

The only way to `explicitly` generate a container is to use the `create-container` command. On the other hand, a container will be `implicitly` generated whenever running some `cauldron` sub-commands such as `regen-container` or `add miniapps` *(and many other ones)*.

To be generated, what the container mostly need is a non empty set of miniapp(s) that may come from different locations *(local directory, npm, git repository)*.

Container generation goes through multiple steps in sequence, starting with composite generation, as illustrated below

![](/files/-MfJPBZ-9n9YgFJXMVPj)

## Composite Generation

The first step of container generation is actually to generate a composite project. Composite and composite generation is covered in a dedicated section of the documentation, but in a nutshell, the composite is a just a JavaScript project with miniapps as dependencies, and a single top level entry point that is just importing each of the miniapps. Electrode Native runs metro bundler on this composite project to create the final JS bundle.

## Compatibility Checks

After generating the composite project, Electrode Native will identify all native depencies *(APIs and native modules)* packages present in the composite and will perform compatibility checks to make sure that there is only one clear identified unique version of each native dependency. For example, if MiniApp A and B both use react-native-maps native module but with a different version, this step would fail.

## Setting up container template

This step is actually relatively straightforward. It just takes care of copying the container project template to the directory where the container will be generated *(output directory)*.

## Injecting native dependencies

This step is responsible for injecting all the native code into the container. The process is a bit different for Android compared to iOS. For Android, all the APIs, APIs native implementations and native modules code are injected into the container. This is because all of these components are not published to Maven, so can't be retrieved as regular maven dependencies in the build.gradle of the container. This is also the reason why a plugin configuration is needed in manifest for native modules, to let Electrode Native where the code of the nativem module is in, and what exactly to inject in the container. For iOS, thanks to CocoaPods injection *(starting with RN 61)*, we don't have to manually inject the code of native modules in the iOS container, but rather rely on CocoaPods, very similar to the auto linking mechanism used by React Native. This is also why iOS plugin configuration in manifest is relatively minimal, as the podspec of the native module takes the role of the plugin configuration.

## JS Bundling

Finally, Electrode Native will run Facebook Metro Bundler on the composite project, to generate the final JS bundle. The bundle output location passed to metro will be the correct target location in the container. The assets output path will also point to the right directory in the container, so that assets are properly injected in the container.

Once this process is completed, the generated container project will be accessible in the output directory. It can then be imported as-is in the client application, or can be further processed using container `transformers` and/or published using container `publishers`.


# Publication

A locally generated container is useful and necessary for example to launch a MiniApp in the Electrode Native runner, or for development and experimentation use, but to be used by a client mobile application, the container will have to be published somewhere.

Electrode Native offers multiple publishers to that end. Publishers are not shipped with Electrode Native but are instead available as independent npm packages that are installed and loaded on demand by Electrode Native.

All publishers have some configuration in common, for example the `url` where the container should be published, or the `container version` to publish. That being said, publishers also expose specific custom configuration that is their own. You should refer to the documentation present in the repository of the publisher(s) for additional details.\
Here is a list of current container publishers offered by Electrode Native :

* [**maven**](https://github.com/electrode-io/ern-container-publisher-maven)\
  This publisher can only publish Android containers. It will take care of building the container and uploading the resulting AAR artifact to a Maven repository of your choice.
* [**maven-cli**](https://github.com/electrode-io/ern-container-publisher-maven-cli)\
  This publisher can publish Android or iOS containers. It won't take care of building the Android or iOS container. It mostly exposed the `deploy:deploy-file` command of `mvn` to publish a pre-produced artifact *(zipped iOS fat framework for example)* to a Maven repository.
* [**jcenter**](https://github.com/electrode-io/ern-container-publisher-jcenter)\
  This publisher can only publish Android containers. It will take care of building the container and uploading the resulting AAR artifact to a JCenter repository.
* [**git**](https://github.com/electrode-io/ern-container-publisher-git)\
  This publisher can be used to publish an Android or iOS container to a remote git repository.
* [**cocoapods-git**](https://github.com/electrode-io/ern-container-publisher-cocoapods-git)\
  This publisher can be used to publish an iOS container as a CocoaPod to a remote Git repository.
* [**cocoapods-spec**](https://github.com/electrode-io/ern-container-publisher-cocoapods-spec)\
  This publisher can be used to publish the CocoaPods spec of an iOS container to a remote Git pod spec repository.
* [**fs**](https://github.com/electrode-io/ern-container-publisher-fs)\
  This publisher can be used to publish Android or iOS containers to a local directory.
* [**dummy**](https://github.com/electrode-io/ern-container-publisher-dummy)\
  This publisher is just a dummy publisher for illustration and debugging purposes. It won't publish the container anywhere, but will just log the configuration supplied to it.

It is possible to use more than one publisher for your container. For example, you can choose to publish your Android containers both to Maven and GitHub.

#### Using a publisher

There are two ways to use a `publisher`, either `explicitly` or `implicitly`.\
Based on your needs and your context, you might need one way or the other (or both).

**Explicilt publisher use**

Electrode Native offers the \[publish-container] command that can be used to publish a container.\
This commands does not require a cauldron.\
It cam publish any pre-generated *(and eventually transformed)* container.

It is possible to run the \[publish-container] command multiple times for the same container, to publish the container to different target repositories.

The use of the \[create-container] / \[publish-container] commands combo, will be mostly useful for development and experimentation with Electrode Native. It can also be used for automation purposes (CI) in some contexts.

**Implicit pulbisher use**

A publisher will be implicitly used when executing a container generation pipeline containing a publisher.

#### Configuring container publication

When explicilty publishing a container, using the `publish-container` command, the publisher configuration should be supplied on the command line. Extra configuration, specific to the publisher, can however kept in a separate json configuration file stored locally or in a cauldron. Refer to the `publish-container` command documentation for more information.

Container publishers can also be added to a container generation `pipeline`, stored in a cauldron, so that it can be shared across users of the Cauldron and automatically triggered whenever regenerating a container from cauldron, using cauldron subcommands.

#### Creating a custom Container publisher

As previously mentionned, Electrode Native container publishers are standalone node packages *(published to npm)* and retrieved dynamically \_(they are not packaged within Electrode Native itself). In that sense it is quite easy to implement *(and eventually distribute)* your own container publisher if needed.

Check our [dummy publisher](https://github.com/electrode-io/electrode-native/blob/master/docs/platform-parts/container/\[https:/github.com/electrode-io/ern-container-publisher-dummy/README.md) as a reference to get started.

A few things to keep in mind when creating a Container publisher :

* The package name must include `ern-container-publisher`. This is a convention for Electrode Native Container publishers, and is enforced by Electrode Native.
* You should add a keyword `ern-container-publisher` in the keywords list of the package.json. This is not required, but could be leveraged later on by Electrode Native to facilitate container publishers discovery.
* All you'll have to implement is a class with two getters `get name` (to return the name of the publisher) and `get platforms` (to return the list of supported platforms of the publisher), as well as the `publish(config)` method. This class should be the default export of the module.
* Once your Container publisher is published to npm, it will immediately be available for Electrode Native users. During development, if you need to try out your publisher before publishing it to npm, you can use `ern publish-container` command by using an absolute local file system path to your Container publisher module. `ern publish-container` will call either `index.js` (or `index.ts` as we support TypeScript) from your module directory root, or `src/index.js` if no index was found in root. Thus make sure to name your entry point as `index.js`/`index.ts`.


# Transformation

Electrode Native container tries to be as agnostic as possible so that it can be added to a client application without requiring any custom modifications.

That being said, in some cases, some tweaking or post-processing of the generated container project might be needed. For example, to update some build settings of the iOS container, or gradle settings of the Android container, or to transform the container in a more radical way *(for example transforming an iOS container to a pre-compiled fat binary framework)*. Because the container is generated by Electrode Native, any manual changes done post generation, would be overwritten by a new generation.

While it is totally possible to write your own transformers without relying on Electrode Native, for example just writing some automation scripts to perform your required transformations, we would recommend using Electrode Native transformers as it better fits in Electrode Native worfklow and can be used part in an Electrode Native pipelines. If you really need to run your own custom transformation script, you can use the \[script-transformer] that allows to run any arbitrary custom made script as a transformer.

As for publishers, transformers have their own specific configuration, that can be supplied directly to the `transform-container` command or inlined in a json configuration file part of a pipeline configuration.

Here is a list of current container transformed offered by Electrode Native :

* [**script**](https://github.com/electrode-io/ern-container-transformer-script)\
  This transformer can be used to run any arbitrary, custom made, executable script to transform the container.
* [**git-patch**](https://github.com/electrode-io/ern-container-transformer-git-patch)\
  This transformer can be used to apply a git patch on the generated container project.
* [**xcframework**](https://github.com/electrode-io/ern-container-transformer-xcframework)\
  This iOS only transformer can be used to transform the container project to an xcframework binary ready for distribution. It will take care of building the container project.
* [**build-config**](https://github.com/electrode-io/ern-container-transformer-build-config)\
  This iOS only transformer can be used to alter iOS build configuration settings of the container.
* [**pbxproj**](https://github.com/electrode-io/ern-container-transformer-pbxproj)\
  This iOS only transformer can be used to patch one or more pbxproj *(iOS project file)* included in the Container, in specific ways.
* [**dummy**](https://github.com/electrode-io/ern-container-transformer-dummy)\
  This transformer is just a dummy transformer for illustration and debugging purposes. It won't publish the container anywhere, but will just log the configuration supplied to it.

#### Using a transformer

There are two ways to use a `transformer`, either `explicitly` or `implicitly`.\
Based on your needs and your context, you might need one way or the other (or both).

**Explicilt transformer use**

Electrode Native offers the \[transform-container] command that can be used to transform a container.\
This commands does not require a cauldron.\
It cam transform any pre-generated container.

It is possible to run the \[transform-container] command multiple times for the same container, to chain transformation on the container.

The use of the \[create-container] / \[transform-container] commands combo, will be mostly useful for development and experimentation with Electrode Native. It can also be used for automation purposes (CI) in some contexts.

**Implicit transformer use**

A transformer will be implicitly used when executing a container generation pipeline containing a transformer.

#### Configuring container transformation

When explicilty transforming a container, using the `transform-container` command, the transformer configuration should be supplied on the command line. Extra configuration, specific to the transformer, can however kept in a separate json configuration file stored locally or in a cauldron. Refer to the `transform-container` command documentation for more information.

Container transformers can also be added to a container generation `pipeline`, stored in a cauldron, so that it can be shared across users of the Cauldron and automatically triggered whenever regenerating a container from cauldron, using cauldron subcommands.

#### Creating a custom container transformer

As previously mentionned, Electrode Native container transformers are standalone node packages *(published to npm)* and retrieved dynamically \_(they are not packaged within Electrode Native itself). In that sense it is quite easy to implement *(and eventually distribute)* your own container transforrmer if needed.

Check our [dummy transforrmer](https://github.com/electrode-io/electrode-native/blob/master/docs/platform-parts/container/\[https:/github.com/electrode-io/ern-container-transformer-dummy/README.md) as a reference to get started.

A few things to keep in mind when creating a Container publisher :

* The package name must include `ern-container-transformer`. This is a convention for Electrode Native Container transformers, and is enforced by Electrode Native.
* You should add a keyword `ern-container-transformer` in the keywords list of the package.json. This is not required, but could be leveraged later on by Electrode Native to facilitate container transformers discovery.


# Pipeline

After being generated, a container can go through a sequence of steps to either alter it in some way and/or publish it to some location. This process can be conceptualized as a pipeline.

Electrode Native expose two main building blocks for building pipelines : `transformers` and `publishers`. A pipeline can be composed of any number of these building blocks, in any order, as illustrated below.

![](/files/-MfJPCGkNInAZfOX33gj)

In this illustration, the first pipeline is the most basic one. It's actually an empty pipeline. Once the container is generated, it doesn't go through any further processing steps.

The second example illustrates a pipeline composed of a single `publisher` block, while the last pipeline intertwines multiple `transformers` and `publishers`.

`transformers` can be used to alter the container in some way *(resulting in changes in the generated container structure and/or files)*, while `publishers` are used to publish the locally generated container as-is to a specific location. `transformers` and `publishers` blocks are not shipped with Electrode Native, they are independent npm packages, and are dynamically installed and loaded on demand. The `transformers` and `publishers` blocks are further detailed in dedicated sections of the documentation.

Electrode Native offers three different ways to run a full pipeline, starting from container generation. Choosing one way or another depends of your project specifics and the envisionned overall workflow. Here are the three different approaches to execute `pipeline 3` depicted above :

**Manually sequencing ern commands**

Electrode Native CLI expose the `create-container` command to generate a container given a set of miniapps. It alos exposes the `transform-container` command to execute a transformer on a pre-generated container, and the `publish-container` command to run a publisher. Therefore, it is possible to sequence these commands to create a pipeline. To reproduce `piepline 3` above, you would for example run the following commands in order

* `create-container`
* `transform-container`
* `publish-container`
* `transform-container`
* `publish-container`

Any publisher or transformer extra configuration should be passed to the commands via the `--extra` option.

**Using a pipeline configuration**

Another way to run a pipeline, is to create a pipeline configuration represented in JSON. This configuration can then either be stored locally to the project, or in an Electrode Native cauldron. A `pipeline` configuration object is part of a `containerGenerator` configuration.

```javascript
{
  "containerGenerator": {
    "pipeline": [
      { "name": "transformer-a" },
      { "name": "publisher-b" },
      { "name": "transformer-c" },
      { "name": "publisher-d" }
    ]
  }
}
```

The `name` property should reference a real publisher/transformer npm package. Here, just for illustration purposes we don't use real ones. Also, apart from the `name` property, all transformers and publishers expose an `extra` property to provide configuration pertaining to the specific publisher/transformer. So in reality, the JSON configuration file will be more beefy than the one above.

Once this configuration is created and accessible locally or stored in a cauldron, the following commands can be run in sequence:

* `create-container` *(to generate the container)*
* `run-container-pipeline` *(to run transformers/publishers pipeline on the container)*

**Using a cauldron**

The last way to run a container pipeline with a single command, is to rely on a cauldron. As for the pipeline configuration approach detailed above, a configuration file have to be stored in the cauldron, to configure not only the pipeline, but also the container generator *(within the `containerGenerator` object)*. Once done, a single command can be used to generate the container and run the pipeline :

* `cauldron regen-container`

This command will take care of first generating the container using the configuration stored in the cauldron *(in the `containerGenerator` object, which also includes the `pipeline` configuration)* and will then run each steps of the pipeline.

The main difference between this approach compared to the other ones, is that using this command will target a specific application descriptor in cauldron, and will refresh the metadata associated to this descriptor in the cauldron *(think of it as a database update, updating any information that may have changed between this newly generated container and the previous one)*. The two previous approaches will not update anything in cauldron. They will just do their job locally and not deal with cauldron at all *(apart from optionally pulling configuration from cauldron in second approach)*.


# Integration

This section describes how to integrate an Electrode Native container in your Android or iOS mobile application.

**Android**

A Container library can be added to a mobile Android application project in one of two ways:

* By adding a dependency on the Electrode Native container AAR *(recommended way)*, or
* By directly adding the Electrode Native container module to the Android project (as a git submodule for example)

You will also need to update your `build.gradle` files with the following:

* `jcenter` repository

We publish the `react-native` Maven artifact to `jcenter`. Therefore, you must make sure that `jcenter` is present in your list of repositories. The repositories are most commonly defined in your top-level project `build.gradle`.

```groovy
repositories {
  jcenter()
  //...
}
```

* resolution strategy

React Native includes some third-party libraries that might conflict with the versions you are using. For example, you might have issues with `jsr305`. If that is the case, add the following to your application module `build.gradle`

```groovy
configurations.all {
  resolutionStrategy.force 'com.google.code.findbugs:jsr305:3.0.0'
  //...
}
```

In addition to the above resolution strategy for handling the `jsr305` conflict, you might also run into a conflict with `OkHttp`. React Native depends on a specific version of the very popular networking library, `OkHttp`. If you are using this library in your application, you might be forced to align your version of `OkHttp` with the version included with the React Native version that you are using. This is due to the current React Native design.

* okio linting

You might run into a conflict with the `okio` third party library which comes with React Native. It is a known issue. To resolve this issue, disable the lint check for `InvalidPackage`. You can also find solutions by searching for the `okio` conflict on the web.

```groovy
lintOptions {
  disable 'InvalidPackage'
  //...
}
```

**Adding the Container as an AAR**

If a Maven publisher has been configured in the Electrode Native cauldron, Electrode Native will package and publish the Electrode Native container project as a Maven artifact containing the AAR file(either to a local or remote Maven repository)

If you are implicitly publishing a container from a Cauldron (through a change in container content or the use of \[cauldron regen-container] command), the Maven artifact will have the following data:

* Group ID : `com.walmartlabs.ern`
* Artifact ID : `{mobile-app-name}-ern-container`
* Version string : `{container-version}`

{mobile-app-name} is the name of the mobile application in the cauldron for the Electrode Native container that is being generated. For example, if the application name is `walmart`, the Electrode Native container artifact ID will be `walmart-ern-container`.

{container-version} is the version of the generated Electrode Native container. The container version can be in the form: `x.y.z` where x, y and z are integers. For example `1.2.3` is a valid container version. You can specify a version for a Container or, by default, the current version will be patched-bumped to the new version.

To add a dependency on the Electrode Native container, in your mobile application add the following code to the `dependencies` object of your application module `build.gradle`. Be sure to substitute the `{mobile-app-name}` and `{container-version}` to represent your application.

```groovy
dependencies {
  api 'com.walmartlabs.ern:{mobile-app-name}-ern-container:{container-version}'
  //...
}
```

If you are explicitly publishing a container through the use of [publish-container](https://github.com/electrode-io/electrode-native/blob/master/docs/cli/publish-container/README.md) command, the Maven artifact id will be `local-ern-container`. The group id will remain the same though `com.walmartlabs.ern`. You can pass options to the command to change the artifact id and group id at your convenience. Please see [publish-container](https://github.com/electrode-io/electrode-native/blob/master/docs/cli/publish-container/README.md) documentation for more details. Also, if you use or plan to use a locally published Electrode Native container (to your maven local repository), make sure to declare `mavenLocal` in the list of repositories. This is located in the top-level project `build.gradle`.

```groovy
repositories {
  mavenLocal()
  //...
}
```

**Proguard**

Container library does not proguard itself, but supports proguarding. In your module's `proguard.txt` add the rule to be during the applications proguarding phase.

```
# keep rules for react-native-electrode-bridge
-keep class com.walmartlabs.electrode.** {*;}
```

**Adding the container as a Git submodule**

Alternatively, you can include an Electrode Native container in a mobile application by adding it as an Android module. Although this is not the recommended way to add third-party dependencies (the container being one) to an Android project, it is however possible and this might be the best process if you don't have a remote Maven repository that you can publish the container to.

To add the container library as an Android module, add a GitHub publisher to the cauldron (or use [publish-container](https://github.com/electrode-io/electrode-native/blob/master/docs/cli/publish-container/README.md) with the `git` publisher option). Then, when a new Container version is published, Electrode Native will publish the resulting project to a private or public GitHub repository. It will create a Git tag for each version of a container. You can then add the container Android module to your application project--managed as a Git submodule.

**Note** Do not edit the code of the container if you use this procedure even though adding the Container directly in your project makes its code editable. The container code should not be modified manually, as any custom modification will be lost the next time the container is generated.

Be sure to include the module in your project `settings.gradle`, and add a `api project` directive to your application module `build.gradle`. Find more information on [declaring API and implementation dependencies](https://docs.gradle.org/current/userguide/java_library_plugin.html)

**Configure Android build configuration versions**

The following android build parameters can be configured with application specific needs.

* `buildToolsVersion` - Android SDK build tools is a component of the Android SDK required for building Android apps. The version specified will update the app level `build.gradle`

  ```groovy
  android {
    buildToolsVersion "28.0.3"
  }
  ```
* `compileSdkVersion` - The API level designated to compile the application.
* `kotlinVersion` - The version of Kotlin to use for the container *(only used in case at least one Kotlin native module is injected in the container)*.
* `minSdkVersion` - The minimum API level that the application targets.
* `sourceCompatibility` - Defines which language version of Java your source files should be treated as. It can take a valid [Java Version](https://docs.gradle.org/current/javadoc/org/gradle/api/JavaVersion.html)
* `targetCompatibility` - Defines the minimum JVM version your code should run on, i.e. it determines the version of byte code the compiler generates. It can take a valid [Java Version](https://docs.gradle.org/current/javadoc/org/gradle/api/JavaVersion.html)
* `targetSdkVersion` - The designated API Level that the application targets

  ```groovy
    android {
      compileSdkVersion 28
      defaultConfig {
          minSdkVersion 19
          targetSdkVersion 28
      }
    }
  ```
* `supportLibraryVersion` - You may want a standard way to provide newer features on earlier versions of Android or gracefully fall back to equivalent functionality. You can leverage these libraries to provide that compatibility layer.

  ```grovy
  compile 'com.android.support:appcompat-v7:28.0.0'
  ```

You can configure `androidConfig` in the cauldron as show below.

```json
{
  "containerGenerator": {
    "androidConfig": {
      "buildToolsVersion": "28.0.3",
      "compileSdkVersion": "28",
      "minSdkVersion": "19",
      "supportLibraryVersion": "28.0.0",
      "targetSdkVersion": "28"
    }
  }
}
```

**Android Dynamic Feature Module Support**

If the Android client mobile application consuming the container is keeping the container dependency in an Android [dynamic feature module](https://developer.android.com/codelabs/on-demand-dynamic-delivery), there will be issues with resources loading *(your MiniApps images won't be visible for example)*. This is because of React Native Android implementation, that is loading some resources via reflection, using the base package name of the application, instead of the package name of the dynamic module [*see Android documentation for more details*](https://developer.android.com/guide/playcore/feature-delivery#resource-uri). For this reason we had no way but to fork React Native to update the implementation to properly handle this use case.\
Our fork of React Native is kept in [electrode-io/react-native](https://github.com/electrode-io/react-native) repository.\
We are only using it to publish special React Native AARs for Android, not for any iOS changes nor JS ones *(i.e we're not publishing anything to npm)*.\
Starting with 0.63 line, we will publish custom releases of the AAR, in addition to the official versions, to include support for dynamic feature modules. These versions will have a patch number starting at 100 *(0.63.100, 0.64.100 ...)*.

If you are facing this fringe scenario with dynamic feature modules, here is what can be done:

1. Generate the container with a custom AAR version of React Native that includes support for Dynamic Feature Modules.\
   This can be done by supplying such a configuration to the container generator *(via --extra option or through Cauldron config)*

```json
{
  "containerGenerator": {
    "androidConfig": {
      "reactNativeAarVersion": "0.64.100"
    }
  }
}
```

Always use the latest custom AAR version matching the React Native version line that your miniapps(s) are using *(for example if your miniapp is using 0.63.4, you should use 0.63.100 here)*.

2. Update the client application to pass the dynamic feature module package name to the container.\
   For example if the client application base package name is `com.foo` and the dynamic feature module containing the container dependency is named `bar`, the package name used for resources resolution in the dynamic feature module would be `com.foo.bar`.\
   In that case, the client application would need to call the following, prior to initializing the container.

```java
ElectrodeReactContainer.setPackageName("com.foo.bar");
```

**JavaScript Engine (RN 0.60 and above)**

Starting with React Native 0.60, the JavaScript engine is distributed separately from the React Native AAR. Also, prior to this version, JavaScriptCore was the only JavaScript engine that could be used on Android for React Native applications. Starting with this new version, it is now possible to use alternative JavaScript engines such as Hermes or V8.

Electrode Native currently support both JavaScriptCore and Hermes engines. By default, without explicit configuration, Electrode Native will use the non international variant of JavaScriptCore engine.

*JavaScriptCore*

With React Native 0.60.0, JavaScriptCore engine now comes in two variants : `android-jsc` and `android-jsc-intl`. The later is the international variant. It includes ICU i18n library and necessary data allowing to use e.g. Date.toLocaleString and String.localeCompare that give correct results when using with locales other than en-US. This variant is about 6MB larger per architecture.

By default, the version of JavaScriptCore used by Electrode Native will be set to the latest version available at the time of Electrode Native version release and will be communicated in the release notes. The default JavaScriptCore variant will always be the non international one.

It is possible to change these defaults, using the `androidConfig` object of `containerGenerator` as shown below.

```json
{
  "containerGenerator": {
    "androidConfig": {
      "jsEngine": "jsc",
      "jscVersion": "^245459.0.0",
      "jscVariant": "android-jsc"
    }
  }
}
```

`jscVersion` is the version (fixed or range) of the JavaScriptCore engine while `jscVariant` is the variant (`android-jsc` or `android-jsc-intl`).

*Hermes*

To use [Hermes](https://hermesengine.dev/) engine rather than JavaScriptCore, you should set the `jsEngine` in `androidConfig` to `hermes`.

```json
{
  "containerGenerator": {
    "androidConfig": {
      "jsEngine": "hermes",
      "hermesVersion": "0.2.1"
    }
  }
}
```

**iOS**

**An Electrode Native container can be retrieved in a few ways:**

* Use a dependency manager such as Carthage or Cocoapods or,
* Perform a manual `git clone` of the container

**Using CocoaPods (RN >= 0.61, XCode >= 11.0)**

If the client application is using CocoaPods to manage its dependencies, it is possible to package and distribute the container in a way that it can be added as a pod dependency *(in the Podfile)* of the client application.

One thing to note here though, is that due to the fact that the container itself is using CocoaPods and is depending on third-party pods, it is not possible *(as far as we know)* to add it 'as-is' to the client application.\
One way to work around this, is to distribute the container as a pre-compiled binary instead of as its raw source code.\
One advantage of such an approach is that it will reduce build time of the client application *(as it doesn't have to build the container during application build)*.\
One inconvenient of this approach is that the source code of the container will not be visible/accessible in the client app which can make debugging issues a bit more complex.

The high level steps are to build & package the container as an XCFramework, and to publish it along with an associated podpsec file, to a git repository. The client application can then add the container as a pod depenndency in its Podfile.

1. Build & Package the container as an XCFramework

After the container is generated *(via create-container command or other way)* the [XCFramework container transformer](https://github.com/electrode-io/electrode-native/blob/master/docs/platform-parts/container/1/README.md) can be used to build & package the container as an XCFramework.

One way to achieve this is to use the [transform-container](https://github.com/electrode-io/electrode-native/blob/master/docs/cli/transform-container/README.md) command as follow:

```
ern transform-container -p ios -t xcframework
```

This can also be achieved through cauldron by adding the following step in container generation pipeline config:

```json
{
  "name": "ern-container-transformer-xcframework",
}
```

2. Publish the container XCFramework as a pod to a git repository

After an XCFramework has been generated for the container, the [CocoaPod git publisher](https://github.com/electrode-io/electrode-native/blob/master/docs/platform-parts/container/2/README.md) can be used to publish the container XCFramework to a git repository, along with its associated podspec.

One way to achieve this is to use the [publish-container](https://github.com/electrode-io/electrode-native/blob/master/docs/cli/publish-container/README.md) command as follow:

```
ern publish-container --platform ios -p cocoapod-git -u [ssh_or_https_url_to_git_repo] -v [container_version]
```

This can also be achieved through cauldron by adding the follwing step in container generation pipeline config:

```json
{
  "name": "ern-container-publisher-cocoapod-git",
  "url": "[ssh_or_https_url_to_git_repo]",
}
```

This publisher will only upload the pre-compiled XCFramework to the repository, along with an adequatly generated ElectrodeContainer.podspec file. It will also create a git tag matching the container version.

3. Add the container pod dependency to client application Podfile

The container can then be added as a one line entry to the Podfile of the client application as follow:

```
pod 'ElectrodeContainer', :git => '[ssh_or_https_url_to_git_repo]', :tag => '[container_version]'
```

The `tag` can be omitted in case the client application prefer to always pull the latest container version from default branch of the repository.\
`:branch` can be used in place of `:tag`, to always pull the latest container from a specific branch.

Then, running `pod install` from the client application, will properly retrieve the container as a pod dependency.

**Using Carthage**

1. Create a Cartfile if you don't already have one, or open an existing Cartfile.
2. Add the following line to your Cartfile.

   ```bash
   git "git@github.com:username/myweatherapp-ios-container.git" "v1.0.0"
   ```
3. Create a `Cartfile.resolved` file if you don't have one or open your existing `Cartfile.resolved` file.
4. Add the following line to your `Cartfile.resolved` file:

   ```bash
   git "git@github.com:username/myweatherapp-ios-container.git" "v1.0.0"
   ```
5. Install your dependencies using the following command:

   ```bash
   carthage bootstrap --no-build --platform ios
   ```

**Use Git to clone container**

1. Clone the container.

   ```bash
   git clone git@github.com:username/myweatherapp-ios-container.git
   ```

**Add Container to your mobile application**

**React Native >= 0.61**

1. Check if your mobile application is using a workspace, (ie: you have an `.xcworkspace` file in your project directory). If not, open the `.xcodeproj` file of your mobile application in Xcode.
2. In Xcode's menu bar, **File** -> **Save As Workspace**... You can use the same name as the `.xcodeproj` file for your workspace name. Save at the same level as the `.xcodeproj`.
3. Close Xcode and re-open, this time selecting the workspace file.
4. Make sure nothing is selected in the project navigator, In Xcode's menu bar, **File** -> **Add Files** to `<your workspace name>`. If you used Carthage, look for `ElectrodeContainer.xcodeproj` in the Carthage/Checkouts directory. If you cloned the container, find the `ElectrodeContainer.xcodeproj` in the cloned container directory.
5. **Add Files** again, this time adding the `Pods.xcodeproj` that is located in the Pods directory of the container.

**React Native < 0.61**

1. Open your mobile application project file in Xcode.
2. Right click your `<your project name>` in the project navigator. Select **Add Files** to `<your project name>`. If you used Carthage, look for `ElectrodeContainer.xcodeproj` in the Carthage/Checkouts directory. If you cloned the container, find the `ElectrodeContainer.xcodeproj` in the cloned container directory.

**Additional Configuration**

After installing the dependency, you will need to add additional configurations.

1. In Xcode, choose `<your project name>` from the Project Navigator panel.
2. Click `<your project name>` under TARGETS.
3. From the General tab, locate **Frameworks, Libraries, and Embedded Content** and click **+**
4. Select `ElectrodeContainer.framework` and click Add.
5. In Build Phases, verify that `ElectrodeContainer` is in Link Binary With Libraries and Embed Frameworks.
6. Edit Scheme for your `<your project name>` target. Locate Build Options and uncheck Parallelize Build.

**Skip installing dependencies (RN >= 0.61)**

When using React Native >= 0.61, you can configure the iOS container generator to skip the automatic installation of dependencies. **This container generation mode is the default one when generating iOS containers on Linux/Windows**, as the `pod install` command cannot be run on these platforms.\
To also generate such a container on MacOS, you can set the `skipInstall` flag to `true` in the container generator iOS configuration, as follow:

```json
{
  "containerGenerator": {
    "iosConfig": {
      "skipInstall": true
    }
  }
}
```

Alternatively, for containers that are not generated using a cauldron, you can set the `--skipInstall` option of the `create-container` command.

**Extra configuration**

You can override the iOS deployment target version to use by setting `iosConfig` in the cauldron as show below.

```json
{
  "containerGenerator": {
    "iosConfig": {
      "deploymentTarget": "11.0"
    }
  }
}
```

You can run pod repo update before pod install by setting `podRepoUpdate` in the cauldron as show below.

```json
{
  "containerGenerator": {
    "iosConfig": {
      "podRepoUpdate": true
    }
  }
}
```


# Initialization

This section describes how to initialize a container for the Android and iOS platforms.

## Android

Before accessing MiniApps that are stored within an Electrode Native container, the container needs to be initialized.

Initialization of a Container should ideally take place during startup of your mobile application. If you are using a class extending Application, you should place the container initialization call in the `onCreate` method of this class. If you are not using an Application class to initialize all libraries used by your mobile application, you should place the container initialization code wherever appropriate. It's best to have it initialized as soon as possible in the application lifecycle.

The initialization of a container is done as a single call of the `initialize static` method of the `ElectrodeReactContainer` class.

```java
ElectrodeReactContainer.initialize(
    this /* Application instance */,
    new ElectrodeReactContainer.Config().isReactNativeDeveloperSupport(BuildConfig.DEBUG)
    /* Additional plugins configuration here */);
```

The first parameter to this method is the `Application` instance. In the sample call above, we use `this` as the call is made from an `Application` extending class. The second parameter is the configuration of the container and React Native. In the sample above, we enable React Native developer support. In the sample we make use of `BuildConfig.DEBUG` to enable developer mode for debug builds only. You can adapt it for your application needs.

The `initialize` method might also contain additional parameters. Respectively, one parameter per plugin configuration. Not all plugins (APIs or third-party native modules) are configurable, so most of them (>90%) won't add an extra parameter to the initialize method. One configurable plugin is `react-native-code-push` for example, as you need to pass a `deployment key` to initialize this plugin, and it also has a debug mode that you can enable or disable.

## iOS

Before accessing MiniApps stored within an Electrode Native container, you need to initialize the container. In iOS, we prefix our platform-specific files with `Electrode`.

Initialization of a Container should ideally take place during startup of your mobile application. Ideally it should take place in your `AppDelegate.m` in `didFinishLaunchingWithOptions:` method. Otherwise, you should call the container initialization wherever appropriate. It's best to have it initialized as soon as possible.

Initialization of Container is performed through the static method `startWithConfigurations:` of `ElectrodeReactNative`.

```swift
    import ElectrodeContainer
```

```swift
    let containerConfig = ElectrodeContainerConfig()
    containerConfig.debugEnabled = RnDevSupportEnabled
    ElectrodeReactNative.start(withConfigurations: containerConfig)
```

```objectivec
    #import <ElectrodeContainer/ElectrodeContainer.h>
```

```objectivec
    ElectrodeContainerConfig *containerConfig = [[ElectrodeContainerConfig alloc] init];
    containerConfig.debugEnabled = RnDevSupportEnabled;
    [ElectrodeReactNative startWithConfigurations:containerConfig];
```

The first parameter is an implementation of the `ElectrodePluginConfig` protocol we provide through `ElectrodeContainer` that allows you to configure for both `ElectrodeContainer` and React Native. In the sample above we use `RnDevSupportEnabled`, a static boolean constant, to decide if developer support should be enabled or not. You can adapt it for your application needs.

The `startWithConfigurations:` method might also take additional parameters such as the implementation of `ElectrodePluginConfig` for additional plugins, depending on your plugin dependencies. Specifically, one parameter per plugin configuration. **Note** Not all plugins (APIs or third party native modules) are configurable, so most of them (>90%) won't add an extra parameter to the `initialize` method. One configurable plugin is `react-native-code-push` for example, as you need to pass a deployment key to initialize this plugin, and it also has a debug mode that you can enable or disable.


# Launching MiniApps

## Android

When a Container is generated, it will create one Activity for each MiniApp included in the container. For example, if you have a MiniApp named `Hello`, the container will create an Activity-extending class named `HelloActivity`. It will also be declared in the `AndroidManifest.xml` file of the container so that you can launch it from your mobile application without extra setup.

All of these activities are stored in the `com.walmartlabs.ern.container.miniapps` namespace.

To launch a MiniApp, all you have to do then, is start its corresponding Activity.\
You can also pass initial properties to a MiniApp, which will be provided to the JavaScript MiniApp as properties in the `componentWillMount` React lifecycle. This might be useful if the MiniApp needs data when first launched.

* Call the following static method of the `ElectrodeMiniAppActivity` class. &#x20;

  The first parameter is the Intent instance that you will pass to `startActivity`, while the second parameter is a Bundle instance containing the data to provide to the MiniApp as key:value pairs.

```java
public static void addInitialProps(@NonNull Intent intent, @NonNull Bundle bundle)
```

The generated Activities are very basic, and might not fulfill more advanced needs. If you need to use your own Activity subclass to host a MiniApp, you can directly extend the `ElectrodeMiniAppActivity` class and override the methods to your needs.

**Note** Be sure to override the following method and return the String corresponding to the MiniApp name hosted by this Activity--using the previous example, we would return "Hello".

```java
protected String getMiniAppName()
```

If you cannot extend your own Activity from this one (you might already have a deep inheritance chain and Java does not support multiple inheritance) but roll your own, or host the MiniApp in a Fragment instead, then you'll need to use `ElectrodeMiniAppActivity` as a template to roll your own class.

## iOS

When a Container is generated, it provides one `UIViewController` for each MiniApp included in the Container. For example, if you have a MiniApp named Hello, the container will create a `UIViewController` that contains the Hello miniapp--and it's the same `UIViewController` that you are already familiar with.

To launch a MiniApp, all you have to do then, is

* Present its corresponding `UIViewController` by calling `[[ElectrodeReactNative sharedInstance] miniAppWithName:@"<your-mini-app-name>" properties:nil]`
* You can also pass initial properties to a MiniApp, which will be provided to the JavaScript MiniApp as properties in the `componentWillMount` React lifecycle. This might be useful if the MiniApp needs data when first launched. To do this, pass an `NSDictionary` to the parameter `property`.

The generated `UIViewController` is basic and might not fulfill your advanced needs. If you would like to use your own subclass of the `UIViewController`, you must override `viewDidLoad:` in your `UIViewController` as shown below:

```objectivec
- (void)viewDidLoad {
    [super viewDidLoad];
    UIViewController *viewController =
    [[ElectrodeReactNative sharedInstance] miniAppWithName:@"<YourMiniAppName>" properties:nil];
    viewController.view.frame = [UIScreen mainScreen].bounds;
    [self.view addSubview:viewController.view];
}
```


# Cauldron

A cauldron is a centralized document database that is used to store information about the client mobile application versions, native dependencies, and information about MiniApps. There is one cauldron per mobile application. With appropriate permissions, you can use the Electrode Native CLI commands to access and modify the data stored within the Cauldron. Some Electrode Native CLI commands are relying on the Cauldron for their execution.

A cauldron is not required to use Electrode Native. It is only required if you intend to use CodePush.

When using a cauldron, a container will automatically be regenerated, and its publishers/transformers pipeline executed, whenever running any cauldron command that alters the state *(the content)* of a container associated to a cauldron descriptor. For example runnings commands such as `cauldron add miniapps` to add one or more miniapp to a container or `cauldron update miniapps` to update the version of some miniapps in a specific container, will cause a new container to be generated and potentially published

Please also note that if your cauldron is properly configured for container publication, you can also use the \[cauldron regen-container] command to trigger a new generation and publication of a container for a given native application version, even if there are no changes to the content of the container (this can be useful in certain scenarios).


# Structure

The cauldron document *(cauldron.json)* stored at the root of a cauldron repository contains:

* One record for each mobile application version, for example: `MyWeatherApp iOS 1.1.0` and `MyWeatherApp Android 1.0.0`.
* Data pertaining to a specific mobile application version including all MiniApps *(and their versions)* that are currently part of it
* The list of all native dependencies *(and their versions)* used by MiniApps in a specific mobile application version
* The list of all MiniApp versions that have been pushed as Over-the-Air (OTA) updates for any given mobile application version

In order to use a MiniApp in any mobile application, first you'll need to add the MiniApp in the cauldron associated to that mobile application. Before adding a MiniApp to a Cauldron, Electrode Native performs compatibility checks to confirm that the MiniApp version (to be added to the target mobile application version) contains only native dependencies that are supported and that the versions are properly aligned with the mobile application version.

If compatibility checks pass, a new container version is generated and published. The new container is updated with the changes and the mobile application version data stored in the Cauldron is updated accordingly to reflect the current new state of the new container version. This occurs when the mobile application version is not released yet *(in-development)*. If some dependencies versions are not compatible, a new container won't be created. Similar checks happen for pushing a MiniApp update as an Over-the-Air (OTA) update.

The cauldron stores `yarn.lock` files that are used internally to guarantee consistency of non-updated MiniApp versions.

Using the Electrode Native CLI, you can access multiple cauldrons. There can however be only one cauldron activated at a time.

## The cauldron document

The following is an example of a `cauldron.json` document.

```javascript
{
  "nativeApps": [
    {
      "name": "MyWeatherApp",
      "platforms": [
        {
          "name": "android",
          "versions": [
            {
              "name": "1.0.0",
              "isReleased": true,
              "binary": null,
              "yarnLocks": {
                "container": "3f5f0e4bac859b9e83adacacc2141e594ac1403d"
              },
              "codePush": {
                "Production": [
                  {
                    "metadata": {
                      "deploymentName": "Production",
                      "isMandatory": true,
                      "appVersion": "1.0.0",
                      "size": 1877208,
                      "releaseMethod": "Release",
                      "label": "v16",
                      "releasedBy": "whoever@whatever.com",
                      "rollout": 100
                    },
                    "miniapps": [
                      "movielistminiapp@0.0.11",
                      "https://github.com/electrode-io/moviedetails-miniapp#0.0.9"
                    ],
                    "jsApiImpls": []
                  }
                ]
              },
              "containerVersion": "1.0.9",
              "container": {
                "nativeDeps": [
                  "react-native-code-push@5.2.1",
                  "react-native-ernmovie-api@0.0.9",
                  "react-native-ernnavigation-api@0.0.4",
                  "react-native@0.52.2",
                  "react-native-electrode-bridge@1.5.9"
                ],
                "miniApps": [
                  "movielistminiapp@0.0.10",
                  "https://github.com/electrode-io/moviedetails-miniapp#0.0.9"
                ],
                "jsApiImpls": [],
                "ernPlatformVersion": "0.24.0"
              }
            }
          ]
        }
      ]
    }
  ]
}
```

This sample `cauldron.json` document shows the following:

* This mobile application version contains two MiniApps *(these might be two screens of the application)*.
* This mobile application version has been released and a CodePush update has been performed to update the version of one of the two MiniApps.
* The `nativeapps` array contains the data of all mobile applications that are part of the cauldron. A cauldron can store multiple mobile applications, however it is not recommended--instead, we recommend that you use one cauldron per mobile application. It can also be a good idea to go even more granular and have one Cauldron per native application platform (i.e `MyWeatherApp Android` / `MyWeatherApp iOS`)
* For each mobile application, the second level is the platforms array. Electrode Native supports two platforms: Android and iOS. For each platform, there can be multiple versions of a mobile application. Most of the Cauldron data is stored at this level *(mobile application + platform + version)*.

For each version of a mobile application, the cauldron stores the following data:

* `isReleased` : `true` if this version is released to users and `false` otherwise (this version is in development)
* `yarnLocks` : The SHA hash of the `yarn.lock` files stored in the cauldron database - this is used by Electrode Native when generating the composite JavaScript bundle.
* `nativeDeps` : An array of native dependencies descriptors, corresponding to the native dependencies (and their versions) stored in the current container of this mobile application version
* `miniApps` : MiniApps package descriptors corresponding to the MiniApps currently part of the current Container version or released through CodePush updates. The `miniApps` array only contains immutable versions. What this means is that any MiniApp path refer to a specific version. For example in the case of a MiniApp added as a registry path, a fixed version must be specified (ex: `movielistminiapp@0.0.10`). This cannot be a range version (ex : `movielistminiapp@^0.0.10`). In the same way, this cannot be a branch (ex : `"https://github.com/electrode-io/moviedetails-miniapp#master`). While it is possible to add a MiniApp this way; Electrode Native will track the branch and only keep a commit SHA in the `miniApps` array (ex : `"https://github.com/electrode-io/MovieDetailsMiniApp#ce08c19e2b707fc96a4db016c47a6f3ae8d66262`). This is done to make sure that one can know exactly what versions (and thus code) of the MiniApps are included in a given Container. Indeed, using a version range such as `^0.0.10` or a branch such as `master` would not allow one to know exactly what is included in a given Container version.

## Cauldron configuration files

Configuration files (`.json` files) are kept in a `config` directory at the root of the Cauldron. At this time there is no way to set or update configuration through commands. Configuration should be done manually.

* This cauldron contains global configurations as well as a single Android mobile application version: `MyWeatherApp 1.0.0`.

***default.json***

```javascript
{
  "manifest": {
    "override": {
      "url": "git@github.com:username/ern-custom-manifest.git",
      "type": "partial"
    }
  },
  "codePush": {
    "entriesLimit": 10
  },
  "requiredErnVersion": ">=0.26.0"
}
```

***MyWeatherApp-android.json***

```javascript
{
  "containerGenerator": {
    "pipeline": [
      {
        "name": "build-config",
        "extra": {
          "configurations": [
            "ElectrodeContainer-Debug",
            "ElectrodeContainer-Release"
          ],
          "settings": {
            "ENABLE_BITCODE": "NO",
            "DEBUG_INFORMATION_FORMAT": "dwarf-with-dsym"
          }
        }
      },
      {
        "name": "git",
        "url": "git@github.com:username/myweatherapp-android-container.git"
      },
      {
        "name": "maven",
        "url": "https://repo.example.org/content/repositories"
      }
    ]
  }
}
```

* At the platform level of the `MyWeatherApp` application (Android), an optional config object contains configuration for the Container generator that applies to every version of the `MyWeatherApp` for the Android platform. Likewise it contains some configuration for a Container transformer. It also contains CodePush configuration. For information about CodePush, see the [CodePush documentation](https://microsoft.github.io/code-push/) for more details. For information about Container Generator and Transformers configuration, refer to the [Container documentation](https://github.com/electrode-io/electrode-native/tree/4365979177cd88285ea1dabc57c271c54bd4f349/docs/platform-parts/cauldron/container.md).


# Setup

Setting up a cauldron is basically the same process as creating a Git repository and storing the data in the repository. If you know how to create a git repository, then you know how to create a Cauldron. To host your cauldron, you can use any provider offering Git repository storage. GitHub, GitLab and BitBucket are some of the most popular providers. Within our documentation, we mention GitHub but you are free to use the provider of your choice.

To create your own mobile application cauldron:

1. Create a new GitHub repository to host your cauldron.

   While there are no repository naming conventions, we recommend that you name it: `[mobile_app_name]-cauldron`

Note: A cauldron is bound to one mobile application--even though it can hold multiple mobile applications. We do not recommend holding multiple mobile applications within a cauldron.

1. Add the cauldron to the repository using the Electrode Native CLI.

```bash
$ ern cauldron repo add <cauldron-alias> <cauldron-url>
```

1. Add your first mobile application version in the cauldron.

```bash
$ ern cauldron add <native-app-descriptor>
// for example
// ern cauldron add nativeapp MyApp:ios:0.0.1
// ern cauldron add nativeapp MyApp:android:0.0.1
```

The descriptor provided to this command should be a complete native application descriptor.


# Compatibility checks

Any MiniApp that needs to be added to a mobile application version stored in the cauldron will go through a series of version compatibility checks. If any of these checks fails, the MiniApp won't be added to the cauldron *(and ultimately won't be included in a new Container or shipped as an OTA update)*.

The Cauldron performs compatibility checks to make sure that any MiniApp added to a mobile application version, will not lead to runtime issues with other MiniApps and native dependencies already part of the container of the mobile application version.

The compatibility checks are primarily checking the native dependency versions proper alignment *(including React Native and any native module or API / API implementation that the MiniApp uses)*.

Listed below are some of the compatibility checks and logic that is performed by Electrode Native, when running an operation changing the state of a container.

## Adding or updating a MiniApp

* To a in-development mobile application version For each of the native dependencies that the MiniApp depends on:\\
  * Don't do anything if the native dependency is already in the Container, with the same version.
  * If the native dependency is not already in the Container, add it.
  * If the native dependency is already in the Container but with a different version, ensure that the versions are backward compatible *(for third-party native modules we don't consider backward compatibility, the platform requires an exact version match, however APIs follow more flexible rules)*. If that is the case and the version of the dependency used by the MiniApp is greater than the one in the Container, bump the version of the dependency in the container to the one used by the MiniApp. If that is not the case, fail the operation.
* To a released mobile application version

  For each of the native dependencies that the MiniApp depends on:\\

  * Nothing to do if the native dependency is already in the Container, using the same version.
  * If the native dependency is not already in the Container, fail the operation. It is not possible to add a native dependency using OTA updates (for third-party native modules we don't consider backward compatibility, the platform requires an exact version match, whereas APIs follow more flexible rules). If that is the case and the version of the dependency used by the MiniApp is lower than the one in the Container, proceed. Otherwise, fail.

## Removing a MiniApp

Compatibility checks are not performed and Electrode Native does not try to remove any of the native dependencies used by the MiniApp.


# Guidelines

While Git offers many benefits in our case compared to a large database system, developers who are familiar with Git repositories are also familiar with the Git workflow, which doesn't match the workflow when working with a cauldron repository. For example, developers working in a Git repository might be tempted to fork, branch, and issue pull requests for a cauldron, but should retain from doing so.

A Cauldron should only be updated using Electrode Native CLI commands. You should not update the Cauldron 'manually'. If you update a cauldron manually, you take the risk of bypassing all compatibility checks performed by Electrode Native and you de-synchronizing the container version and the yarn locks. Only exception to this rule is if you need to setup some `config` objects in the Cauldron *(container generator, manifest)*, as Electrode Native doest have any CLI command yet to write configuration to the Cauldron.


# Manifest

While the Electrode Native cauldron makes sure that no misaligned-aligned or non-supported native dependency version makes it into your mobile application--the Electrode Native manifest aligns native dependency versions across multiple MiniApps in the first place.

Each Electrode Native platform version is associated to an array of supported native dependencies along with their versions. For example:

```javascript
[
  "react-native@0.42.0",
  "react-native-code-push@1.17.1-beta",
  "react-native-stack-tracer@0.1.1",
  "react-native-vector-icons@4.0.0",
  "react-native-maps@0.13.1"
]
```

The array contains the list of all third-party native dependencies (everything except APIs and API implementations) supported by a given Electrode Native platform version along with the versions that should be used.

When native dependencies are added to a MiniApp using the `ern add` command (based on the Electrode Native version used), the command verifies if the dependency is supported and if it is supported, the version declared in the Electrode Native manifest is used.

The Electrode Native platform guarantees that any MiniApp targeting a given Electrode Native version will only include supported dependencies, at the same versions--making it possible to add all MiniApps to a single Electrode Native container.

The Electrode Native platform stores its master manifest in a GitHub repository, [electrode-native-manifest](https://github.com/electrode-io/electrode-native-manifest/blob/master/manifest.json).\
By default, Electrode Native uses the master manifest. For more advanced use cases, it is possible to override the master manifest as described later in this documentation.

In order to update the manifest at any time, it is stored in a Git repository. This allows for adding new supported dependencies for an Electrode Native version at any time, without having to wait for the next Electrode Native main version to be released.

For any Electrode Native version defined in the master manifest:

* We can add new native dependencies support.
* We cannot change or remove existing native dependencies versions (except for bridge and APIs as the following a versioning allowing for more flexibility)

If you change version of or remove native dependencies, the version alignment guarantees offered by the manifest will be lost.

The Electrode Native manifest repository contains:

* The Electrode Native manifest file: `manifest.json`
* Configurations for all supported third-party native modules (The configurations are used by the container generator to inject the native dependencies in the container during generation.)

Open source MiniApp developers should always use the master manifest. This is the default operating mode of the platform.

To align your native dependencies to a new Electrode Native version, use the `ern upgrade-miniapp` command. When you align the native dependencies to a new Electrode Native version, your MiniApp will be able to be added to any mobile application using any Electrode Native version.

You might also consider using the same version of React Native for your mobile application, for a while, before upgrading to a new version of React Native. Indeed, upgrading (the version of react-native or associated native modules) too frequently might harm your release process because you cannot use CodePush to release updates to versions of your mobile application that have already been released with a different version of React Native.

For each new Electrode Native version, the master manifest will contain updated versions of most of the native dependencies, including the version of React Native itself. The master manifest will always uses the latest available version of React Native for each new Electrode Native release.


# Override

You can override the master manifest partially or fully with your own manifest file:

* To stick to some specific native dependencies versions over time while still allowing for Electrode Native version updates
* To allow for the use of non open-sourced (private) native modules in your MiniApps

To override a manifest:

1. Create your own manifest repository on GitHub (you can fork this [starter manifest](https://github.com/electrode-io/electrode-native-starter-manifest)).
2. Create a manifest override configuration in your cauldron--so that it is correctly applied to all users of this cauldron.
3. Update and maintain your manifest as needed, over time.

The following example shows a configuration that includes a partial manifest override.

```javascript
"config": {
  "manifest": {
    "override": {
      "url": "git@github.com:username/ern-custom-manifest.git",
      "type": "partial"
    }
  }
}
```

The configuration object should be **manually added to your cauldron** at the same level as the `nativeApps` array.

* The `override url` is the url of the GitHub repository containing your own Manifest
* The `override type` value can be either partial or full. For most use cases you'll use the partial; full can be useful in rare cases.

## Partial override

The array of dependencies and the versions used by a given Electrode Native version will be the combination of both the override manifest and the master manifest. If a dependency is defined in both manifests for a different version, the override version takes precedence, masking the version defined in the master manifest.

For plugins (native modules) configurations using the partial override type, Electrode Native first checks for a matching plugin configuration inside the override manifest and then returns the matching configuration if found. If a matching configuration is not found, it then checks the master manifest.

## Full override

For dependencies or plugin configurations, a full override means that Electrode Native only queries the override manifest. The master manifest is never used. A full override completely masks the master manifest.

## manifest.json document

Starting with Electrode Native 0.32.0, Electrode Native offers an improved `manifest.json` structure that is not used by our [Master Manifest](https://github.com/electrode-io/electrode-native-manifest/blob/master/manifest.json), but that we recommend use of, for override Manifests.

This new structure get rid of the coupling between a Manifest entry and an Electrode Native version. This association proved to be too restrictive, getting in the way of advanced use cases.

The new `manifest.json` document associate a `manifest id` (manifest object key) to a set of native and javascript dependencies, as follow :

```javascript
{
  "default": {
    "targetNativeDependencies": [
      "react-native@0.59.4",
      "react-native-electrode-bridge@1.5.17",
      "react-native-maps@0.23.0"
    ],
    "targetJsDependencies": ["react@16.8.3"]
  },
  "next": {
    "targetNativeDependencies": [
      "react-native@0.60.0",
      "react-native-electrode-bridge@1.5.18",
      "react-native-maps@0.24.0"
    ],
    "targetJsDependencies": ["react@17.0.0"]
  }
}
```

The `default` manifest id will be picked up automatically, unless a different `manifest id` is explicitly provided to some `ern` commands that are accessing the manifest.

For example, you might want to define a `next` manifest id with upgraded dependencies versions, and from a specific branch of your MiniApps you can then run `ern upgrade-miniapp --manifestId next` which will upgrade the MiniApp dependencies to the versions specified in the `next` manifest entry, while your main MiniApp branches can continue tracking the `default` Manifest entry. This was not possible previously due to the fact that Manifest entries had a one to one mapping to a specific platform version.

## Guidelines for overriding Manifest use cases

If you want to override the master manifest in order to keep specific native dependencies versions over time, you should choose a Electrode Native version and reuse the native dependencies versions associated with it--to override the native dependencies in newer versions of Electrode Native. This practice allows users to update their Electrode Native version-while keeping the same native dependencies versions used with a previous version of Electrode Native.

For example, you use the array of native dependencies versions declared for ern 0.4.0 to re-use it as such for versions 0.5.0 and 0.6.0 of Electrode Native, overriding the native dependencies array of 0.5.0 and 0.6.0 defined in the master Manifest.

You can also choose to change a native dependency version from the version used by the master manifest; however, this type of change loses the version alignment guarantee and makes it difficult to add open-sourced MiniApps to your mobile application.

If you want to override the master manifest to use private (not open sourced) native modules in your MiniApps, or if you want to contribute to Electrode Native by adding the support for an not-already supported open source native module to the master Manifest, you'll need to create native modules (plugins) configuration in the manifest file.


# Native Modules

Electrode Native supports some popular native modules such as `react-native-vector-icons`, `react-native-code-push` or `react-native-maps` for example. And the React Native open source community provides many additional native modules that could be used in your MiniApps.

If the Electrode Native version you are using does not yet support a native module that you would like to use, you can add support for it to Electrode Native by creating a plugin configuration in the manifest--this would be your override manifest in the case of a private native module or the master manifest for an open source native module.

**Why does Electrode Native require a plugin configuration?** In a pure React Native mobile application, you can use the `react-native link` command (formerly the `rnpm` command) to add a React Native plugin (native module) to your React Native application. However, Electrode Native requires that you add the native modules to a container library--not directly to a mobile application.

**Note** Electrode Native generated APIs and API implementations have a specific structure and additional configuration is not needed to support them in Electrode Native. However, if you plan to work on a new native module, it's recommended that you consider using Electrode Native APIs.

## Creating plugin configurations

In the manifest repository, the supported plugin configurations are located in the plugins directory. This plugins directory contains sub-directories that follow a specific naming convention that is used by Electrode Native to correctly match a plugin version with a plugin configuration--for a specific Electrode Native version.

The list below shows an example of the directory naming convention that matches Electrode Native versions.

```
plugins/ern_v0.2.0+
plugins/ern_v0.4.0+
```

Considering the example above, if you are using version `ern` `0.3.0`, the Electrode Native platform looks for a matching plugin configuration in the `plugins/ern_v0.2.0+` directory. If you are using version ern `0.5.0`, the Electrode Native platform looks for a matching plugin configuration first in the `plugins/ern_v0.4.0+` directory and if the configuration is not found that directory, the platform looks in the `plugins/ern_v0.2.0+` directory.

In addition, the plugin configuration files are located in directories within the version directories. These directories also follow a naming convention used by the Electrode Native platform to lookup a plugin configuration, for example:

```
plugins/ern_v0.2.0+/react-native-code-push_v1.17.0+
plugins/ern_v0.2.0+/react-native-linear-gradient_v2.0.0+
plugins/ern_v0.2.0+/react-native-maps_v0.13.1+
plugins/ern_v0.2.0+/react-native-maps_v0.14.0+
plugins/ern_v0.2.0+/@myscope/react-native-my-module_v1.0.0+
```

The naming of these directories includes the minimum version of the plugin that the configuration targets. If a newer version needs a different configuration, a new directory can be created. This is shown in the above example for the `react-native-maps`.

The plugin configuration file is located within these sub-directories.

## Configuration example

The following example shows the configuration files for the `react-native-code-push` plugin. The directory is located [here](https://github.com/electrode-io/electrode-native-manifest/tree/master/plugins/ern_v0.13.0%2B/react-native-code-push_v1.17.0%2B)

```
CodePushPlugin.java
ElectrodeCodePushConfig.h
ElectrodeCodePushConfig.m
config.json
```

Although the plugin has support for both iOS and Android platforms. Your native module can support only one platform.

The `CodePushPlugin.java` file contains configuration information to add the CodePush native module package to the list of native modules--to be loaded by React Native upon initialization of the Android Container library. The file can optionally include the configuration to allow the mobile app to configure the native module.

The `ElectrodeCodePushConfig.h` file and `ElectrodeCodePushConfig.m` file contains similar code for the iOS platform.

The `config.json` file holds the actual plugin configuration. It contains instructions that the container generator will use to add the plugin to the container.

The document can contain one or two top-level objects: `android` and/or `ios`. If a plugin is only supported on one platform, it will only contain that specific platform object.

There are two supported injection configuration directives:

* The `platform agnostic directives` can be used for both iOS and Android platforms.
* The `platform specific directives` can be used only in the context of a specific platform.

## Platform-agnostic directives

The platform-agnostic directives are described in this section.

* `copy`

Used to copy one or more files or directories to the target container directory. The `copy` directive is an array of objects, each containing a specific copy statement. The objects contain a `source` property and a `dest` property:

* `source` : A single file path or directory glob indicating the files to copy
* `dest` : A target directory where the files will be copied to

**Example**

```javascript
"copy":[
   {
      "source":"ios/**",
      "dest":"{{{projectName}}}/Libraries/CodePush"
   }
]
```

The example above shows how to copy the entire content (files and directories) of the plugin `ios` directory to the container `/Libraries/CodePush` directory.

All plugin code needs to be injected in the container--therefore they will have at least one `copy` statement in the `config.json` file. For the most part, in iOS, the `dest` will be `"{{{projectName}}}/Libraries/{PLUGIN_NAME}"`. `projectName` will be replaced during Container generation by the name of the project (`ElectrodeContainer` in the case of container generation), while `PLUGIN_NAME` should be the name of the plugin itself.

* `replaceInFile`

Used to perform string replacements in specified files. This is useful for the iOS platform as some plugins are sometimes needed to replace the way imports are performed. The `replaceInFile` directive is an array of objects, each containing a specific replacement statement. The objects contain a `path` property, a `string` property and a `replaceWith` property:

* `path` : Path to the file that contains a string to be replaced
* `string` : String to be replaced
* `replaceWith` : The new string

**Example**

```javascript
{
  "path": "{{{projectName}}}/Libraries/RNLocation/RNLocation.h",
  "string": "\"RCTBridgeModule.h\"",
  "replaceWith": "<React/RCTBridgeModule.h>"
}
```

This example shows how to replace the string `"RCTBridgeModule.h"` with `<React/RCTBridgeModule.h>` in the `/Libraries/RNLocation/RNLocation.h` file in the container.

* `applyPatch`

Apply a given patch file, by running `git apply` command, from a specific directory. The value of this property should be a single object containing the following two properties :

* `patch` : Path to the patch file to apply, relative to the directory containing the pluging configuration file (`config.json`).
* `root` : Path to the directory from which to run the `git apply` command, relative to the container generator output directory. Mutually exclusive with `inNodeModules`.
* `inNodeModules` : If true, root will be set to root location of the plugin in node nodules. Mutually exclusive with `root`.

**Example**

```javascript
{
  "patch": "example.patch",
  "root": "{{{projectName}}}/Libraries/ExampleNativeModule"
}
```

This example applies the `example.patch` patch file, by running `git apply` command from the `{{{projectName}}}/Libraries/ExampleNativeModule` directory.

## Platform-specific directives

The platform-specific directives for Android and iOS are described in this section.

## Android

The following directives can only be used inside an `android` configuration object.

* `moduleName`

The name of the Android `module` containing the plugin. By default, the plugin configuration uses `lib`, which is the convention most Android plugins adopt to name the module containing the plugin code.

* `root`

The root directory containing the Android module. By default, the plugin configuration uses `android`, which is the convention followed by most third-party native modules.

* `dependencies`

An array of one or more dependencies (in format "::") that the native module is dependent on. The container generator will add all of these extra dependencies as `implementation` statements in the container `build.gradle` file.

For special dependency statements needs, not using default `implementation <groupId>:<artifactId>:<version>` format, it is possible to set the full dependency statement to be injected in the `build.gradle` as illustrated in the following example:

**For example**

```javascript
"dependencies": [
  "com.google.android.gms:play-services-base:10.0.1",
  "implementation('com.crashlytics.sdk.android:crashlytics:2.9.2@aar') { transitive = true }",
  "implementation platform('com.foo:bar-pom:1.0.0')"
]
```

**Will result in the following injection in build.gradle:**

```
implementation 'com.google.android.gms:play-services-base:10.0.1'
implementation('com.crashlytics.sdk.android:crashlytics:2.9.2@aar') { transitive = true }
implementation platform('com.foo:bar-pom:1.0.0')
```

* `features`

An array of one or more [Android hardware or software features](https://developer.android.com/guide/topics/manifest/uses-feature-element) used by the native module, to add to the container manifest when injecting this plugin.

**For example**

```javascript
"features" : [
  "android.hardware.bluetooth"
]
```

**Will result in the following injection in Container manifest**

```markup
<uses-feature android:name="android.hardware.bluetooth" />
```

* Android Resources

If the native module is containing android resources (typically in `src/main/res`) you can use the `copy` directive to copy the resources directories to the container. For example, assuming the android resources directory is located in `android/src/main/res` (relative to the root of the native module package), and the package name of the native module is `react-native-example`, then you should add the following directive to properly copy the native modules resources to the container :

```javascript
"copy": [
  {
    "source": "android/src/main/res/*",
    "dest": "lib/src/main/res/react-native-example"
  }
]
```

Also, because resources are accessed via the `R` generated class, you'll have to make sure to update all imports of this class in the source files importing this class, to use the container namespace rather than the native module one. You can do so using `replaceInFile` directive, as illustrated:

```javascript
"replaceInFile": [
  {
    "path": "lib/src/main/java/com/example/SourceFile.java",
    "string": "com.example.R",
    "replaceWith": "com.walmartlabs.ern.container.R"
  }
]
```

## iOS

The following directives can only be used inside an `ios` configuration object.

* `containerPublicHeader`

Specifies one or more header to surface in the Container umbrella header. This is used only for specific headers that must be accessed from outside the container by the application itself.

**Example**

```javascript
"containerPublicHeader": [
  "ElectrodeBridgeHolder.h"
]
```

iOS also provides an additional directive object: `pbxProj`. The `pbxProj` directive can include directives used to manipulate the container `.pbxproj` file.

* `addProject`

Adds a plugin `xcodeproj` and its target library to the Container. - `path` : Path to the `xcodeproj` of the plugin

* `group` : Group to add the project to (`Libraries` should be used)
* `staticLibs` : An array of static libraries, targets of the plugin project, to link with the Container

**Example**

```javascript
"addProject": [
  {
    "path": "AirMaps/AirMaps.xcodeproj",
    "group": "Libraries",
    "staticLibs": [
      {
        "name":"libAIRMaps.a",
        "target":"AirMaps"
      }
    ]
  }
]
```

* `addHeaderSearchPath`

Adds a header search path to the container. This directive is used to add the proper path to the plugin headers. This is an array of strings--each string is a specific path.

```javascript
"addHeaderSearchPath": [
  "\"$(SRCROOT)/{{{projectName}}}/Libraries/AirMaps/**\""
]
```

* `addHeader`

Adds a header from the plugin project to the container headers.

* `path` : Path to the header file to add
* `group` : Group containing the header - `public` : Boolean indicated whether the header should be public or not (default to false)

```javascript
{
  "path": "ElectrodeReactNativeBridge/ElectrodeBridgeEvent.h",
  "group": "ElectrodeReactNativeBridge",
  "public": true
}
```

* `addSource`

Adds a source file from the plugin project to the container list of sources.

* `path` : Path to the source file to add - `group` : Group containing the source file

```javascript
{
  "path": "ElectrodeReactNativeBridge/ElectrodeObject.swift",
  "group": "ElectrodeReactNativeBridge"
}
```

* `setBuildSettings`

Set one or more build setting(s) in one or more pbxproj(s) associated to the plugin. For example setting `ENABLE_BITCODE` to `NO` for `Debug` and `Release` configurations of `Example` plugin project :

```javascript
"setBuildSettings": [
  {
    "path": "{{{projectName}}}/Libraries/Example/Example.xcodeproj/project.pbxproj",
    "buildSettings": {
      "configurations": ["Debug", "Release"],
      "settings": { "ENABLE_BITCODE": "NO" }
    }
  }
]
```

* iOS Resources

If the native module is containing resources that needs to be added to the container xcode project, you can use the `copy` directive to copy the resources to the container. For example, assuming the following `ios/example/resources` directory structure (relative to the root of the native module package)

```
ios/example/resources
├── Localizable.strings
├── Login.storyboard
└── Media.xcassets
```

You can add them all to the container, using the `copy` directive as illustrated below

```javascript
"copy": [
  {
    "source": "ios/example/resources/*",
    "dest": "{{{projectName}}}/Resources"
  }
]
```

The `dest` should always be set to `{{{projectName}}}/Resources`. During container generation, ern will add any resources present in this directory, to the container xcode project.

**The following directives are only available when using React Native >= 0.61.0**

* `podFile`

Path to a Podfile to use for the Container, relative to the directory containing the plugin config.json file. Can only be set in 'react-native' plugin configuration.

* `podspec`

Path to a podspec file to use for the plugin, relative to the directory containing the plugin config.json file. Can be used in case a native module doesn't have yet an available podspec file or if the podspec file of the native module needs to be different than the one shipped with it.

* `extraPods`

Array of extra pod statements that will be injected in the Container Podfile.

* `extraPodspecsSources`

Array of extra [pod specs sources](https://guides.cocoapods.org/syntax/podfile.html#source) to inject in the Container Podfile. **Only the repositories urls should be provided in the array, not the full source statements.** For example:

```javascript
{
  "extraPodspecsSources": [
    "https://github.com/artsy/Specs.git"
  ]
}
```

* `extraPodfileStatements`

Array of extra statements to inject in the Container Podfile. The strings provided in this array will be injected as-is in the Podfile.

* `requiresManualLinking`

Boolean flag that indicates whether this plugin requires manual linking. If defined and set to `true`, all plugin directives will be processed. If not defined (default) or set to false, only `podFile`, `podspec` and `extraPods` directives will be processed.\n This should only be set to `true` in very rare cases, for plugins that do not support auto linking.


# Configurable Modules

At runtime, some native modules require additional configuration settings. For example, the `react-native-code-push` native module requires a deployment key upon initialization.

Configurable plugins have some source code associated to them in the manifest plugin configuration file in addition to the `config.json` file.

For each configurable plugin added to a container, an extra parameter must be added to the container initialization method that is called by the mobile application. This extra parameter allows the client code to pass the configuration of the plugin--at the time the container is initialized.

This section describes these source files for both Android and iOS.

## Android

The following example describes an Android source file.

`{PLUGIN_NAME}Plugin.java`

In this example, the CodePush plugin file is named `CodePushPlugin.java`.

You can view the configuration in the current master manifest file located [here](https://github.com/electrode-io/electrode-native-manifest/blob/master/plugins/ern_v0.13.0%2B/react-native-code-push_v1.17.0%2B/CodePushPlugin.java)

The core of the source file is the `hook` method. The container invokes the `hook` method during initialization. The last parameter is the actual `Config` instance of the plugin as provided by the user when calling the `ElectrodeReactContainer` `initialize` method.

```java
public ReactPackage hook(@NonNull Application application, @Nullable Config config) {}
```

The `Config` class for the plugin is declared in the same `.java` source file. The class should follow the JAVA `builder` pattern. Mandatory configuration properties should be passed in the constructor, whereas optional properties should be provided using setter methods returning the `Config` instance to allow chaining.

## iOS

The following example describes an iOS source file.

`Electrode{PLUGIN_NAME}Config.h` and `Electrode{PLUGIN_NAME}Config.m`

This example includes two `ObjectiveC` files for for CodePush plugin: `ElectrodeCodePushConfig.h` and `ElectrodeCodePushConfig.m`.

You can view the configuration in these files in the current master manifest file located [here](https://github.com/electrode-io/electrode-native-manifest/blob/master/plugins/ern_v0.13.0%2B/react-native-code-push_v1.17.0%2B/ElectrodeCodePushConfig.h) and [here](https://github.com/electrode-io/electrode-native-manifest/blob/master/plugins/ern_v0.13.0%2B/react-native-code-push_v1.17.0%2B/ElectrodeCodePushConfig.m).

A configuration class should use the `ElectrodePluginConfig` protocol.

The `(void)setupConfigWithDelegate: (id<RCTBridgeDelegate>)` method is called during the container initialization.


# Runner

The Electrode Native platform contains two runners, one for each mobile platform (Android and iOS). Both runners are very simple and light-weight mobile applications--similar to new application projects in Android Studio or Xcode.

The Electrode Native runner application is used to run your standalone MiniApp so that you can effectively develop, debug, and test your MiniApp--before releasing a new or updated version of the MiniApp.

An Electrode Native runner application is automatically generated the first time you use the `ern run-ios` or `ern run-android` commands for your MiniApp. Relative to your MiniApp root directory, the runner application is generated in new Android and iOS directories.

When the Electrode Native runner application is generated, you can make manual code modifications to it, if needed--they aren't overwritten the next time you run the `ern run-ios` or `ern run-android` commands. The only way to trigger a complete regeneration of the Electrode Native runner is to remove the Android or iOS directories.

Each time you run the `ern run-ios` or `ern run-android` commands, a new local container is generated to include your MiniApp along with all of its native dependencies. The Electrode Native runner mobile application depends on the local container in order to launch the MiniApp.

By default, when launching the Electrode Native runner using the `ern run-ios` or `ern run-android` commands, a local React Native Packager is launched and your MiniApp bundle is served from this packager. This is the normal development workflow. However, you can also serve your MiniApp directly from the container stored within the binary of the application using additional command options.

## Multiple MiniApp support

The Electrode Native runner supports containers that include multiple MiniApps. However, since only one MiniApp can be launched when the Electrode Native runner starts, you'll need to specify the primary MiniApp that should be launched when the Electrode Native runner application starts.

## Related commands

* `ern run-ios` and `ern run-android`

  Launches one or more MiniApps in the Electrode Native runner application.


# APIs

At some point you'll need one or more MiniApps to interact with your mobile application--to access data or to trigger an action. Or, your mobile application may need to interact with your MiniApps. That's where Electrode Native APIs come into play.

Powered by the \[Electrode Native Bridge] and automatically generated for you by Electrode Native from a Swagger schema, Electrode Native APIs provide clearly defined methods of communication between the native Android or iOS side and the JavaScript side.

There are two components to Electrode Native APIs: the API project itself and the API implementation.


# Project Generation

Electrode Native automatically generates APIs based on a Swagger schema. The generated API results in a cross platform API project that includes the client code of the API, for all three platforms (JS/Android/iOS), along with any optional API models. Any Electrode Native MiniApp or mobile application can then use this Electrode Native API.

The generated API also contains the necessary hooks to implement the API. For example if your movie API defines a `getAllMovies` request, the API project will also contain hooks to write the actual request handling code and return the appropriate response, in this context, the collection of all movies.

The implementation of an API is not part of the API itself. The API project and the API implementation remain separate. One of the reason is to allow multiple implementations for any given API and offer the possibility to switch between implementations.

Once the API is generated, you should not modify it in any way *(unless you plan not to regenerate it later on)*. The API module contains only generated code. Any regeneration of it *(for example, following a schema update)* will actually overwrite any custom made user code modifications.

Generated APIs have the following naming convention: `react-native-[name]-api`


# Implementation

For obvious reasons API implementations aren't entirely generated. Electrode Native can't know what the implementation will actually do. However, Electrode Native still generates some of the skeleton code to help you kickstart Electrode Native API implementations projects.

An API implementation implements the handling of requests and events from the API. For example, it implements the actual logic behind the `getAllMovies` request. An API implementation is done on one "side" only. For example, an implementation of a given API can be a native implementation (iOS and/or Android) or a JavaScript implementation--but not both. At least not in the same API implementation module.

There can be multiple implementations for a given API. For example, it is possible to have a JavaScript implementation and a native implementation of the same API. But for any API, only one implementation can be used at runtime.


# Versioning

Electrode Native APIs have a few advantages compared to React Native native modules. Because Electrode Native APIs are generated, and Electrode Native knows their exact structure, they don't require a specific container injection (linking) configuration (in the Manifest).

For native modules versions, the platform will not allow a version mismatch. If two different versions (including patch versions) of an identical native module are used by two different MiniApps, the Electrode Native platform won't allow adding both MiniApps. Native module versions must be an exact match, including the patch version, as we can't be sure of the versioning guidelines followed by third party native modules.

However, for APIs (and API implementations), Electrode Native is less strict with version checks, because of the guidelines listed below, that you should adopt for versioning your APIs.

* **Patch version bump**\\

  Used when your API contains changes to the internal implementation and not to the public implementation. For example, from `1.0.0` to `1.0.1`. Because APIs are fully generated and should not to be modified manually, this should only occur when you regenerate an API following a platform version update that contains internal changes such as bug fixes or improvements to our API generator.

For API implementations, you should patch bump if you are making internal modifications to one or more event(s)/request(s) implementation.

* **Minor version bump** Used when your API contains new requests or new events. For example, from `1.0.0` to `1.1.0`.
* **Major version bump** Used when your API contains breaking changes to its public implementation. For example if you remove or rename an existing request or event. For example, going from `1.0.0` to `2.0.0`.

Electrode Native also offers more flexibility for deploying MiniApps that are using API versions not strictly aligned with API versions defined in a container.

* **API with a different patch version** Used when trying to deploy a MiniApp that contains an API version that exists in the container with a different patch version--Electrode Native assumes binary compatibility in any case.
* **API with a different minor version** Used when trying to deploy a MiniApp that contains an API version that exists in the container with a different minor version--Electrode Native assumes binary compatibility only if the version stored in the container is greater than the one used by the MiniApp.
* **API with a different major version** Used when trying to deploy a MiniApp that contains an API version that exists in the container with a different major version--Electrode Native considers binary incompatibility and does not allow deployment.


# Guidelines

While the recommended approach to implement Electrode Native APIs is to do so in a dedicated standalone project, favoring reuse and low coupling, it might not be possible in your context to implement a standalone API. For example if your native API implementation is dependent on the mobile application code itself, it might be needed to write the API implementation directly inside the mobile applicatiosn codebase. While this is possible, we don't recommend this tight coupling approach, and if possible, you should favor a standalone implementation.

Generated standalone API implementations have the following naming convention: `react-native-[name]-api-impl`


# Bridge

The [Electrode Native Bridge](https://github.com/electrode-io/react-native-electrode-bridge) is a low-level bi-directional communication library used to simplify communication between the JavaScript and the native mobile application. . The [Electrode Native Bridge](https://github.com/electrode-io/react-native-electrode-bridge) is actually a React Native-native module and as with most native modules, it contains some JavaScript code as well as iOS and Android platform code. Most of the Electrode Native bridge code is native (95% native/5% JavaScript).

[Electrode Native Bridge](https://github.com/electrode-io/react-native-electrode-bridge)


# Message Types

Communication through the Electrode Native bridge is based on message exchanges between JavaScript and the Native mobile application. The Electrode Native bridge processes three message types: `Request`, `Response`, and `Event`.

* Request\
  A Request message is used to request data from a receiver or to request an action to be performed by a receiver. A Request message always results in an associated response message that can contain either the requested data or indicate the result of an action. A Request message can optionally contain a payload. For any given Request message type, there can be only one associated receiver. The receiver handles the request and issues a response message. From a developer perspective, a Request message can be thought as being a method call.
* Response\
  A Response message is the result of a single Request message. A Response message can optionally contain a payload. From a developer perspective, a Response message can be thought as the return value of a method. The value can be of a specific type or not (void).
* Event\
  An Event message is a "fire and forget" message. The sender of the Event message does not expect a response --so the receiver is known as a listener. Unlike a Request message, an Event message can be sent to multiple listeners. All registered listeners (on JavaScript side and native side) for a specific event message type will receive the Event message.


# Communication

The [Electrode Native Bridge](https://github.com/electrode-io/react-native-electrode-bridge) expose a public client surface that is consistent across all three platforms and allows requests and responses from any side:

* Send Requests *(and associated responses)*
* Emit Events
* Register Requests handlers
* Register/Unregister Event listeners

Request and Event messages are named to identify the Request or Event message type. The name is used to direct the messages to the associated receivers. For example, names for Request messages might be `getMovieById` or `getAllMovies`. And for Event messages, a name might be `movieListUpdated`.

When a Request message is sent from any side, the Electrode Native bridge first attempts to find a registered receiver on the same side from where the message is sent. For example, if the Request message is sent from the JavaScript side, the Electrode Native bridge will first attempt to find a handler for it on the JavaScript side. If a handler is not found on the same side, the Electrode Native bridge will then attempt to find a Register handler on the other side (in this example, the native side). Ultimately if no handler is found, the request will fail with a specific error code.

When an Event message is sent from any side, the Electrode Native bridge looks for all registered listeners for this event type. The Electrode Native bridge then sends the message to all registered listeners for that event type, independent of the side on which they are located.

Payloads for Requests, Responses, or Events can be primitive types, but the Electrode Native bridge also supports complex object payloads (full-fledged model classes).


# Leveraging APIs

Even though the \[Electrode Native Bridge] is a standalone native module that can be used in your React Native projects (even without Electrode Native), if you are using Electrode Native, you do not directly interact with the Electrode Native bridge in your MiniApps or in your mobile applications. Instead, you'll mostly use Electrode Native APIs that are interacting with the bridge on their own. The Electrode Native APIs are generated from a Swagger schema--so they are predefined. Check out our [Electrode Native API documentation](https://native.electrode.io/reference/index-5).


# CLI

The Electrode Native CLI is the Electrode Native platform command line client. The Electrode Native CLI is written in JavaScript (ES6) and runs on Node 10+.

Use the Electrode Native CLI to access platform functionality. However, if you are working only on the mobile application side, you may not need to use the Electrode Native CLI at all.

The Electrode Native CLI is actually composed of two clients: a `global client` and a `local client`.


# Global CLI

The Electrode Native global client is installed globally on your machine using the `npm install -g electrode-native` command.

* The global client is a lightweight client that contains the `ern` binary.
* When you enter an `ern` command in your terminal, the command first passes through the global client before reaching the local client.
* The global client role is used to bootstrap first-time platform installation as well as redirect commands to the currently activated local client version.
* The global client is rarely updated.


# Local CLI

The Electrode Native local CLI client is installed automatically by the Electrode Native platform when you run the `ern platform install` command.

When you issue Electrode Native CLI commands, you use the local client. You can have multiple local client versions on your workstation as each Electrode Native platform version that you install on your system will have it's own version of the Electrode Native CLI installed. Only a single version of an Electrode Native CLI can be active at any given time. You can switch between versions of the local client using the `ern platform use` command.


# GLOSSARY

## complete native application descriptor

A complete native application descriptor is a string with format `[nativeAppName]:[platform]:[version]`

* `nativeAppName` : alphanumeric native application name , cannot contain character ':'
* `platform` : one of `android` or `ios`
* `version` : alphanumeric , cannot contain character ':'

## partial native application descriptor

A partial native application descriptor is a string with format `[nativeAppName]`, `platform` and `version` can remain optional.

* `nativeAppName` : alphanumeric native application name , cannot contain character ':'

## Electrode Native module name

The Electrode Native module name applies to modules created with Electrode Native cli.

* Module names should be alphanumeric and cannot start with a digit or underscore
* `create-miniapp`, `create-api` and `create-api-impl` commands allow passing Electrode Native module name as its arguments.

For example, `ern create-miniapp mymovie-miniapp`, `ern create-api mymovie-api` will create `mymovie-miniapp` and `react-native-mymovie-api` respectively.

## package path

A package path is a string representing the path (local or remote) to a Node Package. In the context of Electrode Native, a few package path formats are supported (as illustrated by the following samples) :

Package in remote git repository:

* `git+ssh://git@github.com:electrode-io/movielist-miniapp.git`
* `git+ssh://git@github.com:electrode-io/movielist-miniapp.git#0.0.9`
* `https://github.com/electrode-io/movielist-miniapp.git`
* `https://github.com/electrode-io/movielist-miniapp.git#0.0.9`

For GitHub SSH urls it is also possible to use the default GitHub format:

* `git@github.com/electrode-io/movielist-miniapp.git`
* `git@github.com/electrode-io/movielist-miniapp.git#0.0.9`

The string following the optional `#` denotes a branch/tag or specific commit SHA.

Package on local file system :

* `file:/etc/movielist-miniapp`
* `/etc/movielist-miniapp`

Package on npm registry:

* `movielistminiapp`
* `movielistminiapp@0.0.9`
* `@myscope/movielistminiapp@0.0.9`

## Container publishers

The following Container publishers are currently available:

* [git](https://github.com/electrode-io/ern-container-publisher-git)
* [maven](https://github.com/electrode-io/ern-container-publisher-maven)
* [jcenter](https://github.com/electrode-io/ern-container-publisher-jcenter)
* [dummy](https://github.com/electrode-io/ern-container-publisher-dummy)

The README of each of these publishers contain information related to their usage and configuration.


# Debugging multiple MiniApps

Debugging individual MiniApps (running *standalone*) works similar to debugging regular React Native apps. See [Debugging](https://reactnative.dev/docs/debugging) for more information.

The rest of this guide focuses on a setup to debug *multiple* MiniApps with the help of the [ern start](/cli-commands/start) command and a local [Composite](/reference/index).

## Prerequisites

* All prerequisites of [React Native](https://reactnative.dev/) and [Electrode Native](https://native.electrode.io/introduction/what-is-ern/requirements)
* [Visual Studio Code](https://code.visualstudio.com/)
* The VS Code [React Native Tools](https://marketplace.visualstudio.com/items?itemName=msjsdiag.vscode-react-native) extension

## Setup

### Step 1: Prepare working directory

Inside a new directory (e.g. `workspace`), clone all MiniApps that you want to debug.

In this example, for two MiniApps `details-miniapp` and `list-miniapp`, the directory structure should look like this:

```
workspace/
├── details-miniapp/
└── list-miniapp/
```

### Step 2: Link MiniApps

Run `ern link` in each MiniApp directory.

The [ern link](/cli-commands/link) command is needed to map the source location between the composite and the MiniApp directory, but also to ensure that any changes to the MiniApp directory are propagated to the Composite.

### Step 3: Initialize parent project

This is necessary for the [React Native Tools](https://marketplace.visualstudio.com/items?itemName=msjsdiag.vscode-react-native) extension to work properly.

Run `yarn init --yes` (or `npm init --yes`) in the parent directory (`workspace`) to create a `package.json` file. Then add the React Native dependencies:

```bash
yarn add react@16.8.6 react-native@0.60.6
```

Use the **same versions** of `react` and `react-native` that are used by the MiniApps (in this example React Native 0.60.6).

The structure should now look like this:

```
workspace/
├── details-miniapp/
├── list-miniapp/
├── node_modules/
├── package.json
└── yarn.lock
```

### Step 4: Create a debug configuration

#### Visual Studio Code

This configuration will be used to attach the [VS Code debugger](https://code.visualstudio.com/docs/editor/debugging) (actually the [React Native Tools](https://marketplace.visualstudio.com/items?itemName=msjsdiag.vscode-react-native) debug adapter) to the native application.

Follow the instructions in [Launch configurations](https://code.visualstudio.com/docs/editor/debugging#_launch-configurations) to create a new launch configuration and open the resulting `launch.json` file.

Manually add a `sourceMapPathOverrides` section to configure [sourcemaps](https://github.com/microsoft/vscode-chrome-debug/blob/master/README.md#sourcemaps):

```javascript
{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Attach to packager",
      "cwd": "${workspaceFolder}",
      "type": "reactnative",
      "request": "attach",
      "sourceMapPathOverrides": {
        "../../composite/node_modules/details-miniapp/*": "${workspaceFolder}/details-miniapp/*",
        "../../composite/node_modules/list-miniapp/*": "${workspaceFolder}/list-miniapp/*"
      }
    }
  ]
}
```

Note that the package name of the MiniApp could be different from the directory name in the workspace folder.

```
"../../composite/node_modules/[MINIAPP_PACKAGE_NAME]/*": "${workspaceFolder}/[MINIAPP_DIRECTORY_NAME]/*"
```

At this point our directory structure should look like:

```
workspace/
├── .vscode/
│   └── launch.json
├── details-miniapp/
├── list-miniapp/
├── node_modules/
├── package.json
└── yarn.lock
```

The basic setup is now complete. If you need to add more MiniApps, clone them into the `workspace` directory, run `ern link`, and add a corresponding mapping entry to `sourceMapPathOverrides` configuration.

We can now start debugging with the help of the [ern start](/cli-commands/start) command.

## Debugging

### Step 1: Create a composite

In order to debug and step through the code, we require a locally generated [Electrode Native Composite](/reference/index) inside of the `workspace` directory.

Pass an absolute path as the `--compositeDir` parameter to `ern start`:

```bash
ern start [options] --compositeDir /path/to/workspace/composite
```

The MiniApps to include in the composite can be passed using the `--miniapp` (or `-m`) flag. If no other options are defined, the `ern start` command requires an active [Cauldron](broken://pages/-LFa-NYIdwHj4mANWo_j). See `ern start --help` for more information.

Once composite generation is done, we should have the following structure:

```
workspace/
├── .vscode/
│   └── launch.json
├── composite/
├── details-miniapp/
├── list-miniapp/
├── node_modules/
├── package.json
└── yarn.lock
```

### Step 2: Open the project and set breakpoints

Open the `workspace` directory in VS Code (if you have not done so already) and launch the native application (if it is not already running). It may have been launched automatically by `ern start`.

Now you may set breakpoints in the JavaScript code of the MiniApps.

### Step 3: Attach the debugger

To attach VS Code to the React Native debugger, run the *Attach to packager* debug configuration. Make sure the `ern start` command has completed and is still running in the background. You will notice an indicator that will keep spinning until the next step is completed.

### Step 4: Enable JS Debugging in the app

In the native application, bring up the [React Native developer menu](https://reactnative.dev/docs/debugging), and turn on JS Debugging by tapping *Debug* (Android) or *Debug JS Remotely* (iOS). This will result in attaching to the Visual Studio Code debugger. If debugging was already turned on in the native app, disable it first, then re-enable it. In VS Code you should now see that the debugger was attached. Check if the breakpoints are triggered in the sources of `details-miniapp` and `list-miniapp`, and debug the MiniApps in VS Code.


# add

## Description

* Add one or more package (dependency) to the MiniApp

## Syntax

`ern add <packages..>`

**Options**

`--dev/-d`

* Add the package(s) to the MiniApp `devDependencies`
* Checks are not performed to add development dependencies

`--peer/-p`

* Add the package(s) to the MiniApp `peerDependencies`
* Checks are not performed to add peer dependencies\`

`--manifestId <manifestId>`

* ID of the override Manifest entry to retrieve dependencies versions from (see [override Manifest](/reference/index-2/override) for more info)

## Remarks

* The `ern add <packages..>` command is the `ern` equivalent of `yarn add` and `npm install` When you work with a MiniApp, always use `ern add` to add packages in place of `yarn add` or `npm install`.
* Based on your preference, you can select which package manager (`npm` or `yarn`) to be used by this command to add the package. This can be done by adding or updating `packageManager` field in the `ern` object kept in the MiniApp package.json. For example, to use `npm`. If this field is missing from the configuration, `yarn` will be used over `npm` if it is installed on the workstation.

```javascript
{
  "ern": {
    "packageManager": "npm"
  }
}
```

* The `ern add <packages..>` command performs compatibility checks before adding the package to the project.
* You don't need to specify an explicit version for a package that you add using `ern add` as the version to use will be retrieved from the Manifest. If you add an explicit version for a package, it will be ignored.
* If the package is declared in the current platform manifest, then the version from the manifest is used.
* The `ern add <packages>` command performs the following checks:
* If the package is declared in the manifest, then `ern` installs the package at the version declared in the manifest.
* If the package is not declared in the manifest, then additional checks are performed:
  * If the package contains native code in any way (the package itself is a native module or it transitively contains one or more native dependencies, the command denies the package installation until a configuration is added to the manifest for this package.
  * If the package contains only JavaScript code, then the command proceeds with the package installation without further checks.


# bundlestore

## Bundle Store

**These commands can only be used with access to an** [**Electrode Native bundle store server**](https://github.com/electrode-io/ern-bundle-store)

Electrode Native bundle store provide features that are close to the ones offered by CodePush but more fitted to development/qa purposes.

Similar to CodePush, ern Bundle Store offers React Native development teams, the ability to push JS bundles that can then be dynamically retrieved and loaded by the native application.

Once a bundle store server is available, any development team or individual developer can easily create (or use existing) store(s) and push JS bundles to the server, using `ern bundlestore` commands. Then, from the native application, anyone can load any bundle from any store, through the `Electrode Native Settings` menu.

The bundle store server keeps all bundles that have been pushed to the different stores, and all these bundles are accessible within the native app. The bundle store also supports source maps out of the box, meaning that if the loaded bundled is crashing at some point, the red screen will show the symbolicated stack trace. Bundle "time machine" and source map support can be very useful, used in conjunction, to pin point the exact location of a crash and in which bundle (which point in time) the problem was introduced.

## Configuring access to bundle store server

The url to the bundle store server should be set in cauldron root configuration (`config/default.json`) as follow :

```javascript
{
  "bundleStore": {
    "url": "localhost:3000"
  }
}
```

Once done, any user connected to the Cauldron will have access to the binary store server.

### Creating a store

Creating a new store can be achieved through the [bundlestore create](/cli-commands/bundlestore/create) command.\
The only parameter this command takes is the name of the store to create. The store name is also the unique identifier of the store, so it shouldn't already exist in the server, otherwise the command will fail.

After creating the store, the command will log the `store access key`. The store access key is needed to upload bundles to this store. Users won't be able to upload bundles to the store without it.\
Assuming the newly created store is meant to be used by developers of a given team, the access key should be shared with the team. Any developer of the team can then start using this store and upload bundles to it.

### Using/Switching store

The [bundlestore use](/cli-commands/bundlestore/use) command should be used to initially start using a given store or switch to a different store that the one currently in use. The only parameter it takes is the given `store access key`. Upon command completion, the `ern` local client will be set to use the store associated with the access key. From this point on, any time an `ern` command is run, it will log the name of the bundle store that it is currently using, next to the Cauldron.

```
[v0.38.0] [Cauldron: -NONE-] [BundleStore: test-store]
```

### Uploading a bundle

`ern` will upload a bundle to the store it is currently set to use (see `Using/Switiching` store above). Then the [bundlestore upload](/cli-commands/bundlestore/upload) command will take care of creating and upload a JS bundle to the active store. Please see the [bundlestore upload](/cli-commands/bundlestore/upload) command reference for additional details, as this command accept many different parameters.

By default, both iOS and Android bundles will be created and uploaded to the server. Also, the bundles will by default be `development` bundles (`__DEV__=true`). These default can be changed through command parameters.

Once the bundle(s) (and source map(s)) have been uploaded to the server, the command will log the `bundle id(s)`. This can be useful for tracking/debugging purposes as the `bundle id(s)` of the currently loaded bundled will also be visible in the native application.

### Loading bundles in the native application

Bundles uploaded to a bundle store can be accessed and launched in the native application via the `Electrode Native Settings` menu (accessible through React Native developer menu).

By default, the bundle store is disabled and the bundle store server host and port is set to `localhost:3000`.

![Bundlestore](/files/-LogYCahGdrjx_o8fSCl)

Server host and port can be set manually, but a better way is to set it directly in the native application when initializing the Container (as seen below for Android). This way, the server host/port will ,by default, point to the server the native application is using, and it will not be needed to set it manually each time the app is installed.

```java
ElectrodeReactContainer.initialize(
            this,
            new ElectrodeReactContainer.Config()
              .bundleStoreHostPort("10.74.57.21:8080"));
```

Tapping the `Store` menu item will display a list of all the stores present in the server. Selecting a store from this list will then give access to all bundles that have been uploaded to this specific store. It is then possible to select a bundle to load from this store through the `Bundle` menu item. By default, the bundle to load will be set to `latest`, meaning that the latest bundle that was uploaded to the store will be loaded. It is possible to load a different bundle (not the latest one) by tapping the `Bundle` menu item and choosing a specific bundle from the list of all uploaded bundles (ordered by time).

The `Auto reload` option (turned on by default) will auto reload the bundle whenever a different bundle is selected from the list of available bundles.

Disabling the bundle store will automatically restore settings that were in use prior to enabling the store and reload the bundle. For example, if the loaded bundle was the one stored in the native application, it will reload this one. If the bundle was the one loaded from a local metro server, it will reconnect to this local server.

### Bundle Store commands reference

[bundlestore create](/cli-commands/bundlestore/create) | Create a new store\
[bundlestore use](/cli-commands/bundlestore/use) | Use a specific store\
[bundlestore delete](/cli-commands/bundlestore/delete) | Delete an existing store\
[bundlestore upload](/cli-commands/bundlestore/upload) | Upload a bundle to a store


# create


# delete


# upload


# use


# binarystore


# add

## Description

* Add a mobile application binary to the binary store

## Syntax

`ern binarystore add <descriptor> <pathToBinary>`

**Arguments**

`<descriptor>`

* A complete native application descriptor (ex: `myapp:android:1.0.0`), representing the native application version associated to this binary.

`<pathToBinary>`

* Relative or absolute path to the binary to add to the binary store. For an `Android` binary the path should point to a `.apk` file, whereas of `iOS` it should point to a `.app`.

**Options**

`--flavor`

* Custom flavor to attach to this binary.
* The binary of a specific application version (for ex `1.0.0`) can have different flavors, representing different build types of the same application version (for example `Dev`/`Prod`/`QA` ...).

## Remarks

* This command will only work if the following conditions are met:
  * A binary store server is running
  * There is an active Cauldron
  * The active Cauldron contains a proper configuration of the binary store
* If a binary already exists in the store for the targeted native application version, it will be replaced.

## Related commands

[ern binarystore get](/cli-commands/binarystore/get) | Get a native application binary from the binary store\
[ern binarystore remove](/cli-commands/binarystore/remove) | Remove a native application binary from the binary store


# get

## Description

* Get a mobile application binary from the binary store

## Syntax

`ern binarystore get <descriptor> <outDir>`

**Arguments**

`<descriptor>`

* A complete native application descriptor (ex: `myapp:android:1.0.0`), representing the native application version associated to this binary.

`<outDir>`

* Relative or absolute path to a directory where the binary will be transferred to. If the directory does not exist, it will be created.

**Options**

`--flavor`

* Custom flavor of this binary that should be retrieved.
* The binary of a specific application version (for ex `1.0.0`) can have different flavors, representing different build types of the same application version (for example `Dev`/`Prod`/`QA` ...).

## Remarks

* This command will only work if the following conditions are met:
  * A binary store server is running
  * There is an active Cauldron
  * The active Cauldron contains a proper configuration of the binary store
* If a binary for the same native application version already exists in `outDir`, it will be replaced
* The binary will be named as follows `[mobile-app-name]:[platform]:[version].[ext]`\
  For example, for `myapp:android:1.0.0`, the binary filename will be `myapp-android-1.0.0.apk`. For `myapp:ios:1.0.0` it will be `myapp-ios-1.0.0.app`.

## Related commands

[ern binarystore add](/cli-commands/binarystore/add) | Add a native application binary to the binary store\
[ern binarystore remove](/cli-commands/binarystore/remove) | Remove a native application binary from the binary store


# remove

## Description

* Remove a mobile application binary from the binary store

## Syntax

`ern binarystore get <descriptor>`

**Arguments**

`<descriptor>`

* A complete native application descriptor (ex: `myapp:android:1.0.0`), representing the native application version associated to this binary.

**Options**

`--flavor`

* Custom flavor of the binary that should be removed.
* The binary of a specific application version (for ex `1.0.0`) can have different flavors, representing different build types of the same application version (for example `Dev`/`Prod`/`QA` ...).

## Remarks

* This command will only work if the following conditions are met:
  * A binary store server is running
  * There is an active Cauldron
  * The active Cauldron contains a proper configuration of the binary store
* If no binary exists in the store for the targeted native application version, the command will fail with an appropriate error message

## Related commands

[ern binarystore add](/cli-commands/binarystore/add) | Add a native application binary to the binary store\
[ern binarystore get](/cli-commands/binarystore/get) | Get a native application binary from the binary store


# code-push

Electrode Native ships with a \[CodePush] integration, to allow for releasing code updates over the air, to released native application versions.

A few commands are exposed by Electrode Native to release CodePush updates, promote releases and update existing releases distribution details.

Please note that only JavaScript code can be updated through CodePush releases, not native code.

## Prerequisites

A Cauldron needs to be active

`code-push` commands only works with a supporting Cauldron. You should have properly setup and activated a Cauldron in order to work with CodePush.

## Setup

### Step 1: Create a CodePush account

CodePush was recently integrated into Microsoft App Center, therefore you'll need to follow instructions on [this page](https://docs.microsoft.com/en-us/appcenter/distribution/codepush/migrationguide) to setup an app center account.

After installing the App Center CLI and logging in through the CLI, please keep the generated token (a.k.a access key) handy, as Electrode Native needs it to perform `code-push` related commands.

You'll then need to add the code push access key to the local Electrode Native configuration. This needs to be done local to each workstation/box that need to issue `code-push` commands. The CodePush access key is not stored in the Cauldron, for security reasons.

```bash
ern platform config set codePushAccessKey YOUR_CODE_PUSH_ACCESS_KEY
```

### Step 2: Create your application in CodePush

Once you are logged-in with the App Center CLI, you'll need to create your application in App Center.

We recommend that you create two different application entries, for your application, one per platform. For example if your application is named `MyAwesomeApp`, you should create an application named `MyAwesomeAppIos` and another named `MyAwesomeAppAndroid`.

The name of the unsuffixed application should match the name you will use (or that you already use) in your Cauldron. For example, if you named your application as `MyCoolApp` in your Cauldron, you cannot use `MyAwesomeApp` for naming it in CodePush.

Refer to the App Center documentation for more details on the command, but for illustration, here are the commands we would run based on our imaginary application name:

```bash
appcenter apps create -p "React-Native" -o "iOS" -d "MyAwesomeAppIos"
appcenter apps create -p "React-Native" -o "Android" -d "MyAwesomeAppAndroid"
```

### Step 3: \[Optional] Set the application names in your Cauldron configuration

If you have named your CodePush application as recommended, with a platform suffix (`MyAwesomeApp` -> `MyAwesomeAppIos` and `MyAwesomeAppAndroid`) then you don't have to do any specific configuration in the Cauldron as this convention will be used when running `code-push` commands.

However, if you have used a different naming convention, for example if you name `MyAwesomeApp` Android as `MyAwesomeAppForAndroid`, you will need to specify the custom name in your Cauldron configuration. You should edit the `cauldron.json` file of your Cauldron manually, as we don't have commands yet to edit configuration in the Cauldron.

You should specify the custom application name in the `codePush` config object of the native application platform, as follow:

```javascript
{
  "nativeApps": [
    {
      "name": "MyAwesomeApp",
      "platforms": [
        {
          "name": "android",
          "config": {
            "codePush": {
              "appName": "MyAwesomeAppForAndroid"
            }
          }
        }
      ]
    }
  ]
}
```

### Step 4: Create your CodePush deployment names

Think about deployment names as different deployment environments. You can choose as many deployment names as you see fit, though most users usually stick with the basic deployment names `Staging` and `Production` that app center creates for you when you add your app.

You will get a different 'key' for each app name / deployment name combination.

The keys are stored in your native application, and based upon the key you select at runtime, your native application will only retrieve the releases from a specific deployment name.

Enter the command below to list the deployments associated with an app

```bash
appcenter codepush deployment list -a <YourAppName>
```

Refer to the App center documentation for more details on how to create deployment environments, but for illustration, here are the commands we would run for our `MyAwesomeApp` application, to create `Dev` deployment name :

```bash
appcenter codepush deployment add -a MyAwesomeAppIos Dev
appcenter codepush deployment add -a MyAwesomeAppAndroid Dev
```

NOTE: If you get `not a valid application id` error, run the `appcenter apps list` command to get the application id to pass in for the commands.

### Step 5: \[Optional] Store the deployment names in your Cauldron

You need to pass a deployment name to all `code-push` commands. This deployment name can be provided as a command option, however if you'd rather like to be prompted for a deployment name to choose from, you can store the deployments names associated to a native application name/platform inside the Cauldron `codePush` configuration.

For illustration, here is how we would store the two deployments we created for our `MyAwesomeApp` Android in our Cauldron:

```javascript
{
  "name": "android",
  "config": {
    "codePush": {
      "deployments": [
        {
          "name": "Production"
        },
        {
          "name": "Staging"
        }
      ]
    }
  }
}
```

### Step 6: \[Optional] Configure version name modifiers in Cauldron

Some native applications are using version name modifiers to distinguish between different environments. For example for our `MyAwesomeApp` on Android, we might use the version suffix `-qa-debug` to denote a debug version built for `QA` and `dev-debug` to denote a `Development` debug version. In this case, for any given version number (for example `1.0.0`) we can have three `variants` of the version : `1.0.0` (Production), `1.0.0-dev-debug` (Dev) and `1.0.0-qa-debug` (QA).

The problem in that scenario, is that, when doing a release targeting a specific native application version, `CodePush` will only install it for versions matching the targeted version string. i.e if we are doing a CodePush release targeting `1.0.0`, then, users running the `1.0.0-dev-debug` version won't get the release.

If you are using version modifiers for your native application, then you should create an appropriate `codePush` configuration entry in your Cauldron.

For example, for your Android application, if `-dev-debug` versions are associated to your `Staging` deployment name and `-qa-debug` versions are associated to your `QA` deployment name, then you should setup the following `codePush` configuration in your Cauldron :

```javascript
{
  "name": "android",
  "config": {
    "codePush": {
      "deployments": ["Staging", "QA", "Production"],
      "versionModifiers": [
        {
          "deploymentName": "Staging",
          "modifier": "$1-qa-debug"
        },
        {
          "deploymentName": "QA",
          "modifier": "$1-dev-debug"
        }
      ]
    }
  }
}
```

### Step 7: \[Optional] Limit the number of CodePush entries in your Cauldron

For each CodePush release or promotion, a specific CodePush entry will be stored in the native application version in the Cauldron.

If you are doing a lot of CodePush releases, you might want to limit the number of CodePush entries stored in the Cauldron, to keep only the last X entries.

This can be achieved through Cauldron `codePush` configuration in the Cauldron top level `config` object. For example, if we desired to keep track of only the last two CodePush release entries for each native application version (per deployment name), our configuration would be as follow:

```javascript
{
  "codePush": {
    "entriesLimit": 2
  }
}
```

By default, if not configured in Cauldron, all CodePush entries will be stored.

### Step 8: Setup code-push in your MiniApp(s)

For each of your MiniApp(s) that should support over the air updates, you should add the `react-native-code-push` dependency.

If not done already, add the `react-native-code-push` dependency to your MiniApp. From your MiniApp root directory, run the following command:

```bash
ern add react-native-code-push
```

Then in your MiniApp, decorate your MiniApp `Component` class with `codePush`, as illustrated by the following sample :

```javascript
import codePush from 'react-native-code-push'

// [...]

class App extends Component {
  // [...]
}

App = codePush({
  checkFrequency: codePush.CheckFrequency.ON_APP_RESUME,
  installMode: codePush.InstallMode.ON_NEXT_RESUME,
  minimumBackgroundDuration: 60 * 2,
})(App)
```

You can use different values for `checkFrequency` or `installMode` based on your use case.

Refer to the official [code-push plugin documentation](https://github.com/microsoft/react-native-code-push#plugin-usage) for more details.

### Step 9: \[Native Application] Initialize the Container with the CodePush configuration

On the native side, as soon as you create a Container that includes at least in the native application code, you will need to initialize the Container with a `CodePush` plugin configuration. This configuration takes the `deployment key` to be used at runtime. This is at this step that you can select which deployment key to be used, based on the build type.

Here follows an illustration on how to initialize the Container with CodePush configuration on both Android and iOS.

#### Android

```java
ElectrodeReactContainer.initialize(
        new CodePushPlugin.Config("DEPLOYMENT_KEY")
        // [...]
);
```

#### iOS

```
ElectrodeContainerConfig *containerConfig = [[ElectrodeContainerConfig alloc] init];
ElectrodeCodePushConfig *codePushConfig = [[ElectrodeCodePushConfig alloc] initWithDeploymentKey:@"DEPLOYMENT_KEY" serverURL:nil containerConfig:containerConfig];
[ElectrodeReactNative startWithConfigurations:containerConfig electrodeCodePushConfig:codePushConfig];
```

### Step 10: CodePush your first release

Head over to the [code-push release](/cli-commands/code-push/release) command documentation to do your first release through CodePush.


# patch

code-push [prerequisites](/cli-commands/code-push) need to be met in order to run this command

## Description

* Patch a CodePush release.
* This command only works for entries that have been released through `ern code-push release` or promoted through `ern code-push promote`.
* Update the corresponding CodePush entry in Cauldron with the changes.

## Syntax

```bash
ern code-push patch
```

### Options

`--descriptor/-d <descriptor>`

* Specify a target native application version (following the *complete native application descriptor* format) that contains the CodePush release to patch.
* **Default** The command will list all released native applications versions stored in the Cauldron and will prompt to select a target native application version from the list.

`--label/-l`

* Specify the `label` (identifier) of the CodePush release to patch.
* **Default** The command will display a prompt to input the label.

`--disabled/-x`

* Update the distribution status of the matched CodePush release. Setting this flag to `true` will disable the CodePush release distribution, while setting this flag to `false` will enable the CodePush release distribution.
* **Default** No change to the distribution status.

`--deploymentName/-d <deploymentName>`

* Update the CodePush deployment name (Production, Staging ...) of the matched release.
* **Default** No change to the deployment name.

`--mandatory/-m`

* Update the mandatory status of the CodePush release entry. Setting this flag to `true` will make the CodePush release mandatory (it will be immediately downloaded and installed), whereas setting this flag to `false` will make the CodePush release non mandatory.
* **Default** No change to the mandatory status.

`--rollout/-r <percentage>`

* Update the percentage of users who will have access to the CodePush release.
* **Default** No change to the rollout percentage.

`--description/--des`

* Description of the changes made to the app with this release
* **Default** Empty String

## Related commands

* [code-push promote](/cli-commands/code-push/promote) | Promote a release to a different deployment name
* [code-push release](/cli-commands/code-push/release) | Issue a CodePush release


# release

code-push [prerequisites](/cli-commands/code-push) need to be met in order to run this command

## Description

* Release one or more MiniApp(s) version(s) to one or more released native application version(s).
* Perform compatibility checks to ensure that the new MiniApp(s) version(s) are compatible with the target native application version(s).
* Update the Cauldron with a new `CodePush` entry containing data about the release.

**Note:** The `ern code-push <miniapps..>` command can release JavaScript code only, not native. Therefore compatibility checks will ensure that the MiniApp(s) native dependencies are compatible with the versions running in the target native application version.

## Syntax

```bash
ern code-push release
```

## Options

`--baseComposite <compositePath>`

* Git or File System path, to the custom Composite repository (refer to the [custom Composite documentation](/reference/index) for more information).

`--miniapps`

* One or more MiniApps (separated by spaces) version(s) to CodePush.
* You can use npm published versions or git based path (SHA or tag only).
* If you are CodePushing a MiniApp that is using a git path in Container, please CodePush using a git path. If you are CodePushing a MiniApp that is using a npm published version in the Container, please CodePush using an npm published version. Do not mix.
* You can't use the `file` scheme for the MiniApp(s).

`--jsApiImpls`

* One or more JS API implementations (separated by spaces) version(s) to CodePush.
* You can use npm published versions or git based path (SHA or tag only).
* If you are CodePushing a JS API implementation that is using a git path in Container, please CodePush using a git path. If you are CodePushing a JS API implementation that is using a npm published version in the Container, please CodePush using an npm published version. Do not mix.
* You can't use the `file` scheme for the MiniApp(s).

`--descriptors/-d <descriptors..>`

* Specify one or more target native application version to release the MiniApp(s) to, following the *complete native application descriptor* format.

`--semVerDescriptor`

* A native descriptor using a semantic version string for its version. The release will target all versions matching the semver.

If no `descriptors` nor a `semVerDescriptor` is specified, the command will list all released native application versions stored in the Cauldron and will display a prompt to select one or more target native application version(s).

`--sourceMapOutput`

* Path to source map file to generate for this code push bundle

`--force/-f`

* Bypass all compatibility checks and force OTA update through CodePush.
* **Default** false

`--deploymentName/-d <deploymentName>`

* Specify the CodePush deployment name that this update is targeting (Production, Staging ...)
* **Default** The command will display a prompt asking to input the deployment name. If deployment names for your native applications are stored in the Cauldron, the prompt will display the deployment names and ask to select one.

`--targetBinaryVersion/-t <targetBinaryVersion>`

* Semver expression that specifies the binary app version this release is targeting
* If omitted, the release will target the exact version of the descriptor
* If versionModifier is specified in the codePush config , exact version of the descriptor is appended to versionModifier
* For using `targetBinaryVersion` option users must target only 1 descriptor
* For using `targetBinaryVersion` option users cannot use semVerDescriptor

`--mandatory/-m`

* Specify that the release is mandatory (will be immediately downloaded and installed).
* **Default** false

`--rollout/-r <percentage>`

* Specify the percentage of users who will have access to this release.
* **Default** 100

`--skipConfirmation/-s`

* Skip confirmation prompts
* **Default** false

`--description/--des`

* Description of the changes made to the app with this release
* **Default** Empty String

`--disableDuplicateReleaseError`

* When this flag is set, releasing a package that is identical to the latest release will produce a warning instead of an error
* **Default** false

## Remarks

* MiniApps are packaged in a single JavaScript bundle. If the native application version contains 5 MiniApps and only one MiniApp is updated, then the remaining 4 MiniApp versions will remain untouched in the bundle.

## Related commands

* \[code-push promote] | Promote a release to a different deployment name
* \[code-push patch] | Patch a release


# promote

code-push [prerequisites](/cli-commands/code-push) need to be met in order to run this command

## Description

* Promote a CodePush release to a different deployment name and/or native application versions.

### Syntax

```bash
ern code-push promote
```

### Options

`--description/--des`

* Description of the changes made to the app with this release. If omitted, the description from the release being promoted will be used.
* **Default** Empty string

`--disableDuplicateReleaseError`

* When this flag is set, promoting a package that is identical to the latest release on the target deployment will produce a warning instead of an error
* **Default** false

`--force/-f`

* Bypass all compatibility checks and force OTA update through CodePush. **USE AT YOUR OWN RISK**
* **Default** false

`--label/-l`

* Promote the release matching this specific label.
* **Default** The latest release matching sourceDescriptor/sourceDeploymentName pair will be promoted.

`--mandatory/-m`

* Specify that the promoted release is mandatory (will be immediately downloaded and installed).
* **Default** false

`--reuseReleaseBinaryVersion`

* Indicates whether to reuse the target binary version that was used for the initial release
* If omitted, and `targetBinaryVersion` is not set, the promotion will target the exact version of the descriptor
* This option is mutually exclusive with `targetBinaryVersion`

`--rollout/-r <percentage>`

* Specify the percentage of users who will have access to this release.
* **Default** 100

`--skipConfirmation/-s`

* Skip confirmation prompts
* **Default** false

`--skipNativeDependenciesVersionAlignedCheck/-n`

* Skip the check to compare native dependencies version alignment
* This flag helps skipping native dependencies check for promoting same bundle label to multiple target versions
* **Default** false

`--sourceDeploymentName`

* The deployment name of the release to promote (Staging for example).
* **Default** The command will prompt to input the deployment name, or display a list of deployment names stored in the Cauldron, to choose from.

`--sourceDescriptor <descriptor>`

* Specify the native application version from which to promote a release in the form of a *complete native application descriptor*.
* The release to be promoted will be the latest non disabled release of this native application version.
* **Default** The command will list all released native applications versions stored in the Cauldron and will prompt to select a target native application version from the list.

`--targetBinaryVersion/-t <targetBinaryVersion>`

* Semver expression that specifies the binary app version this promotion is targeting
* If omitted, and `reuseReleaseBinaryVersion` is not set, the promotion will target the exact version of the descriptor
* If `versionModifier` is specified in the codePush config, it will be applied
* For using `targetBinaryVersion` option users must target only 1 descriptor
* For using `targetBinaryVersion` option users cannot use semVerDescriptor
* This option is mutually exclusive with `reuseReleaseBinaryVersion`

`--targetDeploymentName`

* The deployment name to promote the release to (Production for example).
* **Default** The command will prompt to input the deployment name, or display a list of deployment names stored in the Cauldron, to choose from.

`--targetDescriptors <descriptors..>`

* Specify one or more target native application version to promote the release to, in the form of a *complete native application descriptor* list (separated by spaces).
* The target descriptor can be the same as the source descriptor if the promotion is only changing the deployment name (for example promoting a release from Staging to Production for the same native application version).

`--targetSemVerDescriptor <descriptor>`

* A native descriptor using a semantic version string for its version. The promotion will target all native application versions matching the semver.
* If no `targetDescriptors` nor a `targetSemVerDescriptor` is specified, the command will list all released native application versions stored in the Cauldron and will display a prompt to select one or more target native application version(s) for the promotion.

### Related commands

* [code-push release](/cli-commands/code-push/release) | Issue a CodePush release
* [code-push patch](/cli-commands/code-push/patch) | Patch a release


# compat-check

## Description

* Check the compatibility of one or more MiniApps with a given native application version.
* Display a compatibility report indicating if the MiniApps are compatible with the given native application version
* Display a formatted table listing all compatible dependencies and their versions as well as incompatible dependencies to help you pinpoint any problematic non-compatible native dependencies

## Syntax

`ern compat-check`

* You can run the `ern compat-check` command without arguments if you are in a MiniApp directory.
* If you run the `ern compat-check` command without arguments and you are not in a MiniApp directory, the command logs an error and exits.

`ern compat-check <miniapp>`

* Check the compatibility of a specified MiniApp with a native application version &#x20;

  The MiniApp can be any valid Yarn package descriptor or you can use Git or other file system path scheme.

**Options**

`--miniapps/-m`

* Check the compatibility of one or more MiniApps with a native application version &#x20;

  The MiniApps can be any valid Yarn package descriptor or you can use Git or other file system path scheme.

`--descriptor/-d`

* Check the compatibility of one or more MiniApps with a native application version &#x20;

  Specify the native application version as a *complete native application descriptor* for which to check compatibility with the MiniApps


# create-api-impl

## Description

* Create an implementation skeleton project for a specified API &#x20;

  **Note** This command does not require that you are the author of the API that you are planning to implement, but it requires that the API has been created first.

## Syntax

`ern create-api-impl <apiName> [apiImplName]`

**Arguments**

`<apiName>`

* The package descriptor of the API for which to create an API implementation project
* We recommend suffixing the name of API implementation with suffix `-api-impl`

`[apiImplName]`

* The name of the API implementation project. The API implementation name must follow Electrode Native module name rules.
* If name of the apiImpl is missing the apiName is converted to came case notation and numbers are removed if any.

**Options**

`--nativeOnly/-n`

* Generate an implementation skeleton project for a native implementation of the API

`--jsOnly/-j`

* Generate an implementation skeleton project for a JavaScript implementation of the API

`--packageName/-p`

* Specify the npm package name to use for the API implementation.
* Add the package name automatically in the `package.json` of the generated API implementation.
* **Default** The command will prompt for the package name to use.

`--scope/-s`

* Specify the npm package scope to use for the API implementation.
* Add the package scope automatically in the `package.json` of the generated API implementation.
* **Default** Package will be unscoped.

`--outputDirectory/-o <directory>`

* Generate the project in a specified output directory
* **Default** The project is generated in a new directory named as the API implementation project. The new directory is created in the current working directory.

`--hasConfig`

* Indicates if this api implementation requires some config during initialization.
* This option will be stored and reused during container generation to enforce config initialization

`--skipNpmCheck`

* Skip the check ensuring package does not already exists in npm registry
* **Default** The value defaults to false.

`--force/-f`

* Force the creation of an API implementation project
* **Caution** If there is already an implementation project in the target directory, the new project will overwrite the existing project completely. Use this option only if you are sure that you can overwrite any existing project.

`--manifestId <manifestId>`

* Id of the override Manifest entry to retrieve dependencies versions from (see [override Manifest](/reference/index-2/override) for more info)

## Examples

`ern create-api-impl react-native-weather-api`

This example shows how to create an API skeleton project named `ReactNativeWeatherApiImpl`.

`ern create-api-impl react-native-weather-api MyApi`

This example shows how to create an API skeleton project named `MyApi`.

`ern create-api-impl react-native-weather-api MyApi -p my-weather-api-impl`

This example shows how to create an API skeleton project named `MyApi`. The package name for this project is `my-weather-api-impl`.

`ern create-api-impl react-native-weather-api MyApi -p my-weather-api-impl -s org`

This example shows how to create an API skeleton project named `MyApi`. The package name for this project is `@org/my-weather-api-impl`.

## Remarks

* If name of the apiImpl is missing the apiName is converted to came case notation and numbers are removed if any.
* If you do not specify a platform (for example, native v.s JavaScript), you are prompted to select a platform.

## Related commands

[ern create-api](/cli-commands/create-api) | Create an API


# create-api

## Description

* Create a new API project based on a Swagger schema

## Syntax

`ern create-api <apiName>`

**Arguments**

`<apiName>`

* The name to use for this API. The API name must follow Electrode Native module name rules.
* We recommend suffixing the name of API with suffix `-api`

**Options**

`--scope/-s <scope>`

* Specify a given npm scope for the API project package
* Add the package scope automatically in the `package.json` of the generated API.
* **Default** Package will be unscoped.

`--packageName/-p <name>`

* Specify the npm package name to use for the API.
* Add the package name automatically in the `package.json` of the generated API.
* **Default** The command will prompt for the package name to use.

`--apiVersion/-a <version>`

* Specify an initial version for the API
* **Default** If this option is not used, the API defaults to 0.0.1.

`--apiAuthor/-u <author>`

* Specify the author of the API in the `package.json` file of the API
* **Default** If this option is not used, the author is not set.

`--schemaPath/-m <schemaPath>`

* Generate the API using a pre-existing Swagger schema located at the given `schemaPath`
* **Default** If this option is not used the command uses a default starter schema to generate the initial API. You can modify this option at a later time and then regenerate the API using the `ern regen-api` command.

`--skipNpmCheck`

* Skip the check ensuring package does not already exists in npm registry
* **Default** The value defaults to false.

`--manifestId <manifestId>`

* Id of the override Manifest entry to retrieve dependencies versions from (see [override Manifest](/reference/index-2/override) for more info)

## Examples

`ern create-api weather`\
This example shows how to create a unscoped package named `weather-api`. The API project is located in the new directory named `weather`.

`ern create-api weather --scope MyCompany`\
This example shows how to create a scoped package named `@MyCompany/weather-api`.

`ern create-api weather --schemaPath schema.json`\
This example shows how to create a unscoped package named `weather-api`. The API project is located in the new directory named `weather`. The `--schemaPath` option specifies location of file containing pre-existing Swagger schema.

## Remarks

* The generated API project contains the API client-code for the three platforms (JavaScript, Android, and iOS) as well as any models and code to guide the implementation of the API.
* The generated API project is meant to be published to npm and it contains the `package.json` file.
* Once you have a version of your API ready, you should publish it to npm to make it available for people to use. Considering that the API is published to npm, you should make sure before generating the API, that the name is not already used by another API otherwise you won't be able to publish an API with a duplicate name.
* The API project is created in a new directory named after the API project name.

## Related commands

[ern regen-api](/cli-commands/regen-api) | Add a new request, event, or model to an existing API project schema and regenerate the API\
[ern create-api-impl](/cli-commands/create-api-impl) | Create an implementation skeleton project for a specified API


# create-composite

## Description

* Create a JS Composite project locally.

## Syntax

`ern create-composite`

**Options**

`--baseComposite <compositePath>`

* Git or File System path, to the custom Composite repository (refer to the [custom Composite](https://github.com/electrode-io/electrode-native/tree/c6be4730926296bbcab7b0dce58f618c5c57e03b/docs/cli/platform-parts/composite/index.md) documentation for more information).

`--descriptor/-d <descriptor>`

* Create a new JS Composite including all the MiniApps listed in the Cauldron for the given *complete native application descriptor*

`--extraJsDependencies/-e <dependencies>`

* Add extra JavaScript dependencies to the JS Composite project.

`--fromGitBranches`

* Create Composite using the latest commits made to each of the MiniApp branches (HEAD), rather than using the MiniApps SHAs that are inside the current Container version.
* This flag is only used when creating a Composite from a Cauldron descriptor
* This flag will be ignored if the target descriptor does not contain any MiniApps tracking git branches

  **Default** false

`--jsApiImpls`

* One or more JS API implementation(s) to add to the JS Composite project.
* The JS API implementation(s) passed to this command can be a valid Yarn package format or a Git format or file scheme.
* This option can only be used if the `--descriptor` option is not used.

`--miniapps/-m <miniapps>`

* One or more MiniApps to add to the JS Composite project.
* The MiniApps passed to this command can be a valid Yarn package format or a Git format or file scheme.
* This option can only be used if the `--descriptor` option is not used.

`--outDir/--out <directory>`

* Specify the directory to output the generated JS Composite project to
* The output directory should either not exist (it will be created) or be empty
* **Default** If this option is not provided, the Composite is generated in the default platform directory `~/.ern/containergen/miniAppsComposite`.

## Related commands

[ern create-container](/cli-commands/create-container) | Creates a Container locally


# create-container

### Description

* Create a new Container project locally.

### Syntax

`ern create-container`

**Options**

`--baseComposite <compositePath>`

* Git or File System path, to the custom Composite repository (refer to the [custom Composite](https://github.com/electrode-io/electrode-native/blob/master/docs/cli/platform-parts/composite/index.md) documentation for more information).

`--descriptor/-d <descriptor>`

* Create a new container including all the MiniApps listed in the Cauldron for the given *complete native application descriptor*
* Use this option if you want to locally generate a container that mirrors the container of a given native application version.

`--devJsBundle`

* Will generate a development JavaScript bundle rather than a production one. **Default** false

`--fromGitBranches`

* Create Container using the latest commits made to each of the MiniApp branches (HEAD), rather than using the MiniApps SHAs that are inside the current Container version.
* This flag is only used when creating a Container from a Cauldron descriptor
* This flag will be ignored if the target descriptor does not contain any MiniApps tracking git branches **Default** false

`--miniapps/-m <miniapps>`

* Create a new custom container including all the given MiniApps
* The MiniApps passed to this command can be a valid Yarn package format or a Git format or file scheme.

`--platform/-p <android|ios>`

* Specify the target platform for this container
* If not explicitly provided, the command prompts you to choose between the iOS or the Android platform before execution.

`--outDir/--out <directory>`

* Specify the directory to output the generated container to
* The output directory should either not exist (it will be created) or be empty
* **Default** If this option is not provided, the container is generated in the default platform directory `~/.ern/containergen/out`.

`--ignoreRnpmAssets`

* Inform the Container generator to ignore any rnpm assets optionally declared by MiniApps. This can be used in case you want to keep specific rnpm assets inside the native application itself and not the Container.
* This flag wil have no effect for a Container generated from a Cauldron as the Container configuration stored in the Cauldron will take precedence.
* **Default** Do not ignore rnpm assets and package them inside the generated Container.

`--extra/-e`

* Optional extra configuration specific to creating container
* Override some ios or android container generation configuration by passing `androidConfig` and/or `iosConfig` attributes
  * **As a json string** For example `--extra '{"androidConfig": {"androidGradlePlugin": "3.2.1","rnGradlePlugin": "0.0.6","buildToolsVersion": "28.0.3","compileSdkVersion": "28","gradleDistributionVersion": "4.6","minSdkVersion": "19","sourceCompatibility": "VERSION_1_8","supportLibraryVersion": "28.0.0","targetCompatibility": "VERSION_1_8","targetSdkVersion": "28"}}'` Find more information on [android configuration](https://github.com/electrode-io/electrode-native/blob/master/docs/cli/plaform-parts/container-integration.md)

    or

    `--extra '{"iosConfig": {"deploymentTarget": "11.0"}}'` Find more information on [iOS configuration](https://github.com/electrode-io/electrode-native/blob/master/docs/cli/plaform-parts/container-integration.md)
  * **As a file path** For example `--extra <path>/container-config.json` In that case, the configuration will be read from the file.
  * **As a Cauldron file path** For example `--extra cauldron://config/container/container-config.json` In that case, the configuration will be read from the file stored in Cauldron. For this way to work, the file must exist in Cauldron (you can add a file to the cauldron by using the \[ern cauldron add file] command). Find more information on [configuring via cauldron](https://github.com/electrode-io/electrode-native/blob/master/docs/cli/plaform-parts/container-integration.md)
* Optional hooks to run an arbitary script before or after js bundling is possible.
  * If a script is defined as a `preBundle` hook, it will be executed after the composite generation, prior to running metro bundler, from the directory containing the generated composite project.
    * **As a json string** `--extra '{"containerGenerator": {"hooks": {"preBundle": "/workspace/ern/picking-miniapp/script/pre-script.sh"}}}'`
    * **As a file path** `--extra <path>/container-config.json`
    * **As a Cauldron file path** `--extra cauldron://config/config.json`
  * If a script is defined as a `postBundle` hook, it will be executed just after metro bundler has been run, from the directory containing the bundle.
    * **As a json string** `--extra '{"containerGenerator": {"hooks": {"postBundle": "/workspace/ern/picking-miniapp/script/post-script.sh"}}}'`
    * **As a file path** `--extra <path>/container-config.json`
    * **As a Cauldron file path** `--extra cauldron://config/config.json`

Program to use to run the script should be indicated using [shebang pattern](https://en.wikipedia.org/wiki/Shebang_\(Unix\)) in the script itself as first line.

`--skipInstall`

* Only used when generating an iOS Container with React Native >= 0.61.
* When set, skip `yarn install` and `pod install` after generating the container.
* **default** true on Windows/Linux, false on macOS

`--sourceMapOutput`

* Path to source map file to generate for this container bundle

`--resetCache`

* Indicates whether to reset the React Native cache prior to bundling
* **Default** false

### Remarks

* The `ern create-container` command can be used to create a container locally, for development, debugging and experimentation purposes.
* Container generation and transformation/publication are separate processes (see `Related commands` section below for specific commands)
* To create a container that is published so that your native application team can use the container, you should use one of the Cauldron commands to add your MiniApps to a specified native application version in the Cauldron, which will trigger the generation and publication of a Container. See *Related commands*.

### Related commands

[ern transform-container](/cli-commands/transform-container) | Transform a local Container. [ern publish-container](/cli-commands/publish-container) | Publish a local Container. [ern create-composite](/cli-commands/create-composite) | Creates a JS Composite project locally


# create-plugin-config

## Description

* Automatically generates the Manifest configuration of a given React Native plugin

## Syntax

`ern create-plugin-config <plugin>`

**Arguments**

`<plugin>`

* The npm package name of the React Native plugin for which to generate configuration. If no version is specified, latest will be considered.

## Examples

`ern create-plugin-config react-native-example-plugin`

Creates a plugin configuration for `react-native-example-plugin` latest version

`ern create-plugin-config react-native-example-plugin@1.2.0`

Creates a plugin configuration for `react-native-example-plugin` version `1.2.0`

## Remarks

* This command needs to be run from the root of a cloned Manifest repository
* This command only creates the configuration in the manifest locally. You will need to manually review/test and then git add/commit/push the changes to the Manifest repository.
* This command will fail in case it detects that the plugin should be configurable as it doesn't support Configurable Plugin config generation.


# publish-container

### Description

* This command can be used to publish a local Container to a repository, using a given publisher.

## Currently Available Official Publishers

* [git](https://github.com/electrode-io/ern-container-publisher-git)\
  To publish Android and iOS Electrode Native Containers to a remote git repository. The git repository provider does not matter (GitHub, BitBucket, TFS ...).
* [maven](https://github.com/electrode-io/ern-container-publisher-maven)\
  To publish Android Electrode Native Containers to a local or remote Maven repository.
* [jcenter](https://github.com/electrode-io/ern-container-publisher-jcenter)\
  To publish Android Electrode Native Containers to a remote JCenter repository.
* [dummy](https://github.com/electrode-io/ern-container-publisher-dummy)\
  This publisher is mostly used for testing and as starter simple publisher reference to create your own. It does not actually publish the Containers anywhere.

### Syntax

`ern publish-container`

**Options**

`--containerPath`

* The local file system path to the directory containing the Container to publish.
* **Default** If this option is not provided, the command will look for a Container in the default platform directory `~/.ern/containergen/out/[platform]`.

`--platform`

* Specify the native platform of the target Container to publish (`android` or `ios`)
* This option is required, there is no default.

`--version/-v`

* Specify the Container version to use for publication.
* The version must be in the format: `x.y.z` where x, y and z are integers. For example `version=1.2.30`.
* Defaults to `1.0.0`.

`--publisher/-p`

* Specify the Container publisher to use.
* This option is required, there is no default.
* You can also use a local file system path to a Container publisher package (only used for developing custom publishers)

`--url/-u`

* The url to publish the Container to
* Some publishers might not need an url. Check the specific Container publisher documentation for reference

`--extra/-e`

* Extra configuration specific to the publisher used.
* Some publishers might not need an extra configuration. Check the Container publisher documentation for reference.
* There is three different ways to provide the json extra configuration :
  * **As a json string** &#x20;

    For example `--extra '{"configKey": "configValue"}'`
  * **As a file path** &#x20;

    For example `--extra <path>/publisher-config.json` &#x20;

    In that case, the configuration will be read from the file.
  * **As a Cauldron file path** &#x20;

    For example `--extra cauldron://config/publishers/publisher-config.json` &#x20;

    In that case, the configuration will be read from the file stored in Cauldron. &#x20;

    For this way to work, the file must exist in Cauldron (you can add a file to the cauldron by using the [ern cauldron add file](https://github.com/electrode-io/electrode-native/tree/d12c94d8ecea7762fd570a45d5f4837147cbbccc/docs/cli/add/file.md) command).

`--inPlace`

* Run the publisher directly from the container directory instead of a temporary directory
* Defaults to `false`

### Related commands

[ern create-container](/cli-commands/create-container) | Create a new container (native or JavaScript only) locally to the workstation.


# transform-container

## Description

* This command can be used to transform a local Container using a given Container transformer.

## Currently Available Official Transformers

* [pbxproj](https://github.com/electrode-io/ern-container-transformer-pbxproj)\
  Can be used to patch one or more pbxproj (iOS project file) included in the Container, in specific ways.
* [build-config](https://github.com/electrode-io/ern-container-transformer-build-config)\
  Can be used to update Build Configuration(s) -build settings- of a generated iOS Container.
* [script](https://github.com/electrode-io/ern-container-transformer-script)\
  This transformer allows for executing an arbitrary script to transform the Container in some custom way. It supports transformation of both iOS and Android Containers.
* [git-patch](https://github.com/electrode-io/ern-container-transformer-git-patch)\
  Can be used to apply one or more sequential git patches to the Container.

### Syntax

`ern transformer-container`

**Options**

`--containerPath`

* The local file system path to the directory containing the Container to transform.
* **Default** If this option is not provided, the command will look for a Container in the default platform directory `~/.ern/containergen/out/[platform]`.=

`--platform/-p`

* Specify the native platform of the target Container to transform.
* This option is required, there is no default (unless `--descriptor` is used)

`--transformer/-t`

* Specify the Container transformer to use (for ex `build-config`).
* Can also include a specific version or a version range (for ex `build-config@1.0.0` or `build-config@^1.0.0`)
* If no version is specified, the latest available version of the publisher will be used at the time of publication (this is a bit risky given that new major publisher versions will contain breaking changes. We **recommend** that you use a specific version or version range allowing minor and patch updates only)
* It is also possible to pass a local file system path to a Container transformer package (only used for transformers development).
* This option is required, there is no default (unless `--descriptor` is used)

`--extra/-e`

* Extra configuration specific to the transformer (as json)
* Some transformers might not need any extra configuration. Check the specific Container transformer documentation for reference.
* There is three different ways to provide the json extra configuration :
  * **As a json string** &#x20;

    For example `--extra '{"configKey": "configValue"}'`
  * **As a file path** &#x20;

    For example `--extra <path>/transformer-config.json` &#x20;

    In that case, the configuration will be read from the file
  * **As a Cauldron file path** &#x20;

    For example `--extra cauldron://config/publishers/transformer-config.json` &#x20;

    In that case, the configuration will be read from the file stored in Cauldron. &#x20;

    For this way to work, the file must exist in Cauldron (you can add a file to the cauldron by using the [ern cauldron add file](https://github.com/electrode-io/electrode-native/tree/ae752c5189387f07bf0266cc9e5aaa69b63f9fed/docs/cli/add/file.md) command).

### Related commands

[ern create-container](/cli-commands/create-container) | Create a new Container (native or JavaScript only) locally to the workstation.\
[ern publish-container](/cli-commands/publish-container) | Publish a Container.


# run-container-pipeline

## Description

* This command can be used to run a local pre-generated Container through a Container pipeline *(aribtrary sequence of transformers & publishers)*

## Syntax

`ern run-container-pipeline`

**Options**

`--containerPath`

* The local file system path to the directory containing the Container to run through the pipeline.
* **Default** If this option is not provided, the command will look for a Container in the default platform directory `~/.ern/containergen/out/[platform]`.

`--pipeline`

* Path to the JSON file containing the pipeline configuration.
* Can either be a local file system path to the JSON file, or a path to a JSON file stored in the cauldron *(for example cauldron://config/my-pipeline.json for a my-pipeline.json file stored in config directory in the cauldron)*

`--platform`

* Specify the native platform of the target Container (`android` or `ios`)
* This option is required, there is no default.

`--version/-v`

* Specify the Container version to use for publication.
* The version will be ignored if the pipeline is only composed of transformers.
* Defaults to `1.0.0`.

## Remarks

Refer to [container publication](broken://pages/-LFa-NYD_g_zd7ih8zr6) and [container integration](broken://pages/-LFyIgCvrsm53E-bgDC3) documentation for more details regarding the structure of the JSON pertaining to pipeline configuration.


# create-miniapp

## Description

* Create a new MiniApp in a new directory named after the MiniApp.

The generated MiniApp is a starter "Hello World" app that can be launched as a standalone app on the Android or iOS platforms using our Runner (`ern run-android` and `ern run-ios`).

If you have used React Native previously, you'll notice that the generated project looks similar to the React Native default template app as created by `react-native init`. One of the differences with React Native is that we generate our own native projects which use a locally generated `ern` container.

The `android` and `ios` directories are not created by this command. They will be generated by `ern run-android` and `ern run-ios`.

## Syntax

`ern create-miniapp <appName>`

### Arguments

`<appName>`

* The name to use for the MiniApp. The MiniApp name must follow Electrode Native module name rules.
* We recommend suffixing the name of MiniApp with suffix `-miniapp`

### Options

`--language <TypeScript | JavaScript>`

* **Deprecated:** Use `--template` to use custom templates, for example

  `--template react-native-template-typescript`
* Language to use for this MiniApp (either `TypeScript` or `JavaScript`)
* **Default** `JavaScript`.

`--scope/-s <scope>`

* Specify the npm package scope to use for the MiniApp.
* Add the package scope automatically in the `package.json` of the generated MiniApp.
* **Default** Package will be unscoped.

`--packageManager <npm | yarn>`

* **Deprecated:** Yarn is the default, use --npm to override
* The package manager to be used with this MiniApp (`npm` or `yarn`)
* This will set `ern.packageManager` in the MiniApp `package.json`.
* This setting will only be used for `ern add` and `ern upgrade-miniapp` commands. It won't apply for creating the MiniApp. Electrode Native is internally running `react-native init` command which uses Yarn by default, if available on the machine, when creating an app. React Native does not offer this to be configured as of now. If you wish to use npm, you will have to manually remove `yarn.lock` and `node_modules/` in the MiniApp directory after creation, and run `npm install`.
* **Default** The command will prompt for the package manager to use.

`--packageName/-p <name>`

* Specify the npm package name to use for the MiniApp.
* Add the package name automatically in the `package.json` of the generated MiniApp.
* **Default** The command will prompt for the package name to use.

`--platformVersion/-v <version>`

* Specify a platform version if different from the currently activated version.
* This option is rarely used.
* **Default** Will use the currently activated platform version.

`--skipInstall`

* Skip the installation of dependencies after project creation.
* **Default** The value defaults to false.

`--skipNpmCheck`

* **Deprecated:** Use `npm info` to check manually
* Skip the check ensuring package does not already exists in npm registry.
* **Default** The value defaults to false.

`--manifestId <manifestId>`

* Id of the override Manifest entry to retrieve dependencies versions from (see [override Manifest](/reference/index-2/override) for more info)

`--template <template>`

* The React Native project template to use.
* Internally, Electrode Native will forward this template to 'react-native init' command.
* Electrode Native will perform same post processing as it does on non templated MiniApps, once MiniApp is created (add 'ern' object to the package.json of the MiniApp and remove `android` and `ios` directories).

## Examples

* `ern create-miniapp MyAwesomeApp`

  Creates a MiniApp named `MyAwesomeApp`.
* `ern create-miniapp MyAwesomeApp --scope MyCompany`

  Creates a MiniApp named `MyAwesomeApp` and use `MyCompany` as the scope of the MiniApp npm package.
* `ern create-miniapp MyAwesomeApp --packageName my-awesome-app`

  Creates a MiniApp named `MyAwesomeApp` and use `my-awesome-app` as the name of the MiniApp npm package.

## Remarks

* MiniApp names must be alphanumeric, cannot contain special characters, and cannot start with a digit.
* Package name should be a valid npm package name.
* This command is the `ern` equivalent of the `react-native init` command.


# link

## Description

* Link to a specified MiniApp directory

The `ern link` command is helpful during development of your MiniApps as a way to develop and debug your application. The command is also helpful as a way to use the react-native hot reload feature for your MiniApps when the command is run inside a host application along with other MiniApps.

The `ern link` command was developed to help with developing and debugging MiniApps when running them inside a target native host application. This benefit is realized in the following scenario: When you run multiple MiniApps together in the native application, you cannot use the `react-native start` command from within your MiniApp directory and load the bundle from the local react-native packager as you would normally do when running your MiniApp standalone in the runner.

Using the local packager for your MiniApp makes the native application fail whenever it attempts to load another MiniApp—due to the fact that it doesn't find the other MiniApps in your own MiniApp bundle served through the local packager. And, if running a single MiniApp, the react-native packager does not function well with symbolic links.

In response to this scenario, you can use the `ern link` command to help with developing and debugging MiniApps when running them inside a target native host application.

The `ern link` or the `ern unlink` plus the `ern start` commands are used together to achieve this.

## Syntax

`ern link`

## Caveats

1. If you add a JavaScript dependency to your MiniApp (through `ern add`) or update a JavaScript dependency version, you'll have to relaunch the `ern start` command.

## Remarks

* This command must be executed within a MiniApp working directory.
* Any changes to the code of the MiniApp, inside its working directory, are available in the native host application through a manual react-native reload of the MiniApp or through the live/hot reload feature of react-native.
* After running the `ern link` command, the link to the MiniApp directory remains in effect until you unlink it using the `ern unlink` command.
* The MiniApps link is used when you use the `ern start` command. This command creates a composite bundle with all the MiniApps contained within the native application and starts the react-native packager for this bundle.

## Related commands

[ern start](/cli-commands/start) | Start the Electrode Native platform\
[ern unlink](/cli-commands/unlink) | Remove the link associated to a MiniApp directory


# regen-api

## Description

* Regenerate an existing API located in the current working directory, following a Swagger schema update

## Syntax

`ern regen-api`

**Options**

`--skipVersion/-s`

* Skip the step to update api version and publish to npm.

`--bridgeVersion/-b`

* Specify version of the [Electrode Native Bridge](https://github.com/electrode-io/react-native-electrode-bridge/releases) to use.
* Target `--bridgeVersion` can be found using `yarn info react-native-electrode-bridge versions`

## Remarks

* This command is used for example, if you add new requests, events, or models to the schema and you want to regenerate the existing API based on this schema update and publish a new version of it.
* This command must be executed from within the root directory of an API project that was initially created using the `ern create-api` command.

## Related commands

[ern create-api](/cli-commands/create-api) | Create a new API project based on a Swagger schema\
[ern create-api-impl](/cli-commands/create-api-impl) | Create an implementation skeleton project for a specified API


# regen-api-impl

## Description

* Regenerate an existing API implementation located in the current working directory.

## Syntax

`ern regen-api-impl`

**Options**

`--apiVersion/-v`

* Version of the api for which the implementation needs to be generated. If not passed, the latest available version of the api will be picked up.

`--hasConfig`

* Indicates if this api implementation requires some config during initialization. This command will be stored and reused during container generation to enforce config initialization

`--manifestId <manifestId>`

* Id of the override Manifest entry to retrieve dependencies versions from (see [override Manifest](/reference/index-2/override) for more info)

## Remarks

* This command is used for example, if you add new requests to an api and would like to regenerate the implementation code for the same.
* This command will only regenerate the read-only files inside the implementation project to avoid overriding any local changes made to the request handler implementations.
* Once the command is executed, it may be required to fix any compilation issues in those files before publishing the code a git repo or npm.
* This command must be executed from within the root directory of an API implementation project that was initially created using the `ern create-api-impl` command.


# run-android

### Description

* Runs a MiniApp on an Android emulator or connected device

### Syntax

`ern run-android`

**Options**

`--baseComposite <compositePath>`

* Git or File System path, to the custom Composite repository (refer to the [custom Composite](https://github.com/electrode-io/electrode-native/blob/master/docs/cli/platform-parts/composite/index.md) documentation for more information).

`--descriptor, -d`

* complete native application descriptor

`--dev [true|false]`

* Enable or disable React Native dev support

`--extra/-e`

* Optional extra configuration specific to local container and runner
* Override the Android build config during local container generation and runner project by passing `androidConfig` attributes
  * **As a json string** For example `--extra '{"androidConfig": {"androidGradlePlugin": "3.2.1","rnGradlePlugin": "0.0.6","buildToolsVersion": "28.0.3","compileSdkVersion": "28","gradleDistributionVersion": "4.6","minSdkVersion": "19","sourceCompatibility": "VERSION_1_8","supportLibraryVersion": "28.0.0","targetCompatibility": "VERSION_1_8","targetSdkVersion": "28"}}'` Find more information on [android configuration](https://github.com/electrode-io/electrode-native/blob/master/docs/cli/plaform-parts/container-integration.md)
  * **As a file path** For example `--extra /home/user/my-container-config.json` In that case, the configuration will be read from the file.
  * **As a Cauldron file path** For example `--extra cauldron://config/container/my-container-config.json` In that case, the configuration will be read from the file stored in Cauldron. For this way to work, the file must exist in Cauldron (you can add a file to the cauldron by using the \[ern cauldron add file] command). Find more information on [configuring via cauldron](https://github.com/electrode-io/electrode-native/blob/master/docs/cli/plaform-parts/container-integration.md)

Alternatively, it is also possible to provide this extra configuration in the `package.json` of the MiniApp, inside the `ern` object. For example:

```json
"ern": {
  "androidConfig": {
    "minSdkVersion": "19",
    "compileSdkVersion": "28"
  }
}
```

* Optional hooks to run an arbitary script before or after js bundling is possible.
  * If a script is defined as a `preBundle` hook, it will be executed after the composite generation, prior to running metro bundler, from the directory containing the generated composite project.
    * **As a json string** `--extra '{"containerGenerator": {"hooks": {"preBundle": "/workspace/ern/picking-miniapp/script/pre-script.sh"}}}'`
    * **As a file path** `--extra <path>/container-config.json`
    * **As a Cauldron file path** `--extra cauldron://config/config.json`
  * If a script is defined as a `postBundle` hook, it will be executed just after metro bundler has been run, from the directory containing the bundle.
    * **As a json string** `--extra '{"containerGenerator": {"hooks": {"postBundle": "/workspace/ern/picking-miniapp/script/post-script.sh"}}}'`
    * **As a file path** `--extra <path>/container-config.json`
    * **As a Cauldron file path** `--extra cauldron://config/config.json`

Program to use to run the script should be indicated using [shebang pattern](https://en.wikipedia.org/wiki/Shebang_\(Unix\)) in the script itself as first line.

`--host`

* Host or ip to launch the local packager on *(default: localhost)*

`--launchFlags <string>`

* Extra options passed to `am start` command when launching the application (correspond to the `Launch Flags` in Run/Debug Configurations of application in Android Studio, as can be seen on screenshot below)
* Make sure to use `=` on the command line to provide this option, and keep the string in quotes. For example `--launchFlags="--es aKey aStringValue --ei anotherKey 1"`

![Android Studio Run Config](/files/-LqnImInlEjOrl_iLAY9)

`--mainMiniAppName`

* Name of the MiniApp to launch when starting the Runner application
* If you are running the command from the `MainApp` directory, only specify name of the `MiniApp` (Not the path).

`--miniapps/m`

* One or more MiniApps to combine in the Runner Container

`--port`

* Port on which the local packager should listen on *(default: 8081)*

`--usePreviousDevice/-u`

* Use the previously selected device to avoid prompt

### JavaScript engine

By default Electrode Native will run the MiniApp with a Container that uses JavaScriptCore engine. If you'd rather like to run the MiniApp with [Hermes](https://hermesengine.dev) engine, you should add the following inside the `ern` object of the MiniApp package.json :

```json
{
  "androidConfig": {
    "jsEngine": "hermes"
  }
}
```

### Remarks

* You can launch the MiniApp located in the current working directory or on a connected Android device or running emulator if available. If a connected Android device is not available, the command prompts you to select an emulator to launch from the list of installed emulator images.
* The first time you run this command from within a MiniApp directory, it generates an Android directory containing the Android runner application project. If the Android folder already exists (it is not the first run of the `ern run-android` command for this MiniApp), the existing runner project is used.
* After the runner project is generated, you can safely make native code modifications to it, knowing that the next time the `ern run-android` command is issued, the project and your changes will remain.
* If you want to regenerate the runner project from scratch, remove the Android directory.
* The miniapp can be any Yarn package descriptor, including Git or other file system path schemes.
* The `ern run-android` command is the `ern` equivalent of the `react-native run-android` command.
* If you are running the command from the `MainApp` directory, only specify name of the `MiniApp` (Not the path) in the `--mainMiniAppName` option.


# run-ios

## Description

* Runs a MiniApp on an iOS simulator or connected device

## Syntax

`ern run-ios`

**Options**

`--baseComposite <compositePath>`

* Git or File System path, to the custom Composite repository (refer to the [custom Composite](https://github.com/electrode-io/electrode-native/tree/1fe3ccf5f3c3a92529b7d46968b8433c9b89a639/docs/cli/platform-parts/composite/index.md) documentation for more information).

`--descriptor, -d`

* complete native application descriptor

`--dev [true|false]`

`--extra/-e`

* Optional extra configuration specific to local container and runner
* Override iOS configuration during local container generation and runner project by passing `iosConfig` attributes
  * **As a json string**

    For example `--extra '{"iosConfig": {"deploymentTarget": "11.0"}}'`

    Find more information on [iOS configuration](https://github.com/electrode-io/electrode-native/tree/1fe3ccf5f3c3a92529b7d46968b8433c9b89a639/docs/cli/plaform-parts/container-integration.md)
  * **As a file path**

    For example `--extra /home/user/my-container-config.json`

    In that case, the configuration will be read from the file.
  * **As a Cauldron file path**

    For example `--extra cauldron://config/container/my-container-config.json`

    In that case, the configuration will be read from the file stored in Cauldron.

    For this way to work, the file must exist in Cauldron (you can add a file to the cauldron by using the \[ern cauldron add file] command).

    Find more information on [configuring via cauldron](https://github.com/electrode-io/electrode-native/tree/1fe3ccf5f3c3a92529b7d46968b8433c9b89a639/docs/cli/plaform-parts/container-integration.md)

Alternatively, it is also possible to provide this extra configuration in the `package.json` of the MiniApp, inside the `ern` object. For example:

```javascript
"ern": {
  "iosConfig": {
    "deploymentTarget": "11.0"
  }
}
```

* Optional hooks to run an arbitary script before or after js bundling is possible.&#x20;
  * If a script is defined as a `preBundle` hook, it will be executed after the composite generation, prior to running metro bundler, from the directory containing the generated composite project.&#x20;
    * **As a json string**

      `--extra '{"containerGenerator": {"hooks": {"preBundle": "/workspace/ern/picking-miniapp/script/pre-script.sh"}}}'`
    * **As a file path**

      `--extra <path>/container-config.json`
    * **As a Cauldron file path**

      `--extra cauldron://config/config.json`
  * If a script is defined as a `postBundle` hook, it will be executed just after metro bundler has been run, from the directory containing the bundle.
    * **As a json string**

      `--extra '{"containerGenerator": {"hooks": {"postBundle": "/workspace/ern/picking-miniapp/script/post-script.sh"}}}'`
    * **As a file path**

      `--extra <path>/container-config.json`
    * **As a Cauldron file path**

      `--extra cauldron://config/config.json`

Program to use to run the script should be indicated using [shebang pattern](https://en.wikipedia.org/wiki/Shebang_) in the script itself as first line.

* Enable or disable React Native dev support

`--host`

* Host or ip to launch the local packager on.
* By default it will use the IP address that is returned by the `ipconfig getifaddr en0` command, and fallback to `localhost` in the case the command fails.

`--launchArgs`

* Arguments to pass to the application when launching it (correspond to the `Arguments Passed On Launch` in application scheme run config in Xcode as can be seen on screenshot below).
* Make sure to use `=` on the command line to provide this option, and keep the string in quotes. For example `--launchArgs="-ArgA -ArgB"`

`--launchEnvVars`

* Environment variables to pass to the application when launching it (correspond to the `Environment Variables` in application scheme run config in Xcode as can be seen on screenshot below).
* Make sure to use `=` on the command line to provide this option, and keep the string in quotes. The string should contain `key=value` pairs delimited by spaces. For example `--launchEnvVars="aKey=aValue anotherKey=anotherValue"`

![xcode scheme run](/files/-LqnImIp5JVofvzLQKC5)

`--mainMiniAppName`

* Name of the MiniApp to launch when starting the Runner application

`--miniapps/m`

* One or more MiniApps to combine in the Runner Container

`--port`

* Port on which the local packager should listen on *(default: 8081)*

`--usePreviousDevice/-u`

* Use the previously selected device to avoid prompt

## Remarks

* You can launch the MiniApp located in the current working directory or on a connected iOS device or running emulator if available. If a connected iOS device is not available, the command prompts you to select an emulator to launch from the list of installed emulator images.
* The first time you run this command from within a MiniApp directory, it generates an iOS directory containing the iOS Runner application project. If the iOS folder already exists (it is not the first run of the `ern run-ios` command for this MiniApp), the existing runner project is used.
* After the runner project is generated, you can safely make native code modifications to it, knowing that the next time the `ern run-ios` command is issued, the project and your changes will remain.
* If you want to regenerate the runner project from scratch, remove the iOS directory.
* The miniapp can be any Yarn package descriptor, including Git or other file system path schemes.
* The `ern run-ios` command is the `ern` equivalent of the `react-native run-ios` command.


# start

## Description

* Create a composite bundle out of multiple MiniApps and start the react-native local packager to serve this bundle so that it can be loaded within the native host application

## Syntax

`ern start`

**Note**

If you do not pass an argument to this command, you are prompted to select a native application version from the Cauldron. The command uses whatever MiniApp versions are currently declared in this native application version container to launch the command.

**Options**

`--baseComposite <compositePath>`

* Git or File System path, to the custom Composite repository (refer to the [custom Composite](https://github.com/electrode-io/electrode-native/tree/c6be4730926296bbcab7b0dce58f618c5c57e03b/docs/cli/platform-parts/composite/index.md) documentation for more information).

`--compositeDir <compositeDir>`

* Directory in which to generate the composite
* The directory should either not exist (will be created) or be empty
* By default the composite will be generated in a temporary directory

`--descriptor/-d <descriptor>`

* Target a specific native application version, associated to the provided *complete native application descriptor*.
* This option uses whatever MiniApp versions are currently declared in this native application version container to launch the command.

`--miniapps/-m <miniapps>`

* Specify one or more MiniApps to launch this command
* The command packages all the provided MiniApps in a composite bundle and starts the react-native packager.
* You can use any valid Yarn package descriptor for the MiniApps provided to this command, including Git and other file system path schemes.

`--jsApiImpls`

* Specify one or more JS API Implementations to include

`--watchNodeModules/-w <nodemodules>`

* A list of one or more directory name(s) from node\_modules that should be watched for changes.

`--extraJsDependencies/-e <jsdependencies>`

* Additional JavaScript dependencies to add to the composite JavaScript bundle.

`--host`

* Host or ip to launch the local packager on *(default: localhost)*

`--port`

* Port on which the local packager should listen on *(default: 8081)*

`--resetCache`\\

* Indicates whether to reset the React Native cache prior to bundling

**Platform Specific Options**

`Android`

`--activityName/-a <activity name>`

* Specify Android Activity to launch.

`--launchFlags <string>`

* Extra options passed to `am start` command when launching the application (correspond to the `Launch Flags` in Run/Debug Configurations of application in Android Studio, as can be seen on screenshot below)
* Make sure to use `=` on the command line to provide this option, and keep the string in quotes. For example `--launchFlags="--es aKey aStringValue --ei anotherKey 1"`

![Android Studio Run Config](/files/-LqnImInlEjOrl_iLAY9)

`--packageName/-p <packagename>`

* Android application package name to avoid conflict with the names of classes or interfaces.

`iOS`

`--bundleId/-b`

* iOS Bundle Identifier unique to your app.

`--launchArgs`

* Arguments to pass to the application when launching it (correspond to the `Arguments Passed On Launch` in application scheme run config in Xcode as can be seen on screenshot below).
* Make sure to use `=` on the command line to provide this option, and keep the string in quotes. For example `--launchArgs="-ArgA -ArgB"`

`--launchEnvVars`

* Environment variables to pass to the application when launching it (correspond to the `Environment Variables` in application scheme run config in Xcode as can be seen on screenshot below).
* Make sure to use `=` on the command line to provide this option, and keep the string in quotes. The string should contain `key=value` pairs delimited by spaces. For example `--launchEnvVars="aKey=aValue anotherKey=anotherValue"`
* **Default** false

![xcode scheme run](/files/-LqnImIp5JVofvzLQKC5)

**Binary Store Specific Options**

`--disableBinaryStore`

* Setting this option will bypass retrieval and installation of the binary from the Binary Store.
* It can be useful in case you want to use `ern start` command in conjunction with your own mobile application native binary, build locally on your workstation or retrieved from a specific location.

`--flavor`

* Flavor of the binary to retrieve from the store.
* The binary of a specific application version (for ex `1.0.0`) can have different flavors, representing different build types of the same application version (for example `Dev`/`Prod`/`QA` ...).

## Remarks

* This command can be used to package multiple MiniApps inside a single composite bundle and automatically start the react-native local packager to serve this bundle.
* Use this command when you need to launch and develop or debug your MiniApps from within a native host application which contains other MiniApps along with your MiniApp.
* This command works with the `ern link` command. For additional information, see the documentation for the `ern link` command.
* When using a binary store, file watcher will be started after the binary is retrieved and installed on the simulator/device. If you are using a binary store and don't want to launch binary from the store, please make sure to use the `--disableBinaryStore` option. Otherwise, file watcher will not be started.

## Related commands

[ern link](/cli-commands/link) | Link to a MiniApp directory


# unlink

## Description

* Remove the link associated to a MiniApp directory

## Syntax

`ern unlink`

## Remarks

* You must run this command from within a MiniApp working directory that was linked using the `ern link` command.
* When you remove the link associated to a MiniApp directory, the package launched using the `ern start` command, won't use this MiniApp directory any longer to load the code of the MiniApp.

## Related commands

[ern link](/cli-commands/link) | Link to a MiniApp directory


# upgrade-miniapp

## Description

* Upgrades a MiniApp to the currently activated platform version

## Syntax

`ern upgrade-miniapp`

**Options**

`--version/-v <version>`

* Upgrade the MiniApp to a specific platform version

`--manifestId <manifestId>`

* Id of the override Manifest entry to retrieve dependencies versions from (see [override Manifest](/reference/index-2/override) for more info)

## Remarks

* Based on your preference, you can select which package manager (`npm` or `yarn`) to be used by this command when updating the packages versions. This can be done by adding or updating `packageManager` field in the `ern` object kept in the MiniApp package.json. For example, to use `npm`. If this field is missing from configuration, `yarn` will be used over `npm` if it is installed on the workstation.

```javascript
{
  "ern": {
    "packageManager": "npm"
  }
}
```


# cauldron add


# file

## Description

* Add a file to the Cauldron

## Syntax

`ern cauldron add file <localFilePath> <cauldronFilePath>`

**Arguments**

`<localFilePath>`

* Absolute path to a file to add to the Cauldron

`<cauldronFilePath>`

* Target file path in the Cauldron
* Relative to the root of the Cauldron repository
* Cannot start with `/`
* Should include target file name (can be same as source filename or different)
* Can contain nested directories
* All directories will be created in the Cauldron if necessary.

## Examples

* `ern cauldron add file /etc/example.json data/example.json`\
  Add the file `example.json` from local directory `/etc` to the `data` directory of the Cauldron.
* `ern cauldron add file /etc/example.json data/new.json`\
  Add the file `example.json` from local directory `/etc` to the `data` directory of the Cauldron. Rename the file to `new.json` in the Cauldron.

## Related commands

[ern cauldron update file](/cli-commands/cauldron-update/file) | Update a file in the Cauldron\
[ern cauldron del file](/cli-commands/cauldron-del/file) | Remove a file from the Cauldron


# jsapiimpls

## Description

* Add one or more JS API implementation to a non-released native application version in a Cauldron
* Generate and publish a new Container version

## Syntax

`ern cauldron add jsapiimpls <jsapiimpls..>`

**Arguments**

`<jsapiimpls..>`

* One or more package path to JS API implementation(s) (delimited by spaces) to add to a target native application version in the Cauldron.
* The following types of JS API Implementation paths are not supported by this command :
  * File path (ex `file://etc/js-api-impl`)
  * Git path missing branch/tag or commit sha (ex: `https://github.com/username/js-api-impl.git`)
  * Registry path missing version (ex: `js-api-impl`)
  * Registry path using a version range (ex: `js-api-impl@^1.0.0`)

**Example**

`ern cauldron add jsapiimpls first-js-api-impl@1.0.0 second-js-api-impl@2.0.0`

**Options**

`--containerVersion/-v <version>`

* Specify a version for the new container
* **Default** Incremental patch number of the current container version &#x20;

  Example: If the current container version is 1.2.3 and a version is not included in the command, the new container version will be 1.2.4.

`--descriptor/-d <descriptor>`

* Add the JS API implementation(s) to a given target native application version in the Cauldron matching the provided native application descriptor.
* You can only pass a complete native application descriptor as the JS API implementation(s) added through this command targets only a specific single native application version. &#x20;

  **Default** Lists all non-released native application versions from the Cauldron and prompts you to choose one to add to the JS API implementation. &#x20;

  **Example** `ern cauldron add jsapiimpls <jsapiimpls..> -d MyNativeApp:android:1.0.0`

`--resetCache`\\

* Indicates whether to reset the React Native cache prior to bundling
* **Default** false

## Related commands

[ern cauldron update jsappiimpls](https://github.com/electrode-io/electrode-native/tree/c6be4730926296bbcab7b0dce58f618c5c57e03b/docs/cli/cauldron/update/jsappiimpls.md) | Updates the version of an existing JS API implementation


# miniapps

## Description

* Add one or more MiniApps to a non-released native application version in a Cauldron
* Perform multiple checks, including MiniApp dependencies analysis, to ensure compatibility with the target native application container
* Generate and publish a new Container version

## Syntax

`ern cauldron add miniapps <miniapps..>`

**Arguments**

`<miniapps..>`

* One or more package path to MiniApps (delimited by spaces) to add to a target native application version in the Cauldron.
* Any MiniApp path (but file path) will be added to the Container in the Cauldron, as such, with the exception of a git path including a branch. In that case, the MiniApp path that will be added to the Container in the Cauldron will contain the commit SHA of the HEAD of the branch, rather than the branch itself.
* The following types of MiniApp paths are not supported by this command :
  * File path (ex `file://etc/example-miniapp`)
  * Git path missing branch/tag or commit sha (ex: `https://github.com/username/example-miniapp.git`)
  * Registry path missing version (ex: `example-miniapp`)
  * Registry path using a version range (ex: `example-miniapp@^1.0.0`)

**Example**

`ern cauldron add miniapps first-miniapp@1.0.0 second-miniapp@2.0.0`

**Options**

`--containerVersion/-v <version>`

* Specify a version for the new container
* **Default** Increment the patch digit of the current container version

`--descriptor/-d <descriptor>`

* Add the MiniApp to a given target native application version in the Cauldron matching the provided native application descriptor.
* You can only pass a complete native application descriptor as the MiniApp added through this command targets only a specific single native application version. &#x20;

  **Default** Lists all non-released native application versions from the Cauldron and prompts you to choose one to add to the MiniApp. &#x20;

  **Example** `ern cauldron add miniapps <miniapps..> -d MyNativeApp:android:1.0.0`

`--force/-f`

* Bypass compatibility checks and force-add the MiniApp to the Cauldron. &#x20;

  **Caution** Before using the `--force/-f` option, be sure that you can bypass compatibility checks.

`--resetCache`\\

* Indicates whether to reset the React Native cache prior to bundling
* **Default** false

## Remarks

* If one MiniApp does not pass compatibility checks, the MiniApp is not added to the Cauldron and a new container version is not generated.

## Related commands

[ern cauldron update miniapps](/cli-commands/cauldron-update/miniapps) | Updates the version of an existing MiniApp


# nativeapp

## Description

* Add a new native application version to the currently activated Cauldron

## Syntax

`ern cauldron add nativeapp <descriptor>`

**Arguments**

`<descriptor>`

* A complete native application descriptor representing the native application version to be added to the Cauldron.

**Example**

`ern cauldron add nativeapp MyNativeApp:ios:17.14.0`

**Options**

`--platformVersion/-v`

* Use specified platform version

`--copyFromVersion/-c <version>`

* Copy the data of a native application version stored in the Cauldron.
* Possible values for this option are :
  * A specific version, for example `1.2.3`
  * `latest` if you want to copy the data from the latest version of the native application
  * `none` if you don't want any copy from action
* The `--copyFromVersion/-c <version>` option also copies the list of native dependencies and MiniApps as well as the container version to the new native application version.
* If you use the `--copyFromVersion/-c <version>` option, you do not need to add all MiniApps again after creating a new native application version in the Cauldron.
* This option is commonly used.

`--description`

* Description of the native application version

`--config`

* Configuration to set for this new native application version
* If not provided, the configuration of the version copied from will be used (if any).
* There is three different ways to provide the configuration :
  * **As a json string** &#x20;

    For example `--config '{"configKey": "configValue"}'`
  * **As a file path** &#x20;

    For example `--config /etc/config.json` &#x20;

    In that case, the configuration will be read from the file
  * **As a Cauldron file path** &#x20;

    For example `--extra cauldron://config/myapp-android.json` &#x20;

    In that case, the configuration will be read from the file stored in Cauldron. &#x20;

    For this way to work, the file must exist in Cauldron (you can add a file to the cauldron by using the \[ern cauldron add file] command).

## Remarks

* The `ern cauldron add nativeapp <descriptor>` command is usually used when the development of a new version of the native application is started.
* The new native application version is identified by the *complete native application description* in the Cauldron.

## Related commands

[ern cauldron update nativeapp](/cli-commands/cauldron-update/nativeapp) | Add a new native application version to the currently activated Cauldron


# cauldron config


# get

## Description

Echoes configuration stored in Cauldron.

## Syntax

`ern cauldron config get`

**Options**

`--key`

* The configuration key for which to retrieve value
* **Default** Will return the whole configuration object

`--descriptor`

* The target descriptor which to retrieve configuration from &#x20;

  **Default** Returns the top level / global configuration, not associated to a specific descriptor

`--json`

* Output config as a single line JSON record.

`--strict`

* Echoes the configuration strictly associated to the descriptor &#x20;

  **Default** false. If no configuration is found for the specific descriptor, the closest applied configuration will be returned. For example, if a native application version descriptor is provided but no configuration is stored at this level, the command will look for a configuration -until it finds one- in the platform level, then native application and finally top level / global cauldron config.

## Related commands

[ern cauldron config set](https://github.com/electrode-io/electrode-native/tree/c6be4730926296bbcab7b0dce58f618c5c57e03b/docs/cli/cauldron/config/set.md) | Sets configuration stored in Cauldron.\
[ern cauldron config del](https://github.com/electrode-io/electrode-native/tree/c6be4730926296bbcab7b0dce58f618c5c57e03b/docs/cli/cauldron/config/del.md) | Deletes configuration stored in Cauldron.


# cauldron del


# file

## Description

* Remove a file from the Cauldron

## Syntax

`ern cauldron del file <cauldronFilePath>`

**Arguments**

`<cauldronFilePath>`

* Target file path in the Cauldron, of the file to remove
* Relative to the root of the Cauldron repository
* Should include target file name (can be same as source filename or different)
* The file referenced by the path should exist in the Cauldron

## Examples

* `ern cauldron del file data/example.json` &#x20;

  Remove the file `example.json` from directory `data` of the Cauldron

## Related commands

[ern cauldron add file](/cli-commands/cauldron-add/file) | Add a file in the Cauldron\
[ern cauldron update file](/cli-commands/cauldron-update/file) | Update a file in the Cauldron


# jsapiimpls

## Description

* Remove one or more JS API implementation(s) from a given non-released native application version in a Cauldron
* Generate and publish a new Container version—so that the native applications can use the new Container version to access the new JS API implementation(s) that was/were added &#x20;

  **Note** The `ern cauldron del jsapiimpls <jsapiimpls..>` command can remove (from the native application version container) all native dependencies that are only used by the removed MiniApps. The `ern cauldron del jsapiimpls <jsapiimpls..>` command does not do native dependency cleanup.

## Syntax

`ern cauldron del jsapiimpls <jsapiimpls..>`

**Arguments**

`<jsapiimpls..>`

* One or more package path to JS API implementation(s) (delimited by spaces) to remove from a native application version in the Cauldron.

**Options**

`--containerVersion/-v <version>`

* Specify a version for the new container
* **Default** Incremental patch number of the current container version &#x20;

  Example: If the current container version is 1.2.3 and a version is not included in the command, the new container version will be 1.2.4.

`--descriptor/-d <descriptor>`

* Remove the JS API implementation(s) from a given target native application version in the Cauldron matching the provided native application descriptor
* You can only pass a complete native application descriptor as the native dependencies removed using this command target only a specific single native application version. &#x20;

  **Default** Lists all non-released native application versions from the Cauldron and prompts you to choose one.

`--resetCache`\\

* Indicates whether to reset the React Native cache prior to bundling
* **Default** false

## Remarks

* You don't need to provide a version for the JS API implementation(s) when using the `ern cauldron del jsapiimpls <jsapiimpls..>` command. The version is ignored because only one version of a given JS API implementation can be present in a container at any given time.


# miniapps

## Description

* Remove one or more MiniApps from a given non-released native application version in a Cauldron
* Generate and publish a new Container version—so that the native applications can use the new Container version to access the new MiniApp that was added &#x20;

  **Note** The `ern cauldron del miniapps <miniapps..>` command can remove (from the native application version container) all native dependencies that are only used by the removed MiniApps. The `ern cauldron del miniapps <miniapps..>` command does not do native dependency cleanup.

## Syntax

`ern cauldron del miniapps <miniapps..>`

**Arguments**

`<miniapps..>`

* One or more package path to MiniApp(s) (delimited by spaces) to remove from a native application version in the Cauldron.

**Options**

`--containerVersion/-v <version>`

* Specify a version for the new container
* **Default** Incremental patch number of the current container version &#x20;

  Example: If the current container version is 1.2.3 and a version is not included in the command, the new container version will be 1.2.4.

`--descriptor/-d <descriptor>`

* Remove the MiniApps from a given target native application version in the Cauldron matching the provided native application descriptor
* You can only pass a complete native application descriptor as the native dependencies removed using this command target only a specific single native application version. &#x20;

  **Default** Lists all non-released native application versions from the Cauldron and prompts you to choose one to remove from the MiniApps

`--resetCache`\\

* Indicates whether to reset the React Native cache prior to bundling
* **Default** false

## Remarks

* You don't need to run the `ern cauldron del miniapps <miniapps..>` command from within a MiniApp working directory.
* You don't need to provide a version for the MiniApp when using the `ern cauldron del miniapps <miniapps..>` command. The version is ignored because only one version of a given MiniApp can be present in a container at any given time.

## Related commands

[ern cauldron del dependencies](https://github.com/electrode-io/electrode-native/tree/c6be4730926296bbcab7b0dce58f618c5c57e03b/docs/cli/cauldron/del/dependencies.md) | Manually cleanup native dependencies that are only used by the specified MiniApp


# nativeapp

## Description

* Remove a native application entry from a Cauldron

## Syntax

`ern cauldron del nativeapp <descriptor>`

**Arguments**

`<descriptor>`

* A partial native application descriptor or a complete native application descriptor representing the native application entry to be removed from the Cauldron.

**Example**

`ern cauldron del nativeapp TestApp`\
Remove the native application named `TestApp` from the cauldron.\
This includes removing all platforms and versions of this native application from the Cauldron.

`ern cauldron del nativeapp TestApp:android`\
Remove the android platform entry of `TestApp` from the Cauldron.\
This includes removing all versions entries in Cauldron of `TestApp` for `android` platform, but will other platform versions untouched.

`ern cauldron del nativeapp TestApp:android:1.0.0`\
Remove version `1.0.0` of the `TestApp` `android` from the Cauldron.\
All other versions of `TestApp` `android` will remain untouched.

## Remarks

* The `ern cauldron del nativeapp <descriptor>` command is rarely used for Cauldrons in production environments.


# cauldron get


# config


# dependency

## Description

* Retrieve the native dependencies present in a native application version container
* Log the native dependencies in your terminal

## Syntax

`ern cauldron get dependency <descriptor>`

**Options**

`--json`

* Output dependencies as a single line JSON array.

**Arguments**

`<descriptor>`

* A complete native application descriptor representing the native application version for which to list the native dependencies.


# nativeapp

## Description

* Retrieve the data stored in the Cauldron for a given native application object
* Log the data as a JSON formatted string in your terminal

## Syntax

`ern cauldron get nativeapp [descriptor]`

**Options**

`--descriptor`

* A partial or complete application descriptor representing which native application object to get
* If not provided, the command will log the list of all complete native application descriptors stored in the Cauldron

`--json`

* Output result as a single line JSON record.

**Examples** e

* `ern cauldron get nativeapp`

Will log all the complete native application descriptors from the Cauldron. For example, here is a possible output :

```
walmart:android:17.7.0
walmart:android:17.8.0
walmart:ios:17.7.0
walmart:ios:17.8.0
testapp:android:1.0.0
```

* `ern cauldron get nativeapp walmart`

Will log the JSON document associated to the walmart application.

* `ern cauldron get nativeapp walmart:android`

Will log the JSON document associated to the walmart android application.

* `ern cauldron get nativeapp walmart:android:17.7.0`

Will log the JSON document associated to version 17.7.0 of the walmart android application.


# cauldron repo


# add

## Description

* Add a Cauldron repository to the local collection of Cauldron repositories

## Syntax

`ern cauldron repo add <alias> <url>`

**Arguments**

`<alias>`

* Alias to associate to the cauldron repository.

`<url>`

* Local or remote url to the Cauldron git repository to add.
* A remote url can be the HTTPS or SSH url to the Cauldron git repository (SSH recommended).
* A local url can be any valid path to a local directory (empty directory or containing a git repository).
* For HTTPS urls, the username and password (or token) must be specified in the URL (valid formats are `https://[username]:[password]@[repourl` or `https://[token]@[repourl]`).
* By default, the `master` branch of the repository will be used. If you need to use a different branch, you can set the branch name you want to use, by appending it at the end of the url using the `#[branch-name]` format (second example below illustrate this).

**Options**

* `--current true|false`
  * Set the repository as the active repository after adding it to the collection of repositories.
  * If this option is not provided, you are prompted to choose if you want to set the repository as the active repository.
* `--force/-f true|false`

  Overwrite an existing alias with the same name

**Example**

`ern cauldron repo add my-cauldron git@github.com:username/my-cauldron.git`\
Add a new Cauldron repository, with alias `my-cauldron`, and url `git@github.com:username/my-cauldron.git`, to the local collection of Cauldron repositories. The branch that will be used for this Cauldron will be `master` as no branch was explicitly specified.

`ern cauldron repo add my-local-cauldron ~/path/to/local/cauldron`\
Add a new Cauldron repository with alias `my-local-cauldron` and url pointing to local directory `~/path/to/local/cauldron` to the location collection of Cauldron repositories.

`ern cauldron repo add my-other-cauldron git@github.com:username/other-cauldron#development --current`\
Add a new Cauldron repository, with alias `my-other-cauldron`, and url `git@github.com:username/other-cauldron`, to the local collection of Cauldron repositories and set it at the current activated Cauldron. The branch that will be used for this Cauldron will be `development` as it was explicitly specified in the Cauldron url.

`ern cauldron repo add -f my-local-cauldron ~/path/to/local/cauldron` Adds the `my-local-cauldron` alias, and overwrites it if it already exists.

## Remarks

* If the `alias` already exists, this command will fail, unless `--force/-f` is used.


# clear

## Description

* Go back to a state with no Cauldron activated

## Syntax

`ern cauldron repo clear`

## Remarks

This command allows to reset platform not to use any Cauldron. If you need to switch back to a Cauldron, you can use `ern cauldron use` command.


# current

## Description

* Display the alias and the repository URL of the active Cauldron

## Syntax

`ern cauldron repo current`


# list

## Description

* Lists all Cauldron repositories present in the local collection of repositories

## Syntax

`ern cauldron repo list`

## Remarks

* The `ern cauldron repo list` command lists all Cauldron repositories, including the url and alias name, that have been added using the `ern cauldron repo add` command.


# remove

## Description

* Remove an existing Cauldron repository, identified by its `alias`, from a local collection of Cauldron repositories

## Syntax

`ern cauldron repo remove <alias>`

**Arguments**

`<alias>`

* Alias of the Cauldron repository to remove from the local repository collection.

## Remarks

* This command will fail if the `alias` does not exist in the local collection of Cauldron repositories.


# use

## Description

* Set the Cauldron repository associated to the given alias as the active Cauldron

## Syntax

`ern cauldron repo use <alias>`

**Arguments**

`<alias>`

* Alias of the Cauldron repository to activate.

## Remarks

* This command will fail if the `alias` does not exist in the local collection of Cauldron repositories.


# cauldron update


# file

## Description

* Update an existing file in the Cauldron

## Syntax

`ern cauldron update file <localFilePath> <cauldronFilePath>`

**Arguments**

`<localFilePath>`

* Absolute path to a file to overwrite Cauldron target file with

`<cauldronFilePath>`

* Target file path in the Cauldron, of the file to update (overwrite)
* Relative to the root of the Cauldron repository
* Should include target file name (can be same as source filename or different)
* Source file name can be different
* The file referenced by the path should exist in the Cauldron

## Examples

* `ern cauldron update file /etc/example.json data/example.json` &#x20;

  Overwrite file `example.json` in the Cauldron directory `data`, with the file `example.json` located in local path `/etc`

## Related commands

[ern cauldron add file](/cli-commands/cauldron-add/file) | Add a file to the Cauldron\
[ern cauldron del file](/cli-commands/cauldron-del/file) | Remove a file from the Cauldron




---

[Next Page](/llms-full.txt/1)

