# Ramistat

Middleware for web applications. Keeps app state in sync with URL, manages history, async orders, live data feeds.

## What it is

On the browser side, ramistat manages three kinds of state:

- **navigation state** - URL-synced, bookmarkable, shareable, history-tracked, every link is open-in-new-tab compatible, URLs are automatically shortened.
- **remote state** – live view of backend data with automatic validity tracking (*)
- **orders** – async requests to backend (*).
- **cache**

On the server side, ramistat handles:
- **url shortening**
- **live state production** - with all the niceties offered by the Hakuban library
- **async REST API** - dispatch, execution, load balancing (*)
- **MCP** - including knowledge base (*)

## How to use

### Installation

#### Browser setup

```javascript
import { StateManager } from 'ramistat'

const manager = StateManager.build()
	.with_url_shortener()
	.run()

for await (const state of manager.states()) {
	// state.navigation is the "location" state, tracked by browser history and the url bar
	// state.remote gives access to live backend data
	
	// TODO: 3-lines of mithril, showing how to access current navigation state value, and how to generate an A-tag
	// TODO: 3-lines of mithril, showing how to show live remote state
}
```

#### Backend (optional)

```bash
cargo install ramistat
ramistat --database-url postgresql://my_user@db_host/db_name --scrambler-key 0000000000000000000000000000000000000000000000000000000000000000 serve
```

### StateManager builder

TODO: describe builder methods

### NavigationState methods

```javascript
// shared state data
state.navigation.get("key")
state.navigation.set("key", "value")

// private state data (not URL-encoded)
state.navigation.private_get("key")
state.navigation.private_set("key", "value")

// generate attributes for an A-tag
state.navigation.set("view", "new-view").remove("some_old_id").hrefs()
// generate a url
state.navigation.set("view", "new-view").remove("some_old_id").url()
// trigger navigation instantly
state.navigation.set("view", "new-view").remove("some_old_id").navigate_to()
```
TODO: document all methods; explain state immutability

### Live remote state subscription

```javascript
// (re-)define what's needed
state.observe(definer=>{
	definer.observe("robots", [], "robot-list")
})

// access the state
state.remote.robots
state.remote.robots.data
```

### Cache

TODO: describe how to use state.cache

### Scopes

TODO: describe how to use scopes


## Getting help

- matrix channel: #ramistat:matrix.org
- Repository: https://gitlab.com/yunta/ramistat/
- Author: yunta <maciej.blomberg@mikoton.com>
- License: MIT
