# Quick Start

## Referral Campaign App

In this example, we will try to build an API server for a new referral campaign where:

1. unregistered users will sign up with or without a referral code
2. newly signed up users will have an unique referral code to invite other users
3. if a user's referral code is used when signing up, that user gets a point.

## Prerequisites

To complete the following guide, you will need

1. Node version 8 or newer (to install Node, please go to <https://nodejs.org/en/download/>)
2. MongoDB version 3 or newer (to install MongoDB locally, please go to <https://docs.mongodb.com/manual/installation/#tutorials>)

## 1. Setup your first project

You are going to create a new folder and create a Node application within it.

```bash
$ mkdir referral_journey
$ cd referral_journey
$ npm init --yes
```

![screenshot: initializing your app](https://3515816241-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LOkfsLjd-KkAAHYh7IT%2F-LP6NaRTKcwoW7MxhgPZ%2F-LP6Ou3zuL77CuBQgC5H%2Fimage.png?alt=media\&token=452c854b-f790-40d4-aa45-827a3cd9e59f)

After running these commands, you will find a `package.json` file in your newly created `referral_journey` directory. So far so good!

## 2. Install `jerni` and `jerni-dev`

You need to install `jerni` and `jerni-dev` package from [npm](https://npm.im/jerni-dev) with the following command:

```bash
$ npm i jerni
$ npm i -D jerni-dev
```

For yarn users:

```bash
$ yarn add jerni
$ yarn add -D jerni-dev
```

> `jerni-dev` is a toolkit to improve developers' productivity and experience when developing a `jerni` app. It should never be used in production server.
>
> With `jerni-dev` developers don't have to worry about setting up and maintaining an events queue service. It also enables development only features like hot-reloading your event handlers and time-traveling your events history. Read more about `jerni-dev` at <https://github.com/tungv/jerni/blob/master/packages/jerni-dev/readme.md>

Then open `package.json` file for edit. You need to add a `subscribe-dev` script to `scripts` path.

```javascript
"scripts": {
  "subscribe-dev": "jerni-dev index.js"
}
```

![screenshot: package.json file with subscribe-dev scripts](https://3515816241-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LOkfsLjd-KkAAHYh7IT%2F-LP6RuFNYzMaXuMg5uDL%2F-LP6VPKQyvVCP7HbOQW3%2Fimage.png?alt=media\&token=64ea4670-d8a9-4c19-a22d-ca7f0dbf5c82)

## 3. Define Event Handlers

In this step, we're going to tell `jerni` what it should do when an event arrives. Base on the requirements, we need to react to event `"USER_REGISTERED"`. And the reaction is to insert a new document to mongodb describing the new user.

> in `jerni` an event describes something happened in the past. Events always have a unique and incremental `id`, a `type` and an optional `payload`. It's designed very similarly to a [Flux Standard Action](https://github.com/redux-utilities/flux-standard-action)
>
> Since it's about something that happened, the type should be in a past participle form, eg. `USER_REGISTERED` or `USER_DEACTIVATED`. Note that ALL\_CAPS convention is not a requirement but more a personal reference.

To be able to work with mongodb in the opinionated way of `jerni` we need to install `@jerni/store-mongo` using [npm](https://www.npmjs.com/package/@jerni/store-mongo):

```bash
$ npm i @jerni/store-mongo
```

Create a JavaScript file at `models/users.js` from the current working directory with the following content:

{% code title="models/users.js" %}

```javascript
const { Model } = require("@jerni/store-mongo");
const mapEvents = require("jerni/lib/mapEvents");

module.exports = new Model({
  name: "users",
  version: "1",
  transform: mapEvents({
    USER_REGISTERED: event => ({
      insertOne: {
        id: event.payload.user_id,
        name: event.payload.user_name,
        password: event.payload.hashed_password,
        referred_users: [],
        referral_point: 0
      }
    })
  })
});
```

{% endcode %}

Model is where you handle your events as they arrive. `transform` property accepts a pure function to transform an event into one or many mongodb operations such as `insertOne`/`insertMany` , `updateOne`/`updateMany` , `deleteOne`/`deleteMany`, for more details please read <https://github.com/tungv/jerni/tree/master/packages/store-mongo>

> `mapEvents` is a utility function to make it more readable. It's entirely optional but recommended.

## 4. Connect the journey

We are going to use `createJourney` function from `jerni` package to complete a journey. Please create `index.js` file from the current working directory with the following content:

{% code title="index.js" %}

```javascript
const createJourney = require("jerni");
const { Store } = require("@jerni/store-mongo");
const createJourney = require("jerni");

const { EVENT_STORE_URL } = process.env;

const mongoStore = new Store({
  name: "referral-app",
  url: "mongodb://localhost:27017",
  dbName: "referral-app",
  models: [require("./models/users")]
});

module.exports = createJourney({
  writeTo: EVENT_STORE_URL,
  stores: [mongoStore]
});
```

{% endcode %}

This code will create a journey by connecting an events queue service to your mongodb store. You can have more than one stores but only one events queue is allowed.

## 5. Start sending events
