# montar

manage state in typescript. inspired by [tolitius/mount](https://github.com/tolitius/mount) from clojure.

What's this all about? Watch this [video from Stuart Sierra](https://www.youtube.com/watch?v=13cmHf_kt-Q) to learn more about the background of component, mount, and montar.

## Install

```console
$ npm install --save-dev @digiresilience/montar
```

## Usage

```
import { defState } from "@digiresilience/montar"
```

### Creating State

```
// db.ts
const db = defState("db", {
  start: createDbConnection
})

export default db
```

where the createDbConnection function creates a connection (for example to a database) and is defined elsewhere.

### Starting state

```
import { start } from "@digiresilience/montar"

const bootYourApp = async () => {
  // .. prepare for app boot
  // ..

  // boot!
  return start()
}
```

### Using State

But wait, there is more.. this state is a top level being, which means it can be simply imported by other namespaces:

For example let's say an app needs a connection above. No problem:

```
// server.ts
import db from "./db"


async function doStuff() {
  return db.executeSql("foo")
}
```

Note that before `start()` is called, `db` will be uninitialized and therefore unusable. You must call `start()` before accessing any states.

### Starting/Stopping State

`montar` has start and stop functions that will walk all the states created with `defState` and start / stop them accordingly: i.e. will call their start and stop defined functions.

When testing you might be interested in starting only certain states. You can do this with

- `startOnly(string[])` - only start the given states. WARNING: dependencies are not auto started, so you must ensure all dependencies are passed.
- `startWithout(string[])` - start all states _except_ those passed

### Start and Stop Order

Since dependencies are "injected" by requiring on the namespace level, montar trusts the typescript compiler and node.js runtime to maintain the start and stop order for all the defStates.

The "start" order is then recorded and replayed on each subsequent start

The "stop" order is simply the reverse of the start order.

### Troubleshooting / Debugging

Set the `DEBUG=montar` environment variable for runtime debug logs.

## Differences to mount

montar was created to bring management of top-level application state under
control. It steals greedily from
[tolitius/mount](https://github.com/tolitius/mount) a well-known library in the
clojure and clojurescript community.

The problem solved is: how to load different sub-systems of your application while respecting dependency order? Also, how do achieve this without complicated dependency injection containers that make the code harder to read.

With montar once you define your state, then every other module can import and
use your state without special syntax or wrappers.

montar differs from mount in these ways:

- **start/stop are async** - the start and stop functions are async
- **no var rebinding** - instead we use the little-known [`Proxy`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy)
  - this comes with limitations: only functions, arrays, objects can be defined as state. scalars do not work.
- **not concerned with reloading** - in clj/cljs you have the repl and great hot-code reloading (thanks to immutable and persistent data structures). we do not have this in javascript.

## Credits

Copyright © 2020-present [Center for Digital Resilience][cdr]

### Contributors

| [![Abel Luck][abelxluck_avatar]][abelxluck_homepage]<br/>[Abel Luck][abelxluck_homepage] |
| ---------------------------------------------------------------------------------------- |


[abelxluck_homepage]: https://gitlab.com/abelxluck
[abelxluck_avatar]: https://secure.gravatar.com/avatar/0f605397e0ead93a68e1be26dc26481a?s=100&d=identicon

### License

[![License: AGPL v3](https://img.shields.io/badge/License-AGPL%20v3-blue.svg)](https://www.gnu.org/licenses/agpl-3.0.en.html)

    GNU AFFERO GENERAL PUBLIC LICENSE
    Version 3, 19 November 2007

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as
    published by the Free Software Foundation, either version 3 of the
    License, or (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <https://www.gnu.org/licenses/>.

[cdrtech]: https://digiresilience.org/tech/
[cdr]: https://digiresilience.org
