# Kazana Manifest

The kazana manifest is the entry point used by kazana server to load and configure a Kazana application or plugin. The filename is expected to be `index.js` in the root of the application by default, but it can be configured using [the package main field](https://docs.npmjs.com/files/package.json#main).

It must export an object with the following options

## name _(required)_

Name of the app / plugin

## version

[SemVer](http://semver.org/) compatible version. Defaults to the `"version"` field from `package.json`.

## port

Port number for app, defaults to `5000`.

## config

Default configuration for app or plugin. See [config](config.md) for more information.

## public

Path to folder from where to serve public assets at the root path.

```js
{
  public: 'public'
}
```

For universal apps with server-side rendering, the [routes](#routes) option
can be used with a [multi segment parameter](http://hapijs.com/tutorials/routing#multi-segment-parameters).

## routes

Array of [hapi routes](http://hapijs.com/tutorials/routing):

```js
{
  routes: [
    {
      method: 'GET',
      path: '/my/custom/path',
      handler: function (request, reply) {
        reply('Hello from /my/custom/path')
      }
    }
  ]
}
```

## bootstrap

Either a function with a callback, or a path to a folder.
See [bootstrap API](bootstrap.md) for more information.

```js
{
  bootstrap: '/path/to/bootstrap-data'
}
```

## transform

Key/Value map of transformation scripts by data report source IDs.

```js
transform: {
  bookkeeping: function (server, dataReport, callback) {
    var lines = dataReport.data.split(/\n/)
    var indicators = []
    var matches

    for (var i = 0; i < lines.length; i++) {
      matches = lines[i].match(/^([+-]?[\d\.]+)\s*(.*)$/)
      if (!matches) return callback(new Error('Data could not be parsed'))
      indicators.push({
        type: 'movement',
        amount: parseFloat(matches[1]),
        category: matches[2] || 'not set'
      })
    }
    callback(null, indicators)
  }
}
```

## indices

CouchDB-compatible map/reduce functions by database & index names. The most
common use it to index integrated data and expose reduced data for charts.

For example:

```js
indices: {
  'integrated-data': {
    movementsByCategory: {
      version: '1.0.0',
      map: function (indicator) {
        emit(indicator.data.category, indicator.data.amount)
      },
      reduce: function (keys, values) {
        return {
          amount: sum(values)
        }
      }
    }
  }
}
```

## schema

_TBD: This is not yet implemented, the API is still being discussed_

[JSON Schema](http://json-schema.org/) definitions for raw data reports. If
a schema is defined for a report, the schema is applied to the report data.
If it fails, the report is accepted to avoid data loss, but an error is set
on the raw data report which prevents it from being transformed.

```js
schema: {
  bookkeeping: {
    type: 'string',
    pattern: /^[+-]?[\d\.,]+\s[^\n]+$/ // -2.20 coffee
  }
}
```

## audit

_TBD_ see: https://github.com/eHealthAfrica/kazana/issues/29

Definition of auditing rules to keep track of issues with raw data reports and
integrated data indicators. The rules are functions that return an
[issue](../glossary.md#issues) object, an array of issue objects, or a promise
that resolves either

```js
audit: [
  {
    movement: {
      rules: [
        function (server, indicators) {
          return indicators.map(function (indicator) {
            if (Math.abs(indicators.data.amount) > 1000) {
              return {
                reason: 'amount to high (> 1000)'
              }
            }
          }).filter(Boolean)
        }
      ]
    }
]
```

## events

_TBD: This is not yet implemented, the API is still being discussed_

```js
events: [
  on: 'report:add',
  handler: function (server, report) {
    server.methods.sendEmail({
      to: 'john@example.com',
      subject: 'new report submitted',
      text: toText(report),
      html: toHtml(report)
    })
  }
]
```

## entities

_TBD: This is not yet implemented, the API is still being discussed_

Kazana has build-in support for entities which can be used for data reports,
indices, and what ever comes to mind. `entities` is a key value map, where keys
are the entity type, name is a human readable title, and description can be
used for farther details. The `schema` property can be used to enforce
properties and values using a JSON Schema, `access` can be used to manage who
can access the entity. An entity can belong to another entity (e.g. a district
 can belong to a region). A parent entity type can be set in `belongsTo`.

```js
entities: {
  category: {
    name: 'Category',
    description: 'Assign income & expenses to a category for analysis',
    schema: categoryJsonSchema,
    access: {
      read: 'public',
      write: 'admin'
    }
  }
}
```

## account

_TBD: This is not yet implemented, the API is still being discussed_

```js
account: {
  // entity type to be used as source for user group IDs
  groups: ['agency']
}
```

see [hoodie-server-account’s plugin API](https://github.com/hoodiehq/hoodie-server-account/tree/master/plugin)
for more options.

## service

A function that gets executed before the server starts. It needs to call
the next function when done, if an error is passed, the server start is aborted.

```js
service: function (server, next) {
  // initialise service
  // e.g. start pulling data from some 3rd party service
  next()
}
```

## plugins

Array of objects with same properties as `options` for the
`Kazana` constructor.

```js
plugins: [
  require('kazana-email-inbox'),
  require('my-kazana-plugin')
]
```
