npm package: @jwhenry/rx-state
Description: Framework Agnostic State Management using RXJS 
Author: Justin Henry
Latest version: 1.2.3

# RX State
## Background
After working with Angular for a few years now, I have come to appreciate how people are able to build Angular specific libraries
that accomplish some major feats that make my job easier. I have come to a place where Angular no longer is a part of my best interests
and I am trying to find ways to spread some concepts to a framework-agnostic ecosystem that way I don't have to rewrite a majority of application
logic just to transfer to a new framework.

As a result of my research and experimentation, I have come to appreciate RXJS in a new way. Due to this new-found appreciation
I have come up with a simple state management platform based off of functional programming (slightly) and Redux to compliment those
who wish to have a basic-yet-robust state management system without locking into any one framework.

I hope that through my experimentation in this realm that others can benefit from my findings.

That being said, let's get into the meat of the library:

## Getting Started
This library is heavily influenced by NGXS and Redux to bring those patterns into a framework-agnostic environment.
You should be able to easily throw some code into any framework you want and bind your state and events in any way you please.

To get started: `npm i @jwhenry/rx-state --save`

Dependencies: `rxjs`, yes that is all.

### Event System
The event system is influenced by pub-sub models, Redux, and NGXS.
You are provided a global `events` constant that you can subscribe to in order to observe actions that take place.
You may also set `EventOptions.log` to true if you wish to watch these actions take place.

The event stream is the source of all state actions or any arbitrary behavior you want to trigger in your application.

An `eventsOf` function will allow you to provide a list of names or objects with an `event` property to listen specifically for.
When reading about how to create states, you will see how this is used to trigger state mutations within the ecosystem.

### Creating States
States act as reducers from Redux or State in NGXS. 
Their purpose is to handle the state mutation or other dispatching based on the new state values

Example Actions:
```typescript
export const SomeAction = 'some.action';
export declare type SomePayload = {value:string};
export interface ISomePayload {
    value:string
}
export class StoreSession {
    static readonly event = 'session.store';

    constructor(public data: SessionModel) {

    }
}

export class ClearSession {
    static readonly event = 'session.clear';

}
```
Example State:

States can be constructed with as little boilerplate as necessary.

- By using the `stateof` function, you can build NGXS-like stores with a context to wrap even more boilerplate nicely.
- You can still access other states by using the `selectSnapshot` and `dispatch` functions.
- The purpose of `stateOf` is to make your state fully self-aware and self-contained.
```typescript
import {dispatch, start, stateOf, removeAllStates} from "@jwhenry/rx-state";
import {StoreSession, SessionModel, ClearSession} from "./session-data";
export const SessionState = stateOf<SessionModel>('session', (onEvent, context) => {
    if (!context.getState()) {
        context.setState(new SessionModel()); // Set a default value
    } 
    onEvent(StoreSession, data => {
         // The data will be SessionModel according to the above examples
        context.setState(data);
    });
    onEvent(ClearSession, () => {
        // Clear all states because we don't want to retain anything for users who are not logged in
        removeAllStates();
        // OR remove a specific state
        context.setState(new SessionModel());
    })
}, true); // last argument is whether we persist the state
```

### Observing State
You can observe state in multiple ways:

- Watch the whole state
    - ```typescript
      import {state} from "@jwhenry/rx-state";
      state.subscribe(state => console.log(state));
      ```
- Watch a specific state
    - ```typescript
      import {select} from "@jwhenry/rx-state";
      select('session').subscribe(session => console.log(session));
      ```
- Grab a snapshot of a specific state
    - ```typescript
      import {selectSnapshot} from "@jwhenry/rx-state";
      console.log(selectSnapshot('session'));
      ```

### Starting and Stopping States
In order to start your states, you must register them and when ready, start them:
```typescript
import {register, startStates, stopStates} from "@jwhenry/rx-state";

register(SomeState, SomeOtherState);
startStates();

// Start a state late
start(SomeLazyState);

// After some time or when you want to kill state listeners
stopStates();
```
## Feedback and Future
If there are desired features or feedback that may spark a larger effort on this project, this may become something
that developers can use to replace some framework-specific state management tools.