# Marble.js

Marble.js is a functional reactive Node.js framework for building server-side applications, based on TypeScript and RxJS.

![](/files/-M-RjDKDVCrV6h6A9YmT)

{% embed url="<https://medium.com/@jflakus/announcing-marble-js-3-0-a-marbellous-evolution-ba9cdc91d591>" %}

## Philosophy

The core concept of **Marble.js** assumes that almost everything is a stream. The main building block of the whole framework is an Effect, which is just a function that returns a stream of events. With the big popularity of [RxJS](http://rxjs.dev) Observable, you can create a referential transparent program specification made up of functions that may produce side effects like network, logging, database access, etc. Using its monadic nature we can map I/O operations over effects and flat them to bring in other sequences of operations. RxJS is used as a hammer for expressing asynchronous flow with monadic manner.

![](/files/-M-axbtvmhpoToC-gktV)

Marble.js doesn't operate only over basic [HTTP](/docs/v3/http/effects) protocol but can be used also for general MDA (Message-Driven Architecture) solutions, including [WebSocket](/docs/v3/messaging/websockets), [microservices](/docs/v3/messaging/microservices) or [CQRS](/docs/v3/messaging/cqrs), where the multi-event nature fits best. Don't be scared of the complexity and abstractions — Marble.js framework, in general, is incredibly simple. For more details about its specifics, please visit the next chapters that will guide you through the framework environment and implementation details.

> *For those who are curious about the framework name - it comes from a popular way of visually expressing the time-based behavior of event streams, aka marble diagrams. This kind of domain-specific language is a popular way of testing asynchronous streams, especially in RxJS environments.*

{% hint style="success" %}
👉 If you have ever worked with libraries like [Redux Observable](https://redux-observable.js.org), [@ngrx/effects](https://github.com/ngrx/platform/blob/master/docs/effects/README.md) or other libraries that leverage functional reactive paradigm, you will feel at home.
{% endhint %}

{% hint style="info" %}
👉 If you don't have any experience with functional reactive programming, we strongly recommend to gain some basic overview first with [ReactiveX intro](http://reactivex.io/intro.html) or with [The introduction to Reactive Programming you've been missing](https://gist.github.com/staltz/868e7e9bc2a7b8c1f754) written by [@andrestaltz](https://twitter.com/andrestaltz).
{% endhint %}

## Previous articles

{% embed url="<https://medium.com/@jflakus/marble-2-reactive-better-functional-stronger-5924119d3098>" %}

{% embed url="<https://medium.com/@jflakus/marble-js-when-node-js-meets-rxjs-da2764b7ca9b>" %}

## Examples

If you would like to get a quick glimpse of a simple RESTful API built with Marble.js, visit the following link:

{% content-ref url="/pages/-M-RgXr1EtrFnO8zp1d8" %}
[How does it glue together?](/docs/v3/other/how-does-it-glue-together)
{% endcontent-ref %}


# Installation

**Marble.js** requires node **v8.0** or higher:

```bash
$ npm i @marblejs/core fp-ts rxjs
```

or if you are a hipster:

```bash
$ yarn add @marblejs/core fp-ts rxjs
```

Every `@marblejs/*` package requires `@marblejs/core` + `fp-ts` + `rxjs` to be installed first.

| package                                                                             | description                  |
| ----------------------------------------------------------------------------------- | ---------------------------- |
| [@marblejs/core](/docs/v3/other/api-reference/core)                                 | Core module                  |
| [@marblejs/messaging](/docs/v3/other/api-reference/messaging)                       | Messaging module             |
| [@marblejs/websockets](/docs/v3/other/api-reference/websockets)                     | WebSocket module             |
| [@marblejs/testing](/docs/v3/testing/http-testing)                                  | Testing module               |
| [@marblejs/middleware-logger](/docs/v3/other/api-reference/middleware-logger)       | Logger middleware            |
| [@marblejs/middleware-body](/docs/v3/other/api-reference/middleware-body)           | Body parser middleware       |
| [@marblejs/middleware-io](/docs/v3/other/api-reference/middleware-io)               | I/O validation middleware    |
| [@marblejs/middleware-jwt](/docs/v3/other/api-reference/middleware-jwt)             | JWT authorization middleware |
| [@marblejs/middleware-cors](/docs/v3/other/api-reference/middleware-cors)           | CORS middleware              |
| [@marblejs/middleware-multipart](/docs/v3/other/api-reference/middleware-multipart) | Multipart middleware         |


# Quick setup

The very basic configuration consists of two steps: HTTP listener definition and HTTP server configuration.

`httpListener` is the basic starting point of every Marble application. It includes definitions of all global middlewares and API effects.

{% tabs %}
{% tab title="http.listener.ts" %}

```typescript
import { httpListener } from '@marblejs/core';
import { logger$ } from '@marblejs/middleware-logger';
import { bodyParser$ } from '@marblejs/middleware-body';
import { api$ } from './api.effects';

const middlewares = [
  logger$(),
  bodyParser$(),
  // middleware3$
  // middleware4$
  // ...
];

const effects = [
  api$,
  // endpoint2$
  // endpoint3$
  // ...
];

export const listener = httpListener({
  middlewares,
  effects,
});
```

{% endtab %}
{% endtabs %}

And here is our simple "hello world" endpoint.

{% tabs %}
{% tab title="api.effects.ts" %}

```typescript
import { r } from '@marblejs/core';
import { mapTo } from 'rxjs/operators';

export const api$ = r.pipe(
  r.matchPath('/'),
  r.matchType('GET'),
  r.useEffect(req$ => req$.pipe(
     mapTo({ body: 'Hello, world!' }),
  )));
```

{% endtab %}
{% endtabs %}

To create Marble app instance, we can use [`createServer`](/docs/v3/other/api-reference/core/createserver), which is a wrapper around Node.js server creator with much more possibilities and goods inside. When created, it won't automatically start listening to given port and hostname until you call its awaited instance.

{% tabs %}
{% tab title="index.ts" %}

```typescript
import { createServer } from '@marblejs/core';
import { IO } from 'fp-ts/lib/IO';
import { listener } from './http.listener';

const server = createServer({
  port: 1337,
  hostname: '127.0.0.1',
  listener,
});

const main: IO<void> = async () =>
  await (await server)();

main();
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
To see Marble.js in action you can visit [example repository](https://github.com/marblejs/example) for a complete Marble.js app example.
{% endhint %}

We'll use [TypeScript](https://www.typescriptlang.org/) in the documentation but you can always write Marble apps in standard JavaScript (and any other language that transpiles to JavaScript).

To test run your server you can install `typescript` compiler and `ts-node`:

```bash
$ yarn add typescript ts-node
```

Add the following script to your `package.json` file:

```javascript
"scripts": {
  "start": "ts-node index.ts"
}
```

Now go ahead, create `index.ts`, `http.listener.ts`, `api.effects.ts` modules in your project and run your server:

```bash
$ yarn start
```

Finally test your "functional" server by visiting [http://localhost:1337](/docs/v3/getting-started/quick-setup)

{% hint style="info" %}
For more API specific details about server bootstrapping, visit [createServer](/docs/v3/other/api-reference/core/createserver) API reference
{% endhint %}

In the next HTTP chapter you will learn how to create basic **Marble.js** endpoints using [Effects](/docs/v3/getting-started/quick-setup), how to build and compose middlewares and how to build a basic REST API routing.


# Effects

Effect is the main building block of the whole framework. It is just a function that returns a stream of events. Using its generic interface we can define API endpoints, event handlers or middlewares.

## Building your own Effect

```haskell
Effect :: Observable<T> -> Observable<U>
```

Marble.js **HttpEffect** is a more specialized form of Effect for processing HTTP requests. Its responsibility is to map every incoming request to response object.

```haskell
HttpEffect :: Observable<HttpRequest> -> Observable<HttpEffectResponse>
```

```typescript
import { HttpEffect, HttpEffectResponse, HttpRequest } from '@marblejs/core';
import { Observable } from 'rxjs/operators';
import { mapTo } from 'rxjs/operators';

const hello$ = (req$: Observable<HttpRequest>): Observable<HttpEffectResponse> =>
  req$.pipe(
    mapTo({ body: 'Hello, world!' }),
  );

// same as 

const hello$: HttpEffect = req$ =>
  req$.pipe(
    mapTo({ body: 'Hello, world!' }),
  );
```

The Effect above responds to incoming request with *"Hello, world!"* message. In case of HTTP protocol each incoming request has to be mapped to an object with **body**, **status** or **headers** attributes. If the status code or headers are not defined, then the API by default responds with `200 OK` status and `Content-Type: application/json` header.

{% hint style="info" %}
Every Marble.js Effect is eagerly bootstrapped on app startup with its own hot Observable.\
It means that a function can act as a constructor and a returned stream as a place "where the magic happens". It gives you a set of possibilities in terms of optimization, so e.g. you can inject all required [context readers](/docs/v3/http/context) during the app startup only once.&#x20;
{% endhint %}

In order to route our first HttpEffec&#x74;*,* we have to define the path and HTTP method that the incoming request should be matched to. The simplest implementation of an HTTP API endpoint can look like this.

{% tabs %}
{% tab title="hello.effect.ts" %}

```typescript
import { r } from '@marblejs/core';
import { mapTo } from 'rxjs/operators';

const hello$ = r.pipe(
  r.matchPath('/'),
  r.matchType('GET'),
  r.useEffect(req$ => req$.pipe(
    mapTo({ body: 'Hello, world!' }),
  )));
```

{% endtab %}
{% endtabs %}

Let's define a little bit more complex endpoint.

{% tabs %}
{% tab title="postUser.effect.ts" %}

```typescript
import { r } from '@marblejs/core';
import { map, mergeMap } from 'rxjs/operators';
import { User, createUser } from './user.helper';

const postUser$ = r.pipe(
  r.matchPath('/user'),
  r.matchType('POST'),
  r.useEffect(req$ => req$.pipe(
    map(req => req.body as User),
    mergeMap(createUser),
    map(body => ({ body }))
  )));
```

{% endtab %}
{% endtabs %}

The example above will match every POST request that matches to `/user` url. Using previously parsed body (see [bodyParser$](/docs/v3/other/api-reference/middleware-body) middleware) we can flat map it to other stream and map again to `HttpEffectResponse` object as an action confirmation.

{% hint style="warning" %}
**Deprecation warning**

With an introduction of Marble.js 3.0, old [`EffectFactory`](/docs/v3/other/api-reference/core/core-effectfactory) HTTP route builder is deprecated. Please use[`r.pipe`](/docs/v3/other/api-reference/core/r.pipe) builder instead.
{% endhint %}

**HttpRequest**

Every HttpEffect has an access to two most basics objects created by http.Server. **HttpRequest** is an abstraction over the basic *Node.js* [http.IncomingMessage](https://nodejs.org/dist/latest-v10.x/docs/api/http.html#http_class_http_incomingmessage) object. It may be used to access response status, headers and data, but in most scenarios you don't have to deal with all available APIs offered by IncomingMessage class. The most common properties available in request object are:

* url
* method
* headers
* body (see [bodyParser$](/docs/v3/other/api-reference/middleware-body) section)
* params (see [routing](broken://pages/-LDRN-W5HZ2wx3xRzuI-) chapter)
* query (see [routing](broken://pages/-LDRN-W5HZ2wx3xRzuI-) chapter)
* res (**HttpResponse)**

{% hint style="info" %}
For more details about available API offered in `http.IncomingMessage`, please visit [official Node.js docummentation](https://nodejs.org/dist/latest-v10.x/docs/api/http.html#http_class_http_incomingmessage).
{% endhint %}

**HttpResponse**

Response object is also an abstraction over basic *Node.js* [http.ServerResponse](https://nodejs.org/dist/latest-v10.x/docs/api/http.html#http_class_http_serverresponse) object. Besides the default API, the response object exposes an `res.send` method, which can be a handy wrapper over *Marble.js* responding mechanism. For more information about the *res.send* method, visit [Middlewares](/docs/v3/http/middlewares) chapter.

{% hint style="warning" %}
Since Marble.js version 3.0, HttpResponse object is accessible via `req.res` attribute of every HttpRequest.
{% endhint %}

{% hint style="info" %}
For more details about the available API offered in `http.ServerResponse`, please visit [official Node.js docummentation](https://nodejs.org/dist/latest-v10.x/docs/api/http.html#http_class_http_serverresponse).
{% endhint %}


# Middlewares

In Marble.js, middlewares are streams of side-effects that can be composed and plugged-in to our request/event lifecycle to perform certain actions before reaching the designated Effect.

## Building your own middleware

```haskell
MiddlewareEffect :: Observable<T> -> Observable<T>
```

Because everything here is a stream, the plugged-in middlewares are also based on a similar Effect interface.

```haskell
HttpMiddlewareEffect :: Observable<HttpRequest> -> Observable<HttpRequest>
```

By default, framework comes bundled with composable middlewares like: [logging](/docs/v3/other/api-reference/middleware-logger), request [body parsing](/docs/v3/other/api-reference/middleware-body) or request [validator](/docs/v3/other/api-reference/middleware-io). Below you can see how simple can look a dummy HTTP request logging middleware.

{% tabs %}
{% tab title="logger.middleware.ts" %}

```typescript
import { HttpMiddlewareEffect, HttpRequest } from '@marblejs/core';
import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';

const logger$ = (req$: Observable<HttpRequest>): Observable<HttpRequest> =>
  req$.pipe(
    tap(req => console.log(`${req.method} ${req.url}`)),
  );

// same as   

const logger$: HttpMiddlewareEffect = (req$, res) =>
  req$.pipe(
    tap(req => console.log(`${req.method} ${req.url}`)),
  );
```

{% endtab %}
{% endtabs %}

The example above performs I/O operation for every request that comes through the stream. As you can see, the middleware, compared to the basic effect, must return the processed request at the end.

In order to use our custom middleware, we need to attach the defined middleware to the `httpListener` config.

```typescript
import { httpListener } from '@marblejs/core';
import { logger$ } from './logger-middleware';

const middlewares = [
  // 👇 our custom middleware 
  logger$,
];

const listener = httpListener({ middlewares, effects });
```

### Parameterized middleware

There are some cases when our custom middleware needs to be parameterized - for example, the dummy `logger$` middleware should log request URL's conditionally. To achieve this behavior we can make our middleware function curried, where the last returned function should conform to`HttpMiddlewareEffect` interface.

```typescript
interface LoggerOpts {
  showUrl?: boolean;
}

const logger$ = (opts: LoggerOpts = {}): HttpMiddlewareEffect => req$ =>
  req$.pipe(
    tap(req => console.log(`${req.method} ${opts.showUrl ? req.url : ''}`)),
  );
```

The improved logging middleware, can be composed like in the following example:

```typescript
const middlewares = [
  // 👇 our custom middleware
  logger$({ showUrl: true }),
];
```

### Sending a response earlier

Some types of middlewares need to send an HTTP response earlier. For this case Marble.js exposes a dedicated `req.res.send` method which allows to send an HTTP response using the same common interface that we use for sending a response inside API Effects. The mentioned method returns an empty Observable (Observable that immediately completes) as a result, so it can be composed easily inside a middleware pipeline.

```typescript
import { HttpMiddlewareEffect } from '@marblejs/core';
import { mergeMap } from 'rxjs/operators';

const middleware$: HttpMiddlewareEffect = req$ =>
  req$.pipe(
    mergeMap(req => req.res.send({ body: 💩, status: 304, headers: /* ... */ })),
  );
```

If the HTTP response is sent earlier than inside the target Effect, the execution of all following middlewares and Effects will be skipped.

## Middlewares composition

You can compose middlewares in four ways:

* globally (inside `httpListener` configuration object),
* inside grouped effects (via `combineRoutes` function),
* or by composing it directly inside Effect request pipeline.

### via Effect

There are many scenarios where we would like to apply middlewares inside our API Effects. One of them is to authorize only specific endpoints. Going to meet the requirements, Marble.js allows us to compose them using dedicated [use operator](/docs/v3/other/api-reference/core/operator-use), directly inside request stream pipeline.

Lets say we have an endpoint for getting list of all users, but also we would like to make it secure, and available only for authorized users. All we need to do is to compose authorization middleware using dedicated for this case `use` operator.

{% tabs %}
{% tab title="getUsers.effect.ts" %}

```typescript
import { use, r } from '@marblejs/core';
import { authorize$ } from './auth.middleware';

const getUsers$ = r.pipe(
  r.matchPath('/'),
  r.matchType('GET'),
  // 👇 here...
  r.use(authorize$),
  r.useEffect(req$ => req$.pipe(
    // 👇 or here...
    use(authorize$),
    // ...
  )));
```

{% endtab %}
{% endtabs %}

The example implementation of `authorize$` middleware can look like in the following snippet:

{% tabs %}
{% tab title="auth.middleware.ts" %}

```typescript
import { HttpMiddlewareEffect, HttpError, HttpStatus } from '@marblejs/core';
import { of, throwError } from 'rxjs';

const authorize$: HttpMiddlewareEffect = req$ =>
  req$.pipe(
    mergeMap(req => !isAuthorized(req),
      ? throwError(new HttpError('Unauthorized', HttpStatus.UNAUTHORIZED)),
      : of(req)),
  );
```

{% endtab %}
{% endtabs %}

### via combineRoutes

There are some cases where you would like to compose a bunch of middlewares before grouped routes, e.g. to authorize only a selected group of endpoints. Instead of composing middlewares for each route separately, you can also compose them via extended second parameter of `combineRoutes()` function.

```typescript
import { combineRoutes } from '@marblejs/core';

const api$ = combineRoutes('/api/v1', {
  middlewares: [ authorize$ ],
  effects: [ user$, movie$, actor$ ],
});
```

### via httpListener

If your middleware should operate globally, e.g. in case of request logging, the best place is to compose it inside `httpListener`. In this case the middleware will operate on each request that goes through your HTTP server.

```typescript
import { httpListener } from '@marblejs/core';
import { logger$ } from '@marblejs/middleware-logger';
import { bodyParser$ } from '@marblejs/middleware-body';

const middlewares = [
  logger$(),
  bodyParser$(),
];

const effects = [
  // ...
];

export const listener = httpListener({ middlewares, effects });
```

{% hint style="info" %}
The stacking order of middlewares inside `httpListener` and `combineRoutes` matters, because middlewares are run sequentially (one after another).
{% endhint %}


# Routing

Routing determines how an application responds to a client request to a particular endpoint, which is a path and a specific HTTP method (eg. GET, POST).

## Route composition

As we know - every API requires composable routing. Lets assume that we have a separate **User** feature where its API endpoints respond to GET and POST methods on `/user` path.

{% hint style="warning" %}
**Deprecation warning**

With an introduction of Marble.js 3.0, old [`EffectFactory`](/docs/v3/other/api-reference/core/core-effectfactory) HTTP route builder is deprecated. Please use[`r.pipe`](/docs/v3/other/api-reference/core/r.pipe) builder instead.
{% endhint %}

`r.pipe` is an indexed monad builder used for collecting information about Marble REST route details, like: path, request method type, middlewares and connected Effect.

{% tabs %}
{% tab title="user.effects.ts" %}

```typescript
import { combineRoutes, r } from '@marblejs/core';

const getUsers$ = r.pipe(
  r.matchPath('/'),
  r.matchType('GET'),
  r.useEffect(req$ => req$.pipe(
    // ...
  )));

const postUser$ = r.pipe(
  r.matchPath('/'),
  r.matchType('POST'),
  r.useEffect(req$ => req$.pipe(
    // ...
  )));

export const user$ = combineRoutes('/user', [
  getUsers$,
  postUser$,
]);
```

{% endtab %}
{% endtabs %}

Route effects can be grouped together using `combineRoutes` function, which combines routing for a prefixed path passed as a first argument. Exported group of Effects can be combined with other Effects like in the example below.

{% tabs %}
{% tab title="api.effects.ts" %}

```typescript
import { combineRoutes, r } from '@marblejs/core';
import { user$ } from './user.effects';

const root$ = r.pipe(
  r.matchPath('/'),
  r.matchType('GET'),
  r.useEffect(req$ => req$.pipe(
    // ...
  )));

const foo$ = r.pipe(
  r.matchPath('/foo'),
  r.matchType('GET'),
  r.useEffect(req$ => req$.pipe(
    // ...
  )));

export const api$ = combineRoutes('/api/v1', [
  root$,
  foo$,
  user$, // 👈
]);
```

{% endtab %}
{% endtabs %}

As you can see, the previously defined routes can be combined together, so as a result the routing is built in a much more structured way. If we analyze the above example, the routing will be mapped to the following routing table.

```
GET    /api/v1
GET    /api/v1/foo
GET    /api/v1/user
POST   /api/v1/user
```

There are some cases where there is a need to compose a bunch of middlewares before grouped routes, e.g. to authenticate requests only for a selected group of endpoints. Instead of composing middlewares using [use operator](/docs/v3/other/api-reference/core/operator-use) for each route separately, you can compose them via the extended second parameter in`combineRoutes()` function.

```typescript
import { combineRoutes } from '@marblejs/core';

const user$ = combineRoutes('/user', {
  middlewares: [authorize$],
  effects: [getUsers$, postUser$],
});
```

## Body parameters

Marble.js doesn't come with a built-in mechanism for parsing POST, PUT and PATCH request bodies. In order to get the parsed request body you can use dedicated *@marblejs/middleware-body* package. A new `req.body` object containing the parsed data will be populated on the request object after the middleware, or undefined if there was no body to parse, the `Content-Type` was not matched, or an error occurred. To learn more about body parsing middleware visit the [@marblejs/middleware-body](/docs/v3/other/api-reference/middleware-body) API specification.

{% hint style="danger" %}
All properties and values in `req.body`object are untrusted and should be validated before usage.
{% endhint %}

{% hint style="danger" %}
By design, the `req.body, req.params, req.query`are of type `unknown`. In order to work with decoded values you should validate them before (e.g. using dedicated validator middleware) or explicitly assert attributes to the given type. We highly recommend to use the [@marblejs/middlware-io](/docs/v3/other/api-reference/middleware-io) package which allows you to properly infer the type of validated properties.
{% endhint %}

## URL parameters

The `combineRoutes` function and the `matchPath` allows you to define parameters in the path argument. All parameters are defined by the syntax with a colon prefix.

```typescript
import { r } from '@marblejs/core';

const foo$ = r.pipe(
  r.matchPath('/:foo/:bar'),
  // ...
);
```

Decoded path parameters are placed in the `req.params` property. If there are no decoded URL parameters then the property contains an empty object. For the above example and route `/bob/12` the `req.params` object will contain the following properties:

```typescript
{
  foo: 'bob',
  bar: '12',
}
```

For parsing and decoding URL parameters, Marble.js makes use of [`path-to-regexp`](https://github.com/pillarjs/path-to-regexp) library.

{% hint style="danger" %}
All properties and values in `req.params` object are untrusted and should be validated before usage.
{% endhint %}

{% hint style="info" %}
You should validate incoming URL params using dedicated [requestValidator$](/docs/v3/other/api-reference/middleware-io) middleware.
{% endhint %}

Path parameters can be suffixed with an asterisk (`*`) to denote a zero or more parameter matches. The code snippet below shows an example use case of a "zero-or-more" parameter. For example, it can be useful for defining routing for static assets.

{% tabs %}
{% tab title="getFile.effect.ts" %}

```typescript
import { r } from '@marblejs/core';
import { map, mergeMap } from 'rxjs/operators';

const getFile$ = r.pipe(
  r.matchPath('/:dir*'),
  r.matchType('GET'),
  r.useEffect(req$ => req$.pipe(
    // ...
    map(req => req.params.dir),
    mergeMap(readFile(STATIC_PATH)),
    map(body => ({ body }))
  )));
```

{% endtab %}
{% endtabs %}

## Query parameters

Except intercepting URL params, the routing is able to parse query parameters provided in path string. All decoded query parameters are located inside `req.query` property. If there are no decoded query parameters then the property contains an empty object. For parsing and decoding query parameters, Marble.js makes use of [`qs`](https://github.com/ljharb/qs) library.

**Example 1:**

```
GET /user?name=Patrick
```

```typescript
req.query = {
  name: 'Patrick',
};
```

**Example 2:**

```
GET /user?name=Patrick&location[country]=Poland&location[city]=Katowice
```

```typescript
req.query = {
  name: 'Patrick',
  location: {
    country: 'Poland',
    city: 'Katowice',
  },
};
```

{% hint style="danger" %}
All properties and values in `req.query` object are untrusted and should be validated before usage.
{% endhint %}

{% hint style="info" %}
You should validate incoming `req.query` parameters using dedicated[ requestValidator$](/docs/v3/other/api-reference/middleware-io) middleware.
{% endhint %}


# Errors

Every Marble.js listener factory allows you to intercept outgoing errors via dedicated error$ handler.

## Building your own error effect

Middlewares and Effects are based on the same generic interface, so also error handlers can work in a very similar way.

```haskell
HttpErrorEffect :: Observable<{ req: HttpRequest; error: E }>
  -> Observable<HttpEffectResponse>
```

{% tabs %}
{% tab title="error.effect.ts" %}

```typescript
import { HttpErrorEffect } from '@marblejs/core';
import { map } from 'rxjs/operators';

const error$: HttpErrorEffect = req$ =>
  req$.pipe(
    map(({ req, error }) => ({
     status: error.status,
     body: error.data,
    }),
  );
```

{% endtab %}
{% endtabs %}

As any other Effect, error handler maps the stream of errored requests to objects of type HttpEffectResponse (status, body, headers). To connect the custom error handler, all you need to do is to attach it to `error$` property in `httpListener` config object.

{% hint style="info" %}
By default Marble.js comes with built-in error handler, but based on requirements you can override it anytime.
{% endhint %}

{% tabs %}
{% tab title="http.listener.ts" %}

```typescript
import { httpListener } from '@marblejs/core';
import { error$ } from './error.effect';

const listener = httpListener({
  middlewares,
  effects,
  error$ // 👈
});
```

{% endtab %}
{% endtabs %}

Lets take a look again at the previous example of authorization middleware. In case of unauthorized request, `authorize$` middleware will throw an error an propagate it to error stream (custom or global one).

{% tabs %}
{% tab title="auth.middleware.ts" %}

```typescript
import { HttpMiddlewareEffect, HttpError, HttpStatus } from '@marblejs/core';
import { of, throwError } from 'rxjs';
import { mergeMap } from 'rxjs/operators';

const authorize$: HttpMiddlewareEffect = req$ =>
  req$.pipe(
    mergeMap(req => !isAuthorized(req)
      ? throwError(new HttpError('Unauthorized', HttpStatus.UNAUTHORIZED))
      : of(req)),
  );
```

{% endtab %}
{% endtabs %}

Marble.js comes with a dedicated `HttpError` class for defining request related errors that can be caught easily inside error handler. Using RxJS built-in `throwError` function, we can throw an error and catch it on an upper level (e.g. directly inside Effect or global error handler).

The `HttpError` class resides in the `@marblejs/core` package. The constructor takes as a first parameter an error message and as a second parameter a `HttpStatus` code that can be a plain JavaScript number or TypeScript enum. Optionally you can pass the third argument, which can contain any other error related values.

```typescript
new HttpError('Forbidden', HttpStatus.FORBIDDEN, { resource: 'index.html' });
```

## 404 error handling

404 (Not Found) responses are not the result of an error, so the error handler will not capture them. This behavior is because a 404 response simply indicates the absence of matched Effect in request lifecycle; in other words, request didn't find a proper route. Since Marble.js comes with built-in effect for matching not-found routes, but you can override it anytime. All you need to do is to define a dedicated Effect at the very end of the effects stack to handle a 404 response.

{% tabs %}
{% tab title="not-found.effect.ts" %}

```typescript
import { r, HttpError, HttpStatus } from '@marblejs/core';
import { throwError } from 'rxjs';
import { mergeMap } from 'rxjs/operators';

const notFound$ = r.pipe(
  r.matchPath('*'),
  r.matchType('*'),
  r.useEffect(req$ => req$.pipe(
    mergeMap(() =>
      throwError(new HttpError('Route not found', HttpStatus.NOT_FOUND))),
  )));
```

{% endtab %}
{% endtabs %}

The effect handles **all** paths and **all** method types then throws an 404 error code that can be intercepted inside global HttpErrorEffect.

"Not-found" Effects can be placed in any layer you want, eg. you can have multiple Effects that will handle missing routes in dedicated organization levels of your API structure.


# Output

Every Marble.js listener factory allows you to intercept outgoing messages via dedicated output$ handler.

## Building your own output effect

Using `HttpOutputEffect` you can grab an outgoing HTTP response and map it into different response, modifying outgoing data on demand.

```haskell
HttpOutputEffect :: Observable<{ req: HttpRequest; res: HttpEffectResponse }>
  -> Observable<HttpEffectResponse>
```

`HttpOutputEffect` allows you to grab the outgoing response together with corresponding initial request. Lets build a simple response compression middleware.

{% tabs %}
{% tab title="output.effect.ts" %}

```typescript
import { HttpOutputEffect } from '@marblejs/core';
import { map } from 'rxjs/operators';
import * as zlib from 'zlib';

const output$: HttpOutputEffect = res$ =>
  res$.pipe(
    map(({ res, req }) =>  {
      switch(req.headers['accept-encoding']) {
        case 'br':
          return ({
            ...res,
            headers: { ...res.headers, 'Content-Encoding': 'br' },
            body: res.body.pipe(zlib.createBrotliDecompress()),
          });
        case 'gzip':
          return ({
            ...res,
            headers: { ...res.headers, 'Content-Encoding': 'gzip' },
            body: res.body.pipe(zlib.createGunzip()),
          });
        case 'deflate':
          return ({
            ...res,
            headers: { ...res.headers, 'Content-Encoding': 'deflate' },
            body: res.body.pipe(zlib.createInflate()),
          });
        default:
          return res;
      }
    }),
  );
```

{% endtab %}
{% endtabs %}

To connect the output effect, all you need to do is to attach it to `output$` property in `httpListener` config object.

```typescript
import { httpListener } from '@marblejs/core';
import { output$ } from './output.effect';

export const listener = httpListener({
  middlewares: [ ... ],
  effects: [ ... ],
  output$, // 👈
});
```


# Context

DI is a very simple concept, which can be implemented in many different ways. Marble.js introduces a Context, which is an abstraction over Reader monad implementation of the DI system.

## Dependency Injection

Dependency Injection (DI) is a very simple concept, which can be implemented in many different ways. It means to get dependencies of a class passed in by using constructor, or to get dependencies of a function passed in by using arguments, or even more advanced techniques. If we step back and look at the concept in a more abstract way, the only thing to remember is that we gain the possibility to provide dependencies to any of our entities any point in time. Now we can provide different implementations of those dependencies by using extension (polymorphism), interface implementation, or whatever technique we want to use.

Marble.js comes to the DI concept in a different, more functional way, that can be very similar to popular pure functional languages like eg. Haskell. From version 2.0, Marble.js introduces a **Context**, which is an abstraction over Reader monad implementation of the DI system.

> The [`Reader`](http://hackage.haskell.org/package/mtl-2.2.2/docs/Control-Monad-Reader.html#t:Reader) monad (also called the Environment monad), represents a computation, which can read values from a shared environment, pass values from function to function, and execute sub-computations in a modified environment. \[...]
>
> \~ [Haskell docs](http://hackage.haskell.org/package/mtl-2.2.2/docs/Control-Monad-Reader.html)

## The basics

In Marble.js you don't have to create the app context explicitly. In order to create a basic environment you can use `createServer` function which prepares underneath a basic application context with default set of bounded dependencies, like, eg. [*Logger*](/docs/v3/http/advanced/logging).

Every context dependency that you would like to register has to conform to `ContextReader` interface, which in other words means that the registered function should be able to read from the bootstrapped server context. Knowing the basics, let's create some readers!

{% tabs %}
{% tab title="example.ts" %}

```typescript
import { createContextToken, reader } from '@marblejs/core';
import { pipe } from 'fp-ts/lib/function';
import * as R from 'fp-ts/lib/Reader';
import * as O from 'fp-ts/lib/Option';

export const Dependency1Token = createContextToken<string>('Dependency1');
export const Dependency2Token = createContextToken<string>('Dependency2');

export const Dependency1 = pipe(reader, R.map(() => 'Hello'));
export const Dependency2 = pipe(reader, R.map(ask => pipe(
  ask(Dependency1Token),
  O.map(v => v + ', world!'),
  O.getOrElse(() => ''),
)));
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="index.ts" %}

```typescript
import { bindTo createServer } from '@marblejs/core';
import { Dependency1, Dependency2, Dependency1Token, Dependency2Token } from './example';

const server = createServer({
  // ...
  dependencies: [
    bindTo(Dependency1Token)(Dependency1),
    bindTo(Dependency2Token)(Dependency2),
  ],
  // ...
});
```

{% endtab %}
{% endtabs %}

Having our dependencies defined, let's define some test Effect where we can check how our dependency can be consumed.

{% tabs %}
{% tab title="example.effect.ts" %}

```typescript
import { r } from '@marblejs/core';
import { mapTo } from 'rxjs/operators'; 
import { pipe } from 'fp-ts/lib/function';
import * as O from 'fp-ts/lib/Option';
import { Dependency2Token } from './example';

export const example$ = r.pipe(
  r.matchPath('/'),
  r.matchType('GET'),
  r.useEffect((req$, ctx) => {

    const dependency2 = pipe(
      ctx.ask(Dependency2Token),
      O.getOrElse(() => ''),
    );

    return req$.pipe(
      mapTo({ body: dependency2 }),
    );
  })
);
```

{% endtab %}
{% endtabs %}

If you will try to do a `GET /` request, you should see in the `Hello, world!` message in the response. Thats how Dependency Injection work in Marble.js!

Each Marble.js Effect defines a second argument called as `EffectContext` which holds i.a. the context provider (**ask**) and the contextual client instance (in case of HTTP module it will be a running *HttpServer*).

The type safety is very important. If you are percipient, you'll notice that by using previously defined `Dependency2Token` , we can also grab the dependency inferred type. Reading from the context is not a safe operation, thus the provided dependency is wrapped around [Option](https://gcanti.github.io/fp-ts/Option.html) monad that you can work on. As you can see the real benefit of using Readers is to be able to provide that context in an implicit way without the need to state it explicitly on each one of the functions that needs it.

{% hint style="info" %}
All Marble.js Effects are eagerly bootstrapped, which means that we you can inject dependencies only once at app startup, if the dependency is injected before the main *Observable* stream.
{% endhint %}

## createReader + useContext

As you can see reading from context is a very verbose operation - you have to pipe the reader instance, ask the context provider with a token, map the result and add a fallback in case of unmeet dependency. That's a lot of work to do! What is really needed is to resolve all required dependencies before the startup by asking the context and failing in case of unmeet dependency - that's the typical use case. Going out towards expectations, Marble.js defines a useful `createReader` and `useContext` utility functions that save a lot of unnecessary boilerplate. Let's redefine the previous example.

```typescript
import { createContextToken, createReader } from '@marblejs/core';

export const Dependency1Token = createContextToken<string>('Dependency1');
export const Dependency2Token = createContextToken<string>('Dependency2');

export const Dependency1 = createReader(() => 'Hello');
export const Dependency2 = createReader(ask =>
  useContext(Dependency1Token)(ask) + ', world!');
```

```typescript
import { r, useContext } from '@marblejs/core';
import { mapTo } from 'rxjs/operators';
import { Dependency2Token } from './example';

export const example$ = r.pipe(
  r.matchPath('/'),
  r.matchType('GET'),
  r.useEffect((req$, ctx) => {

    const dependency2 = useContext(Dependency2Token)(ctx.ask);

    return req$.pipe(
      mapTo({ body: dependency2 }),
    );
  }));
```

{% hint style="info" %}
In order to have a more grained control over injected context dependencies, please use a raw Reader monad.
{% endhint %}

## Eager vs lazy readers

Let's say you have a HTTP server that would like to connect with another one. When bootstrapping a WebSocket server we want to instantiate it as soon as possible (aka eagerly). The Marble.js Context was designed with a need for flexible way of connecting dependent modules - eagerly or lazily.

**By default Instances are created lazily - when they are needed**. If a dependency is never used by another component, then it won’t be created at all. This is usually what you want. For most readers there’s no point creating them until they’re needed. However, in some cases you want your dependencies to be started up straight away or even if they’re not used by another function. For example, you might want to send a message to a remote system or warm up a cache when the application starts. You can force a dependency to be created eagerly by using an **eager binding**.

In order to instantiate our registered dependency as soon as possible, you have to run it inside `bindEagerlyTo` function. It means that the registered dependency will try to resolve its dependencies on server startup.

{% hint style="warning" %}
Note that the order of registered lazy dependencies doesn't matter. Marble.js will start to resolve eager dependencies on on app startup, when all dependencies are already bound.
{% endhint %}

```typescript
import { bindTo, bindLazilyTo, bindEagerly } from '@marblejs/core';

// lazy binding
bindTo(Token)(Dependency);
bindLazilyTo(Token)(Dependency);

// eager binding
bindEagerly(Token)(Dependency);
```

## Async readers

Sometimes there is a need to suspend the application startup until one or more asynchronous tasks or jobs are fulfilled. For example, you may want to wait with starting up your server before the connection with a database has been established. The updated syntax of context readers handles Promises or async/await syntax out of the box in the reader factory. The context container (including Marble app factory) will await a resolution of the promise before instantiating any reader that depends on (injects) async reader.

```typescript
import { bindTo, bindEagerly } from '@marblejs/core';

// 1

bindEagerlyTo(Token)(async () => 'bar');

const foo = useContext(Token)(ask);   // foo === 'bar'

// 2

bindTo(Token)(async () => 'bar');

const foo = useContext(Token)(ask);   // foo === Promise<'bar'>
```

Let's look at an example of eager binding of a WebSocket server.

{% tabs %}
{% tab title="tokens.ts" %}

```typescript
import { createContextToken } from '@marblejs/core';
import { WebSocketServerConnection } from '@marblejs/websockets';

export const WebSocketServerToken =
  createContextToken<WebSocketServerConnection>('WebSocketServer');
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="index.ts" %}

```typescript
import { createServer, bindEageryTo } from '@marblejs/core';
import { mapToServer } from '@marblejs/websockets';
import { WebSocketServerToken } from './tokens';
import { webSocketServer } from './websocket.server';

const server = createServer({
  // ...
  dependencies: [
    bindEageryTo(WebSocketServerToken)(async () =>
      await (await webSocketServer)()
    ),
  ],
});
```

{% endtab %}
{% endtabs %}

Having the WebSocket dependency eagerly registered we can ask for it inside an Effect.

{% hint style="info" %}
Note that provided dependency won't be instantiated one more time while asking since it is already evaluated.
{% endhint %}

{% tabs %}
{% tab title="postItem.effect.ts" %}

```typescript
import { useContext } from '@marblejs/core';
import { requestValidator$, t } from '@marblejs/middleware-io';
import { bodyParser$ } from '@marblejs/middleware-body';
import { map, mergeMap } from 'rxjs/operators';
import { WebSocketServerToken } from './tokens';

const validateRequest = requestValidator$({
  body: t.type(...),
});

const postItem$ = r.pipe(
  r.matchPath('/items'),
  r.matchType('POST'),
  r.useEffect((req$, ctx) => {
    const webSocketServer = useContext(WebSocketServerToken)(ctx.ask);

    return req$.pipe(
      validateRequest,
      map(req => req.body),
      mergeMap(payload =>
        webSocketServer.sendBroadcastResponse({ type: 'ADDED_ITEM', payload })),
      // ...
      map(body => ({ body })),
    ));
  });
```

{% endtab %}
{% endtabs %}


# Advanced


# Logging

## Overview

`@marblejs/core` defines a pluggable **Logger** dependency registered by default to the context of every server factory. Having that you can inspect things like, registered context dependencies, mapped HTTP routes, request/response logs, I/O event traces, etc.

![](/files/-M0O8WSt6CgpR9kVX5bg)

## Logger

The interface allows you to define the log tag, type, main message and an optional level, which if not defined defaults to `LoggerLevel.INFO`.

```typescript
{
  tag: 'event_bus',
  type: 'saveOfferDocument$',
  message: 'Saving offer document...',
  level: LoggerLevel.INFO
}
```

```typescript
enum LoggerLevel { INFO, WARN, ERROR, DEBUG, VERBOSE };

interface LoggerOptions = {
  tag: string;
  type: string;
  message: string;
  level?: LoggerLevel;
};
```

Marble.js logger is an instance of IO monad which represents a synchronous effectful computation. In order to execute the logger you have to "run the `IO` action".

```haskell
Logger :: LoggerOptions -> IO<void>;
```

```typescript
import { LoggerTag, LoggerToken, LoggerLevel, use, r } from '@marblejs/core';
import { requestValidator$, t } from '@marblejs/middleware-io';
import { tap } from 'rxjs/operators';
import { UserDto } from './user.dto';

const foo$ = r.pipe(
  r.matchPath('/foo'),
  r.matchType('GET'),
  r.useEffect((req$, ctx) => {
    const logger = useContext(LoggerToken)(ctx.ask);

    const logMagic = logger({
      tag: LoggerTag.HTTP
      level: LoggerLevel.INFO,
      type: 'foo$',
      message: 'Here the magic happens...',
    });
            
    return req$.pipe(
      tap(logMagic),
      // ..
    ));
  });
```

## Custom logger

You can override the binding and map the stdout IO operations to a different destination (e.g. file or external service) when needed.

{% tabs %}
{% tab title="logger.reader.ts" %}

```typescript
import * as O from 'fp-ts/lib/Option';
import { pipe } from 'fp-ts/lib/pipeable';
import { Logger, LoggerLevel, createReader } from '@marblejs/core';
import { CustomLogger } from './customLogger';

export const CustomLoggerReader = createReader<Logger>(() => opts => {
  const tag = opts.tag;
  const level = opts.level ?? LoggerLevel.INFO;
  const message = `${opts.type} ${opts.message}`;
  const log = pipe(
    O.fromNullable({
      [LoggerLevel.ERROR]: CustomLogger.error,
      [LoggerLevel.INFO]: CustomLogger.log,
      [LoggerLevel.WARN]: CustomLogger.warn,
    }[level),
    O.getOrElse(() => CustomLogger.log),
  );

  return () => log({ tag, message });
});
```

{% endtab %}
{% endtabs %}

Then in your server definition you have to override the binding.

```typescript
import { bindTo, createServer, LoggerToken } from '@marblejs/core';
import { CustomeLoggerReader } from './logger.reader.ts';

const server = createServer({
  // ...
  dependencies: [
    bindTo(LoggerToken)(CustomLoggerReader),
  ],
});
```


# Validation

## Usage

[io-ts](https://github.com/gcanti/io-ts) is a nifty library that validates and checks at runtime that incoming data has the shape that you expect. This powerful library can extract a static type from the validator that is guaranteed to match any values that pass validation.

Lets say that we would like to validate users that can contain different roles from the given set: `'ADMIN' | 'GUEST'`. You can create string literals using combination of `t.union` and `t.literal` codecs.

{% tabs %}
{% tab title="user.dto.ts" %}

```typescript
import { t } from '@marblejs/middleware-io';

export const UserDto = t.type({
  id: t.string,
  firstName: t.string,
  lastName: t.string,
  roles: t.array(t.union([
    t.literal('ADMIN'),
    t.literal('GUEST'),
  ])),
});

export type UserDto = t.TypeOf<typeof UserDto>;

/* 👇
type User = {
  id: string;
  name: string;
  roles: ('ADMIN' | 'GUEST')[];
};
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="postUser.effect.ts" %}

```typescript
import { r } from '@marblejs/core';
import { requestValidator$, t } from '@marblejs/middleware-io';
import { UserDto } from './user.dto';

const validateRequest = requestValidator$({
  body: UserDto,
});

const postUser$ = r.pipe(
  r.matchPath('/'),
  r.matchType('POST'),
  r.useEffect(req$ => req$.pipe(
    validateRequest,
    // ..
  )));
```

{% endtab %}
{% endtabs %}

## Branded types

io-ts allows you to create a custom codec validators that must match to given predicate. There are ton of use cases where you can use this mechanism, eg. you would like to validate users which are adult (age is bigger or equal 18).

```typescript
import { t } from '@marblejs/middleware-io';

interface AgeAdultBrand {
  readonly AgeAdult: unique symbol;
}

const AdultAge = t.brand(
  t.number,
  (age): age is t.Branded<number, AgeAdultBrand> => age >= 18,
  'AgeAdult'
);

const User = t.type({
  id: t.string,
  name: t.string,
  age: AdultAge,
})

type User = t.TypeOf<typeof User>;

👇

type User = {
  id: string;
  name: string;
  age: t.Branded<number, AgeAdultBrand>;
};
```

As you can see, io-ts requires some boilerplate in order to have it properly typed, but the benefits are invaluable.

## Optional properties

According to [io-ts](https://github.com/gcanti/io-ts) documentation you can define a validator with optional values as an intersection of optional and required properties.

```typescript
import { t } from '@marblejs/middleware-io';

const Story = t.intersection([
  t.type({
    type: t.literal('story'),
    commentsTotal: t.number,
  }),
  t.partial({
    description: t.string,
    url: t.string,
  })
]);

type Story = t.TypeOf<typeof Story>;

👇

type Story = {
  type: 'story';
  commentsTotal: number;
} & {
  description?: string | undefined;
  url?: string | undefined;
}
```

The generated `Story` type is not as clean as it might be. [Jasse Hallett](https://www.olioapps.com/blog/checking-types-real-world-typescript/) in his article proposed a slightly different approach to defining optional values in validator schemas. Lets define a handy `optional` combinator!

```typescript
import { t } from '@marblejs/middleware-io';

export const optional = <T extends t.Any>(
  type: T,
  name = `${type.name} | undefined`
): t.UnionType<
  [T, t.UndefinedType],
  t.TypeOf<T> | undefined,
  t.OutputOf<T> | undefined,
  t.InputOf<T> | undefined
> =>
  t.union<[T, t.UndefinedType]>([type, t.undefined], name);
```

> Technically this implies that we expect the given property to be present in every case, but that the value might be `undefined`. In practice, that distinction often does not matter, and io-ts will validate an object that is missing a required property if the type of that property is allowed to be `undefined`.

Using the introduced combinator our `Story` definition can be much more cleaner and readable.

```typescript
import { t } from '@marblejs/middleware-io';

const Story = t.type({
  type: t.literal('story'),
  commentsTotal: t.number,
  description: optional(t.string),
  url: optional(t.string),
});

type Story = t.TypeOf<typeof Story>;

👇

type Story = {
  type: 'story';
  commentsTotal: number;
  description: string | undefined;
  url: string | undefined;
}
```


# Server Events

The Node.js server after startup can emit a variety of different events that the app can listen to, eg. `upgrade`, `listening`, etc. As you know, streams are the main building block of Marble.js. **@marblejs/core** [createServer](/docs/v3/other/api-reference/core/createserver) function allows you to listen to emitted server events via `event$` attribute, where you can hook your stream.

`HttpServerEffect` is used for dealing with stream of incoming server events, but in comparison to others, the interface doesn't specify what the output of the stream should be.

```typescript
import { createServer, matchEvent, ServerEvent, HttpServerEffect } from '@marblejs/core';
import { merge } from 'rxjs';
import { map, tap } from 'rxjs/operators';

const listening$: HttpServerEffect = event$ =>
  event$.pipe(
    matchEvent(ServerEvent.listening),
    map(event => event.payload),
    tap(({ port, host }) => console.log(`Running @ http://${host}:${port}/`)),
  );

const server = createServer({
  // ...
  event$: (...args) => merge(
    listening$(...args),
  ),
});
```

As in the case of WebSocket or messaging module, you can match incoming events using the same `matchEvent` operator.  `ServerEvent` contains a full list of events that you can match to, preserving at the same time type correctness of matched events.

## Upgrading HTTP connections

> The [HTTP/1.1 protocol](https://developer.mozilla.org/en-US/docs/Web/HTTP) provides a special mechanism that can be used to upgrade an already established connection to a different protocol, using the [`Upgrade`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Upgrade) header field.
>
> This mechanism is optional; it cannot be used to insist on a protocol change. Implementations can choose not to take advantage of an upgrade even if they support the new protocol, and in practice, this mechanism is used mostly to bootstrap a WebSockets connection.
>
> \---\
> source: [MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Protocol_upgrade_mechanism)

```typescript
import { createServer, matchEvent, ServerEvent, HttpServerEffect, bindEagerlyTo } from '@marblejs/core';
import { mapToServer } from '@marblejs/websockets';
import { merge } from 'rxjs';
import { WebSocketServerToken } from './tokens';
import { listener } from './http.listener';
import { webSocketServer } from './ws.listener';

const upgrade$: HttpServerEffect = (event$, ctx) =>
  event$.pipe(
    matchEvent(ServerEvent.upgrade),
    mapToServer({
      path: '/api/:version/ws',
      server: ctx.ask(WsServerToken),
    }),
  );

const server = createServer({
  port: 1337,
  httpListener,
  dependencies: [
    bindEageryTo(WebSocketServerToken)(async () =>
      await (await webSocketServer)()
    ),
  ],
  event$: (...args) => merge(
    upgrade$(...args),
  ),
});
```

You can upgrade running WebSocket server using dedicated [`mapToServer`](/docs/v3/other/api-reference/websockets/operator-maptoserver) operator. This kind of mechanism allows you to hook multiple WebSocket servers into an already running HTTP server on different paths.

```typescript
// `createServer`
bindEageryTo(WsServerToken_1)(async () => await (await webSocketServer_1)()),
bindEageryTo(WsServerToken_2)(async () => await (await webSocketServer_2)()),

// upgrade$
mapToServer({
  path: '/ws_1',
  server: ctx.ask(WsServerToken_1),
}, {
  path: '/ws_2',
  server: ctx.ask(WsServerToken_2),
}),
```


# Streaming

Node.js streams are collections of data that might not be available all at once, and they don’t have to fit in memory. This makes streams really powerful when working with large amounts of data, or data that’s coming from an external source one chunk at a time.

With Marble.js you can map Node.js streams directly through HttpEffectResponse **body** attribute which will be piped internally as client response.

```typescript
import { r, combineRoutes } from '@marblejs/core';
import { requestValidator$, t } from '@marblejs/middleware-io';
import { readFile } from '@marblejs/core/dist/+internal';
import { map } from 'rxjs/operators';
import * as fs from 'fs';
import * as path from 'path';

const validateRequest = requestValidator$({
  params: t.type({ dir: t.string })
});

const getFile$ = r.pipe(
  r.matchPath('/static/:dir*'),
  r.matchType('GET'),
  r.useEffect(req$ => req$.pipe(
    validateRequest,
    map(req => req.params.dir),
    map(dir => fs.createReadStream(path.resolve(STATIC_PATH, dir))),
    map(body => ({ body })),
  )),
);
```


# Continuous mode

## Overview

The basic HTTP/1.1 protocol can be tricky, especially when trying to place it in frames of proper event-based thinking. In its very basic version, every request should come with a corresponding response. It is not a full-duplex communication — first a client makes the request, then a server can respond to it. That means you cannot in an easy way selectively omit/filter/combine incoming requests because every incoming event has to be consumed. The processing enforced by the protocol frames makes things very limited.

Marble.js route resolving mechanism can work in two modes — **continuous** and **non-continuous***.* The second way is the default one which applies to 99% of possible use cases that you can model with REST APIs. Under the hood, it applies a default error handling for each incoming request making the request processing safe but tangled to disposable stream. The last 1% is for all the crazy ones. The new continuous mode allows you to process the stream of incoming requests in a fluent, non-detached way.

### Continuous mode

By default Marble.js HttpEffects work in non-continuous mode, which means that you have to explicitly tell the route that you would like to work in a continuous mode. In order to do that you have to append a metadata function to route builder with `continuous` flat set to true.

```typescript
  r.applyMeta({ continuous: true }),
```

The example below demonstrates an example Effect which buffers all the incoming requests till the `/flush` endpoint won't be triggered. After that all previously buffered requests will be flushed and all waiting responses will be sent back to client.

{% hint style="warning" %}
Notice that mapping to **error** and **response** comes with an initial `request` object required for sending back the response to client.
{% endhint %}

```typescript
import { r, HttpRequestBusToken, HttpStatus } from '@marblejs/core';
import { from, of } from 'rxjs';
import { bufferWhen, catchError, filter, map, mergeMap } from 'rxjs/operators';

const getFlush$ = (req$: Observable<HttpRequest>) =>
  req$.pipe(
    filter(req => req.method === 'GET' && req.url === '/flush'),
  );

const foo$ = r.pipe(
  r.applyMeta({ continuous: true }),
  r.matchPath('/'),
  r.matchType('GET'),
  r.useEffect((req$, ctx) => {
    const reqBus$ = useContext(HttpRequestBusToken)(ctx.ask);
    const terminate$ = getFlush$(reqBus$);

    return req$.pipe(
      bufferWhen(() => terminate$),
      mergeMap(buffer => from(buffer)),
      mergeMap(request => processData(request).pipe(
        map(body => ({ body, request })),
        catchError(error => of({
          request,
          status: HttpStatus.BAD_REQUEST,
          body: { error: { message: error.message }}
        })),
      )),
    );
  }));
```

{% hint style="warning" %}
By treating each incoming request as an event that always has to be consumed, **continuous** mode involves the necessity of adding a custom error handling mechanism for every processed event and mapping the response with its corresponding request.
{% endhint %}


# Core concepts

The core idea of @marblejs/messaging module is focused around reacting to incoming events.

## Overview

While you might have used REST as your service communications layer in the past, more and more projects are moving to an event-driven architecture. When a service performs some piece of work that other services might be interested in, that service produces an *event* — a record of the performed action. Other services consume those events so that they can perform any of their own tasks needed as a result of the event.

Since version 3.0, event-based communication is the framework prime focus of interest. It defines a uniform interface for asynchronous processing of incoming events. The mental model is very similar to other popular libraries that you can find in the frontend, like — `redux-observable` or `ngrx/effects`. Both libraries had a huge influence on design and architectural decisions.&#x20;

Messaging module can be applied to variety of models, including the post popular: queue, "pub/sub"-based [microservice](/docs/v3/messaging/microservices) communication, [CQRS](/docs/v3/messaging/cqrs) or EventSourcing.

{% content-ref url="/pages/-M-Rdj4-gGMRcZJ09EsM" %}
[Microservices](/docs/v3/messaging/microservices)
{% endcontent-ref %}

{% content-ref url="/pages/-M-RdbkPqCRMgipLWj8i" %}
[CQRS](/docs/v3/messaging/cqrs)
{% endcontent-ref %}

{% content-ref url="/pages/-M-RfgMM5OSzOwlli\_nX" %}
[WebSockets](/docs/v3/messaging/websockets)
{% endcontent-ref %}


# Events

The messaging module builds the mental model around an event - a uniform structure that represents a notification of specific type. Events can be handled in a variety of ways. For example, they can be published to a queue that guarantees delivery of the event to the appropriate consumers, or they can be published to a “pub/sub” model stream that publishes the event and allows access to all interested parties. In either case, the *producer* sends the event, and the *consumer* receives that event, reacting accordingly.

### Interface

Events are plain JavaScript objects. They must have a `type` property that indicates the type of event being performed and optional `payload` that carries additional information needed to process the event. As in most messaging systems, events are reified, i.e., they are represented as concrete objects and they can be stored and passed around.

Messaging mental model is a very simple, so it does not make a lot of assumptions about your events. Marble.js does not prescribe one way to construct them, nor it tells us how to define types and payloads. But this does not mean that all events are alike  👉 [CQRS](/docs/v3/messaging/cqrs).

```typescript
import { Event } from '@marblejs/core';

const event: Event = {
  type: 'USER_CREATED',
  payload: { id: '#123' },
};
```

Marble.js events can also carry additional information in form of  `metdata` that can be treat as less important from the domain perspective. They can include their unique/correlation identifier which can be used for determining to which input event the output event belongs. Besides that, they can also carry the information about a channel to which the response event should be directed. Both mentioned properties can be used for RPC (Remote Procedure Call) messaging.

Additionally, the interface defines an `error` property which can be used to optionally carry the exception information in form of plain object. The last and less important property is used internally by the framework to carry the `raw` data about the incoming event in form of transport layer compatible object.

```typescript
interface Event<P, E, T> {
  type: T;
  payload?: P;
  error?: E;
  metadata?: EventMetadata;
}

```

```typescript
interface EventMetadata {
  correlationId?: string;
  replyTo?: string;
  raw?: any;
}
```

{% hint style="info" %}
The design decision behind Marble.js messaging assumes that all events are serialized to the plain form that can be easily transferred via the underlying I/O transport layer. This means that  object instances like *Date* will be serialized to the plain form of ISO string format.
{% endhint %}

### I/O event decoding/encoding

Event-based communication follows the same laws as request-based communication - each incoming event should be validated before usage. With an introduction of version 3.3.0, **@marblejs/core** module exposes a dedicated **event** decoder/encoder which helps with maintaining a set of event codecs thanks to everyone well known `io-ts` library.

{% tabs %}
{% tab title="user.events.ts" %}

```typescript
import { event } from '@marblejs/core';
import * as t from 'io-ts';

enum UserEventType {
  USER_CREATED = 'USER_CREATED',
  USER_UPDATED = 'USER_UPDATED',
};

export const UserCreatedEvent =
  event(UserEventType.USER_CREATED)(t.type({
    id: t.string,
  }));
  

export const UserUpdatedEvent =
  event(UserEventType.USER_UPDATED)(t.type({
    id: t.string,
  }));
```

{% endtab %}
{% endtabs %}

Thanks to `io-ts` library we can infer event type from its definition and construct the event object accordingly:

```typescript
/*
const userUpdatedEvent: {
  type: UserEventType.USER_UPDATED,
  payload: {
    id: string,
  },
}
*/
const userUpdatedEvent = UserUpdatedEvent.create({ 
  id: 'some_id',
});
```

In order to match the incoming event agains the type literal and validator all you have to do is to apply the event codec to `matchEvent` operator and `eventValidator$` middleware.

```typescript
import { act, matchEvent } from '@marblejs/core';
import { MsgEffect } from '@marblejs/messaging';
import { eventValidator$ } from '@marblejs/middleware-io';
import { UserUpdatedEvent } from './user.events';

const userUpdated$: MsgEffect = event$ =>
  event$.pipe(
    matchEvent(UserUpdatedEvent),
    act(eventValidator$(UserUpdatedEvent)),
    act(event => ...),
  );
```


# Effects

Marble.js messaging mental model represents incoming notifications as a stream of Events, that can be emitted either by an independent producer (client) or another consumer.

![](/files/-M-ax_hM5Mf6K8h_oIwA)

### Processing

The module is built around similar abstractions, like: effect, middleware or output streams. The messaging effect it's just an extension of generic core Effect which is a function that maps a stream of incoming Events to another stream of outgoing Events, thus middleware and output models are a direct equivalent of basic effects.

```haskell
MsgEffect :: Observable<Event> -> Observable<Event>

MsgOutputEffect :: Observable<Event> -> Observable<Event>

MsgMiddlewareEffect :: Observable<Event> -> Observable<Event>
```

`MsgEffect` when compared to their predecessor in form of `HttpEffect` is much more powerful tool, taking the possibilities to the next level. Once you're inside your Effect, use any Observable patterns you desire as long as any output from the final, returned stream, is an Event.

![](/files/-M-axbtvmhpoToC-gktV)

The marble diagram above can be translated into effect code as follows.

```typescript
import { matchEvent } from '@marblejs/core';
import { MsgEffect } from '@marblejs/messaging';
import { mergeMap } from 'rxjs/operators';

const userCreated$: MsgEffect = event$ =>
  event$.pipe(
    matchEvent('USER_CREATED'),
    mergeMap(event => [
      { type: 'SEND_WELCOME_SMS_FOR_USER', payload: event.payload.id },
      { type: 'SEND_WELCOME_EMAIL_FOR_USER', payload: event.payload.id },
    ]),
  );
```

Effects can define the matching against one or more events. Marble.js exposes a [`matchEvent`](/docs/v3/other/api-reference/core/operator-matchevent) operator that is just an abstraction over RxJS `filter` operator, with additional functionalities and type-safety underneath.

{% hint style="warning" %}
Keep in mind that messaging effects will always try to emit back the outgoing event. Mapping to  the same input event will cause an infinite loop. You should always map the input event to different event type, or skip emitted values, eg. by `ignoreElements` operator, in case you don't want to output anything.
{% endhint %}

{% hint style="info" %}
To learn more about `matchEvent` operator please visit core [API documentation](/docs/v3/other/api-reference/core/operator-matchevent).
{% endhint %}

### Error handling

Effects are built on top of observable streams provided by RxJS. They are listeners of observable streams that continue until an error or completion occurs. In order for effects to continue running in the event of an error in the observable, or completion of the observable stream, they must be nested within a "flattening" operator, such as `mergeMap`, `concatMap`, `exhaustMap` or other flattening operator. The snippet below shows the example error handling strategy for fetching an author.

```typescript
import { matchEvent } from '@marblejs/core';
import { MsgEffect } from '@marblejs/messaging';
import { of } from 'rxjs';
import { catchError, map, mergeMap } from 'rxjs/operators';
import { pipe } from 'fp-ts/lib/pipeable';

const getUser$: MsgEffect = event$ =>
  event$.pipe(
    matchEvent('GET_USER'),
    mergeMap(event => pipe(
      getUser(event.payload.id),
      map(payload => ({ type: 'GET_USER_RESULT', payload })),
      catchError(error => of({
        type: 'GET_USER_ERROR',
        error: { name: error.name, message: error.message },
      })),
    )),
  );
```

{% hint style="danger" %}
Always remember to catch an error in disposable stream. If not, the event stream will be restarted, which means that every already processing event will be lost. Listener will try to resubscribe the stream automatically notifying the developer about the error.
{% endhint %}

Marble.js defines an [`act`](/docs/v3/other/api-reference/core/operator-act) operator that reduces the required boilerplate to minimum applying the error handling underneath the operator.

```typescript
import { act, matchEvent } from '@marblejs/core';
import { MsgEffect } from '@marblejs/messaging';
import { map } from 'rxjs/operators';
import { pipe } from 'fp-ts/lib/pipeable';

const getUser$: MsgEffect = event$ =>
  event$.pipe(
    matchEvent('GET_USER'),
    act(event => pipe(
      getUser(event.payload.id),
      map(payload => ({ type: 'GET_USER_RESULT', payload })),
    )),
  );
```

{% hint style="info" %}
To learn more about `act` operator please visit core [API documentation](/docs/v3/other/api-reference/core/operator-act).
{% endhint %}

### Replying

The previous example shows an effect that produces `GET_USER_RESULT` event without replying to producer. As mentioned in [previous chapter](/docs/v3/messaging/core-concepts/events), event interface defines two additional metadata attributes: `replyTo` and `correlationId`. Typically when dealing with RPC (request-response) messaging, the event handler (effect) has to reply in case of success or error. In order to do that, effect has to combine the mapped outgoing event with incoming event metadata, passing the information about the **correlation id** that the producer will look for and the **reply channel** where the outgoing event should be routed to.

```typescript
import { act, matchEvent } from '@marblejs/core';
import { reply, MsgEffect } from '@marblejs/messaging';
import { map } from 'rxjs/operators';
import { pipe } from 'fp-ts/lib/pipeable';

const getUser$: MsgEffect = event$ =>
  event$.pipe(
    matchEvent('GET_USER'),
    act(event => pipe(
      getUser(event.payload.id),
      map(payload => ({
        type: 'GET_USER_RESULT',
        payload,
        metadata: e.metadata, // { correlationId, replyTo }
      })),
    )),
  );
```

Again, in order to make the event processing more descriptive and easier to understand, Marble.js defines a [`reply`](/docs/v3/other/api-reference/messaging/reply) function that makes the mapping more explicit.

```typescript
import { act, matchEvent } from '@marblejs/core';
import { reply, MsgEffect } from '@marblejs/messaging';
import { map } from 'rxjs/operators';
import { pipe } from 'fp-ts/lib/pipeable';

const getUser$: MsgEffect = event$ =>
  event$.pipe(
    matchEvent('GET_USER'),
    act(event => pipe(
      getUser(event.payload.id),
      map(payload => reply(event)({ type: 'GET_USER_RESULT', payload })),
    )),
  );
```

{% hint style="info" %}
To learn more about `reply` function please visit messaging [API documentation.](/docs/v3/other/api-reference/messaging/reply)
{% endhint %}

{% hint style="warning" %}
When replying to an incoming event, remember to define a different event type than the origin one. In some specific use cases there is a high risk that an emitted command (non RPC message) will produce an infinite loop.
{% endhint %}


# Microservices

Using a dedicated @marblejs/messaging module, Marble.js offers a robust and unified architecture for building event-based microservices.

{% hint style="warning" %}
This chapter doesn't intend to describe the idea that stands behind Microservices. If you would like to learn more about it, there are many good resources that explain the topic in a better way.
{% endhint %}

## Installation

```bash
$ yarn add @marblejs/messaging @marblejs/core rxjs fp-ts
```

## **Overview**

> **Microservice** architecture is an architectural style that structures an application as a collection of services that are: highly maintainable and testable, loosely coupled, independently deployable, organized around business capabilities, owned by a small team. The architecture enables the rapid, frequent and reliable delivery of large, complex applications.\
> [👉 https://microservices.io/](https://microservices.io/)

Microservices need a lightweight approach for communicating with one another. HTTP/1.1 is certainly a valid protocol but there are better options — especially when considering performance. While you might have used REST as your service communications layer in the past, more and more projects are moving to an event-driven architecture. When a service performs some piece of work that other services might be interested in, that service produces an *event* — a record of the performed action. Other services consume those events so that they can perform any of their own tasks needed as a result of the event.

`@marblejs/messaging` defines the concept of transport layers, similar to NestJS. They are taking the responsibility of transporting messages between two parties. The messaging module abstracts the implementation details of each layer behind a generic Effect interface. For the sake of beginning, Marble.js 3.0 implements the [AMQP (RabbitMQ)](/docs/v3/messaging/microservices/rabbitmq) and [Redis Pub/Sub](/docs/v3/messaging/microservices/redis-pub-sub) transport layers.

{% hint style="info" %}
More transport layers are supposed to come in future minor releases, e.g. *NATS*, *MQTT* or *GRPC*.
{% endhint %}

### Consumer

To instantiate a microservice, use the `createMicroservice()`.

{% tabs %}
{% tab title="consumer.ts" %}

```typescript
import { createMicroservice, messagingListener, Transport } from '@marblejs/messaging';
import { IO } from 'fp-ts/lib/IO';
import { hello$ } from './consumer.effect';

const listener = messagingListener({
  middlewares: [ ... ],
  effects: [ hello$ ],
});

const microservice = createMicroservice({
  transport: Transport.AMQP
  options: {
    host: 'amqp://localhost:5672',
    queue: 'hello_queue',
  },
  listener,
  dependencies: [ ... ],
});

const main: IO<void> = async () =>
  await (await microservice)();

main();
```

{% endtab %}
{% endtabs %}

The configuration object passed to factory function is very similar to other server factories, i.a. it allows to hook the *event$*, define dependencies and of course pass a listener. Besides that you have to obligatory define the transport layer and its options. The `options` object is always specific to the chosen transporter.

| Attribute   | Description                                                                  |
| ----------- | ---------------------------------------------------------------------------- |
| `transport` | Specifies the transport layer (e.g. `Transport.AMQP`)                        |
| `options`   | A transport-specific options object that determines transport layer behavior |

Microservice Effects can defined as any other `MsgEffect`. For more details about possible ways of processing events please visit messaging [Effects](/docs/v3/messaging/core-concepts/effects) chapter.

{% tabs %}
{% tab title="consumer.effect.ts" %}

```typescript
import { act, matchEvent } from '@marblejs/core';
import { MsgEffect } '@marblejs/messaging';
import { of } from 'rxjs';

export const hello$: MsgEffect = (event$, ctx) =>
  event$.pipe(
    matchEvent('HELLO'),
    act(event =>
      of(reply(event)({
        type: event.type,
        payload: `Hello, ${event.payload}!`,
      })
    ),
  );
```

{% endtab %}
{% endtabs %}

### Publisher

A Publisher aka Client can exchange messages or publish events to a microservice.

{% tabs %}
{% tab title="publisher.client.ts" %}

```typescript
import { createContextToken } from '@marblejs/core';
import { messagingClient, MessagingClient, Transport } from '@marblejs/messaging';

export const ClientToken = createContextToken<MessagingClient>('MessagingClient');

export const client = messagingClient({
  transport: Transport.AMQP
  options: {
    host: 'amqp://localhost:5672',
    queue: 'hello_queue',
  },
});
```

{% endtab %}
{% endtabs %}

`messgingClient` factory function defines an interface similar to microservice factory: **transport** and **options**. Remember that you have to define your own context token for each messaging client you would like to bound to context. Messaging client exposes two main methods:

| Method  | Description                                          |
| ------- | ---------------------------------------------------- |
| `send`  | Blocking (**request-response**), RPC-like messaging. |
| `emit`  | Asynchronous messaging without response.             |
| `close` | Closes active connection and teardowns subscribers.  |

If you would like to communicate HTTP effects with your microservice just inject the bound client by specific token.

{% tabs %}
{% tab title="publisher.effect.ts" %}

```typescript
import { r, useContext, HttpStatus } from '@marblejs/core';
import { mapTo, mergeMapTo } from 'rxjs/operators';
import { ClientToken } from './client';

export const getRoot$ = r.pipe(
  r.matchPath('/'),
  r.matchType('GET'),
  r.useEffect((req$, ctx) => {
    const client = useContext(ClientToken)(ctx.ask);

    return req$.pipe(
      mergeMapTo(client.send({ type: 'HELLO', payload: 'John' })),
      mapTo({ status: HttpStatus.ACCEPTED }),
    );
  }),
);
```

{% endtab %}
{% endtabs %}

Remember that you have to bound the client to context before usage.

{% tabs %}
{% tab title="publisher.ts" %}

```typescript
import { bindEagerlyTo, createServer, httpListener } from '@marblejs/core';
import { IO } from 'fp-ts/lib/IO';
import { client, ClientToken } from './client';
import { getRoot$ } from './effect';

const listener = httpListener({
  effects: [ getRoot$ ],
});

const server = createServer({
  listener,
  dependencies: [
    bindEagerlyTo(ClientToken)(client),
  ],
});

const main: IO<void> = async () =>
  await (await server)();

main();
```

{% endtab %}
{% endtabs %}


# AMQP (RabbitMQ)

AMQP is an open standard application layer protocol for message-oriented communication, i.e. implemented by RabbitMQ message-broker.

> RabbitMQ is the most widely deployed open source message broker. With tens of thousands of users, it is one of the most popular open source message brokers. From [T-Mobile](https://www.youtube.com/watch?v=1qcTu2QUtrU) to [Runtastic](https://medium.com/@runtastic/messagebus-handling-dead-letters-in-rabbitmq-using-a-dead-letter-exchange-f070699b952b), it is used worldwide at small startups and large enterprises. RabbitMQ is lightweight and easy to deploy on premises and in the cloud. It supports multiple messaging protocols and can be deployed in distributed and federated configurations to meet high-scale, high-availability requirements.

## Installation

Before the usage remember to install required packages.

```bash
$ yarn add amqplib amqp-connection-manager
```

## Overview

{% tabs %}
{% tab title="microservice.ts" %}

```typescript
import { createMicroservice, Transport } from '@marblejs/messaging';

const microservice = createMicroservice({
  transport: Transport.AMQP
  options: {
    host: 'amqp://localhost:5672',
    queue: 'hello_queue',
    queueOptions: { durable: false },
  },
  // ...
});
```

{% endtab %}

{% tab title="client.ts" %}

```typescript
import { createMicroservice, Transport } from '@marblejs/messaging';

const client = messagingClient({
  transport: Transport.AMQP
  options: {
    host: 'amqp://localhost:5672',
    queue: 'hello_queue',
  },
  // ...
});
```

{% endtab %}
{% endtabs %}

The `options` property is specific to the chosen transport layer. **AMQP** exposes the following properties:

| Attribute       | description                                                                                                           |
| --------------- | --------------------------------------------------------------------------------------------------------------------- |
| `host`          | Host address of the RabbitMQ server                                                                                   |
| `queue`         | Queue name which your microservice will listen to                                                                     |
| `queueOptions`  | Additional queue options (see [`AssertQueue`](https://www.squaremobius.net/amqp.node/channel_api.html) specification) |
| `prefetchCount` | Sets the prefetch count for the channel                                                                               |
| `expectAck`     | If `true`, manual acknowledgment mode is enabled                                                                      |
| `timeout`       | Timeout for RPC-like communication. Defaults to **120 seconds**                                                       |

### Acknowledgement

To make sure an event is never lost, RabbitMQ supports [message acknowledgements](https://www.rabbitmq.com/confirms.html). An acknowledgement is sent back by the consumer to tell RabbitMQ that a particular message has been received, processed and that RabbitMQ is free to delete it. If a consumer dies (its channel is closed, connection is closed, or TCP connection is lost) without sending an *ack*, RabbitMQ will understand that a message wasn't processed fully and will re-queue it.

To enable manual acknowledgment mode, set the `expectAck` property to `true`.

{% tabs %}
{% tab title="microservice.ts" %}

```typescript
import { createMicroservice, Transport } from '@marblejs/messaging';

const microservice = createMicroservice({
  transport: Transport.AMQP
  options: {
    host: 'amqp://localhost:5672',
    queue: 'hello_queue',
    expectAck: true, // 👈
  },
  // ...
});
```

{% endtab %}
{% endtabs %}

When manual acknowledgements are turned on, we must send a proper acknowledgement from the worker to signal that we are done with a task.

```typescript
import { MsgEffect, ackEvent, nackEvent } from '@marblejs/messaging';
import { matchEvent } from '@marblejs/core';
import { pipe } from 'fp-ts/lib/pipeable';
import { mapTo, tap, catchError } from 'rxjs/operators';

const foo$: MsgEffect = (event$, ctx) =>
  event$.pipe(
    matchEvent('FOO'),
    act(event => pipe(
      // do some work...
      // ...and ack event
      tap(event => ackEvent(ctx)(event)()),
      mapTo({ type: 'FOO_RESPONSE' }),
      catchError(error => pipe(
        // nack event in case of an exception 
        defer(nackEvent(ctx)(event)),
        mergeMapTo(throwError(error)),
      ));
    )),
  );
```

**@marblejs/messaging** v3.3 introduces three handy functions for event acknowledgement: `ackEvent`, `nackEvent` and `nackAndResendEvent`. While the behavior of the first function is obvious, the second function will reject the event immediately, where the third one will try to resend the event again to the origin channel. You have to pass `EffectContext` first and the incoming event object to which acknowledgement will be made. Since all three functions are doing an asynchronous side effect, you have to call it explicitly.

```typescript
nackEvent(ctx)(event)() // Task<boolean> === () => Promise<boolean>
```

{% hint style="warning" %}
It is in the responsibility of developer to *nack* messages. If the consumer won't *nack* the message, it will hang up and wait for (non-)acknowledgement signal till the default transport layer timeout or the connection closing signal. After this time the event will be automatically rejected.
{% endhint %}

{% hint style="info" %}
If the microservice (consumer) is in acknowledgement mode (`expectAck: true`), all outgoing messages that target the same origin queue won't be emitted to prevent accidental consumer blocking. If you would like to emit another event, eg. as a confirmation response to the origin queue with acknowledgement mode enabled, you have to emit the event explicitly by connected messaging client.
{% endhint %}


# Redis Pub/Sub

Redis Pub/Sub implements the messaging system where the publishers sends the messages while the subscribers receive them.

> Aside from data storage, [Redis](https://redis.io/) can be used as a Publisher/Subscriber platform. In this pattern, publishers can issue messages to any number of subscribers on a channel. These messages are fire-and-forget, in that if a message is published and no subscribers exists, the message evaporates and cannot be recovered.

## Installation

Before the usage remember to install required packages.

```bash
$ yarn add redis
```

## Overview

{% tabs %}
{% tab title="microservice.ts" %}

```typescript
import { createMicroservice, Transport } from '@marblejs/messaging';

const microservice = createMicroservice({
  transport: Transport.REDIS
  options: {
    host: 'redis://127.0.0.1:6379',
    channel: 'hello_channel',
  },
  // ...
});
```

{% endtab %}

{% tab title="client.ts" %}

```typescript
import { createMicroservice, Transport } from '@marblejs/messaging';

const client = messagingClient({
  transport: Transport.REDIS
  options: {
    host: 'redis://127.0.0.1:6379',
    channel: 'hello_channel',
  },
  // ...
});
```

{% endtab %}
{% endtabs %}

The `options` property is specific to the chosen transport layer. **REDIS** exposes the following properties:

| Attribute  | description                                                     |
| ---------- | --------------------------------------------------------------- |
| `host`     | Host address of the Redis server                                |
| `channel`  | Channel name which your microservice will listen to             |
| `timeout`  | Timeout for RPC-like communication. Defaults to **120 seconds** |
| `port`     | Port of the Redis server                                        |
| `password` | If set, client will run Redis auth command on connect.          |


# CQRS

{% hint style="warning" %}
This chapter doesn't intend to describe the idea that stands behind CQS/CQRS. If you would like to learn more about it, there are many good resources that explain the topic in a better way.
{% endhint %}

## Installation

```bash
$ yarn add @marblejs/core @marblejs/messaging rxjs fp-ts
```

## Overview

The design has as its main concern, the separation of read and write operations The pattern divides methods into three categories: commands, queries and events.

{% hint style="success" %}
Marble.js implements a dedicated “local” transport layer for EventBus messaging, which can be easily adopted to CQS/CQRS pattern. Compared to other popular implementations, the module implements only one, common bus for transporting events of any type.
{% endhint %}

#### Commands

Dispatching a command is akin to invoking a method: we want to do something specific. This means we can only have one place, one handler, for every command. This also means that we may expect a reply: either a value or an error. Firing command is the only way to change the state of our system - they are responsible for introducing all changes to the system.

```typescript
{
  type: 'CREATE_USER',
  payload: {
    firstName: 'John',
    lastName: 'Doe',
  }
}
```

#### Queries

Queries never modify the database - they only perform read operations so they don't affect the state of the system. A query returns a DTO that does not encapsulate any domain knowledge.

```typescript
{
  type: 'GET_USER_BY_ID',
  payload: {
    id: '#ABC123',
  }
}
```

#### Events

When dispatching an event, we notify the application about the change. We do not get a reply and there might be more than one effect handler registered.

```typescript
{
  type: 'USER_CREATED',
  payload: {
    id: '#ABC123',
  }
}
```

### EventBus

In order to initialize event bus you have bind the dependency to the server. Since the context resolving can occur in an asynchronous way the dependency has to be bound eagerly (on app startup). The factory inherits all bounded dependencies from the server, so there is not need to register the same dependencies one more time.

```typescript
import { bindEagerlyTo } from '@marblejs/core';
import { EventBusToken, eventBus } from '@marblejs/messaging';

const listener = messagingListener({
  middlewares: [ ... ],
  effects: [ ... ],
});

// ...

bindEagerlyTo(EventBusToken)(eventBus({ listener })),
```

### EventBus Client

EventBus client is a specialized form of messaging client that operates on local transport layer. It can be injected into any effect via `EventBusClientToken`. Due to its async nature it has to be bound eagerly on app startup.

```typescript
import { bindEagerlyTo } from '@marblejs/core';
import { EventBusClientToken, eventBusClient } from '@marblejs/messaging';

// ...

bindEagerlyTo(EventBusClientToken)(eventBusClient),
```

Similar to every messaging client, the reader exposes two main methods:

| method  | description                                          |
| ------- | ---------------------------------------------------- |
| `send`  | Blocking (**request-response**), RPC-like messaging. |
| `emit`  | Asynchronous messaging without response.             |
| `close` | Closes event bus subscribers.                        |

## Example

Let's build a simple event-based app that demonstrates how to dispatch commands from an endpoint and process them in a command handler.

{% tabs %}
{% tab title="user.command.ts" %}

```typescript
import { event } from '@marblejs/core';
import * as t from 'io-ts';

export enum UserCommandType {
  CREATE_USER = 'CREATE_USER',
};

export const CreateUserCommand =
  event(UserCommandType.CREATE_USER)(t.type({
    firstName: t.string,
    lastName: t.string,
  }));
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="user.event.ts" %}

```typescript
import { event } from '@marblejs/core';
import * as t from 'io-ts';

export enum UserEventType {
  USER_CREATED = 'USER_CREATED',
};

export const UserCreatedEvent =
  event(UserEventType.USER_CREATED)(t.type({
    id: t.string,
  }));
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="createUser.effect.ts" %}

```typescript
import { act, useContext, matchEvent } from '@marblejs/core';
import { reply, MsgEffect } from '@marblejs/messaging';
import { eventValidator$ } from '@marblejs/middleware-io';
import { mergeMap } from 'rxjs/operators';
import { pipe } from 'fp-ts/lib/pipeable';
import { createUser } from './user.model';
import { CreateUserCommand } from './user.command';
import { UserCreatedEvent } from './user.event';
import { UserRespositoryToken } from './tokens';

export const createUser$: MsgEffect = (event$, ctx) => {
  const userRepository = useContext(UserRespositoryToken)(ctx.ask);

  return event$.pipe(
    matchEvent(CreateUserCommand),
    act(eventValidator$(CreateUserCommand)),
    act(event => pipe(
      event.payload,
      createUser,
      userRepository.persist,
      mergeMap(user => [
        UserCreatedEvent.create({ id: user.id }),
        reply(event)(UserCreatedEvent.create({ id: user.id })),
      ]),
    )),
  );
};
```

{% endtab %}
{% endtabs %}

The logic of the command handler is quite simple:

1. match all incoming events (commands) of specific type (`CREATE_USER`)
2. create domain object and persist via injected repository
3. notify all interested parties that user was created
4. return a confirmation back to client

{% tabs %}
{% tab title="postUser.effect.ts" %}

```typescript
import { r, HttpStatus, useContext, use } from '@marblejs/core';
import { map, mapTo, mergeMap } from 'rxjs/operators';
import { EventBusClientToken } from '@marblejs/messaging';
import { requestValidator$, t } from '@marblejs/middleware-io';
import { CreateUserCommand } from './user.commands';
import { pipe } from 'fp-ts/lib/pipeable';

const validateRequest = requestValidator$({
  body: t.type({
    firstName: t.string,
    lastName: t.string,
  }),
});

export const postUser$ = r.pipe(
  r.matchPath('/user'),
  r.matchType('POST'),
  r.useEffect((req$, ctx) => {
    const eventBusClient = useContext(EventBusClientToken)(ctx.ask);

    return req$.pipe(
      validateRequest,
      mergeMap(req => {
        const { firstName, lastName } = req.body;

        return pipe(
          CreateUserCommand.create({ firstName, lastName }),
          eventBusClient.send,
        );
      }),
      mapTo({ status: HttpStatus.CREATED }),
    );
  }));
```

{% endtab %}
{% endtabs %}

The implementation of `postUser$` effect is also very simple. First we have to inject the EventBus client from the context and map the incoming request to `CREATE_USER` command. Since we want to notify the API consumer about success or failure of operation, we have to wait for the response. In order to do that we have to dispatch an event using `send` method.

{% tabs %}
{% tab title="index.ts" %}

```typescript
import { httpListener, createServer, bindEagerlyTo } from '@marblejs/core';
import { messagingListener, EventBusToken, EventBusClientToken, eventBusClient, eventBus } from '@marblejs/messaging';
import { bodyParser$ } from '@marblejs/middleware-body';
import { logger$ } from '@marblejs/middleware-logger';
import { postUser$ } from './postUser.effect';
import { createUser$ } from './createUser.effect';

const eventBusListener = messagingListener({
  effects: [
    createUser$,
  ],
});

const listener = httpListener({
  middlewares: [
    logger$(),
    bodyParser$(),
  ],
  effects: [
    postUser$,
  ],
});

export const server = createServer({
  listener,
  dependencies: [
    bindEagerlyTo(EventBusClientToken)(eventBusClient),
    bindEagerlyTo(EventBusToken)(eventBus({ listener: eventBusListener })),
  ],
});

const main: IO<void> = async () =>
  await (await server)();

main();
```

{% endtab %}
{% endtabs %}


# WebSockets

@marblejs/websockets module implements the RFC 6455 WebSocket protocol, providing full-duplex communication channels over a single TCP connection.

## Installation

```bash
$ yarn add @marblejs/websockets @marblejs/core rxjs fp-ts
```

## Bootstrapping

Like [*httpListener*](/docs/v3/other/api-reference/core/core-httplistener) \_\_the WebSocket module defines a similar way of bootstrapping the app.

{% tabs %}
{% tab title="webSocket.listener.ts" %}

```typescript
import { webSocketListener } from '@marblejs/websockets';

const effects = [
  effect1$,
  effect2$,
  // ...
];

const middlewares = [
  middleware1$,
  middleware2$,
  // ...
];

export const listener = webSocketListener({ effects, middlewares });
```

{% endtab %}
{% endtabs %}

To create WebSocket app instance, we can use `createWebSocketServer`, which is a wrapper around `ws` server creator. When created, it won't automatically start listening to given port and hostname until you call its awaited instance.

{% tabs %}
{% tab title="index.ts" %}

```typescript
import { createWebSocketServer } from '@marblejs/websockets';
import { IO } from 'fp-ts/lib/IO';
import { listener } from './webSocket.listener';

const webSocketServer = createWebSocketServer({
  options: {
    port: 1337,
    host: '127.0.0.1',
  }, 
  listener,
});

const main: IO<void> = async () =>
  await (await webSocketServer)();

main();
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
If you are curious about other ways of server bootstrapping, reach out the HTTP [Server events](/docs/v3/http/advanced/server-events) chapter.
{% endhint %}

## Effects

Marble.js defines a common interface for many different kinds Effects. In case of **@marblejs/websockets**, the module defines a `WsEffect` which works within WebSocket protocol and deals with streams of Events. The very basic implementation of WebSocket Effect can look like in the code snipped below.

{% tabs %}
{% tab title="hello.effect.ts" %}

```typescript
import { matchEvent } from '@marblejs/core';
import { WsEffect } from '@marblejs/websockets';
import { mapTo } from 'rxjs/operators';

export const hello$: WsEffect = event$ =>
  event$.pipe(
    matchEvent('HELLO'),
    mapTo({ type: 'HELLO', payload: 'Hello, world!' }),
  );
```

{% endtab %}
{% endtabs %}

Like any other Effect, it is just a function which returns a stream of outgoing events. The Effect above responds to *HELLO* events with `Hello, world!` message. In case of default `WsEffect` interface, each incoming event has to be mapped to an outgoing [event](/docs/v3/messaging/core-concepts/events) which is just an object with **type** and **payload** attributes.

Lets do some cool math! In the next example we will try to build a very basic calculator using only streams! For the example purpose we will only need two Effects: the first that will match *ADD* events and the second that will match *SUM* events.

{% tabs %}
{% tab title="calculator.effect.ts" %}

```typescript
import { use, matchEvent } from '@marblejs/core';
import { WsEffect } from '@marblejs/websockets';
import { t, eventValidator$ } from '@marblejs/middleware-io';
import { buffer, map } from 'rxjs/operators';

export const sum$: WsEffect = event$ =>
  event$.pipe(
    matchEvent('SUM'),
  );

export const add$: WsEffect = (event$, ...args) =>
  event$.pipe(
    matchEvent('ADD'),
    use(eventValidator$(t.number)),
    buffer(sum$(event$, ...args)),
    map(events => events.reduce((a, e) => e.payload + a, 0)),
    map(payload => ({ type: 'SUM_RESULT', payload })),
  );
```

{% endtab %}
{% endtabs %}

In the example above we did a little bit of RxJS magic using `buffer` operator, which buffers the source Observable values until closing notifier emits (in this case `sum$`). Additionally, to be sure that incoming *ADD* events are sent with payload of type number, we used [@marblejs/middleware-io](/docs/v3/other/api-reference/middleware-io) validator, which is able to infer payload type from defined schema.

Lets examine in steps how the server will respond to given equation: $$7 + 3 + 1$$

```javascript
// #1 sent to server
{
  "type": "ADD",
  "payload": 7
}

// #2 sent to server
{
  "type": "ADD",
  "payload": 3
}

// #3 sent to server
{
  "type": "ADD",
  "payload": 1
}

// #4 sent to server
{
  "type": "SUM",
}

// #5 response from server
{
  "type": "SUM_RESULT",
  "payload": 11
}
```


# HTTP routes testing

@marblejs/testing is a tool agnostic module for testing Marble.js apps.

### Installation

To get started simply install testing module in your project as a **dev dependency.** You can use any testing framework that you like, but for example purposes will show and stick to **Jest** testing environment.

```bash
$ yarn add --dev @marblejs/testing
```

### HttpTestBed

In order to test Marble.js HTTP APIs you have to create a TestBed instance. It is a primary API with a role to configure and initialize environment for testing, overriding and injecting bound dependencies. For HTTP protocol specific use cases we will use `createHttpTestBed` factory function. In case of `HttpTestBed` type you have to provide a required HTTP listener instance and optionally default headers that will be applied for each tested request.

{% tabs %}
{% tab title="test.setup.ts" %}

```typescript
import { createHttpTestBed } from '@marblejs/testing';
import { listener } from './http.listener';

const httpTestBed = createHttpTestBed({
  listener,
  defaultHeaders: {
    ...
  },
});


// then ...


describe('user$', () => {

  test('POST "/api/v1/user" creates user', async () => {
    const dependencies = [ ... ];
    const { request, finish, ask } = await httpTestBed(dependencies);

    // 1. initialize testing environment...
    // 2. prepare and send test request...
    // 3. assert recieved response...
    // 4. ... and close connection
    
    await finish();
  });

);
```

{% endtab %}
{% endtabs %}

You can inject any bound dependencies to the TestBed constructor and ask for them eg. via `useContext` hook function.

Usually testing HTTP APIs is very repetitive - you have to create a TestBed instance, provide all basic dependencies, send a request, assert the response and finish (close) hanging test connection. In order to make things simple and more DRY, **@marblejs/testing** defines a useful function for defining a test setup that you can refer to in any `*.spec` file, which can save a lot of unnecessary boilerplate for defining test environment. All you have to do is to pass previously defined TestBed instance to `createTestBedSetup` function and define a default set of dependencies that later on can be overridden in test cases. Additionally you can define a set of cleanups that will be triggered on close/finish. We will go back to this topic later.

{% tabs %}
{% tab title="test.setup.ts" %}

```typescript
import { bindTo } from '@marblejs/core';
import { createHttpTestBed, createTestBedSetup } from '@marblejs/testing';
import { listener } from './http.listener';
import { UserDaoToken, UserDao } from './user.dao';
import { UserRepositoryToken, UserRepository } from './user.repository';

const testBed = createHttpTestBed({
  listener,
  defaultHeaders: {
    ...
  },
}),

export const useTestBedSetup = createTestBedSetup({
  testBed,
  dependencies: [
    bindTo(UserDaoToken)(UserDao),
    bindTo(UserRepositoryToken)(UserRepository),
    ...
  ],
  cleanups: [ ... ],
});
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="user.effect.spec.ts" %}

```typescript
import { pipe } from 'fp-ts/lib/pipeable';
import { useTestBedSetup } from './test.setup';

describe('user$', () => {
  const testBedSetup = useTestBedSetup()

  test('POST "/api/v1/user" creates user', async () => {
    const { request } = await testBedSetup.useTestBed();

    const response = await pipe(
      request('POST'),
      request.withPath('/api/v1/user'),
      request.withHeaders({ 'Authorization': 'Bearer FAKE' }),
      request.withBody({ email: 'bob@test.com' }),
      request.send,
    );

    expect(response.statusCode).toEqual(200);
    expect(response.body).toEqual({ email: 'bob@test.com' });
  });
  
  afterEach(async () => {
    await testBedSetup.cleanup();
  });

);
```

{% endtab %}
{% endtabs %}

### Dependency injection

The main role of the TestBed, besides constructing and sending test requests, is environment setup and context preparation. You can override any binding you want and ask for bound instances in order to do some pre-test preparations.&#x20;

```typescript
import { bindTo, useContext } from '@marblejs/core';
import { pipe } from 'fp-ts/lib/pipeable';
import { useTestBedSetup } from './test.setup';
import { UserDaoToken, UserDaoMock } from './user.dao';
import { UserRepositoryToken, UserRepository } from './user.repository';

describe('user$', () => {
  const testBedSetup = useTestBedSetup()

  test('POST "/api/v1/user" creates user', async () => {
  
    // override binding
    const dependencies = [
      bindTo(UserDaoToken)(UserDaoMock),
    ];
    
    const { request, ask } = await testBedSetup.useTestBed(dependencies);
    
    // access bound instances 
    const userRepository = useContext(UserRepositoryToken)(ask);
    ...

    const response = await pipe(
      request('POST'),
      request.withPath('/api/v1/user'),
      request.withHeaders({ 'Authorization': 'Bearer FAKE' }),
      request.withBody({ email: 'bob@test.com' }),
      request.send,
    );

    expect(response.statusCode).toEqual(200);
    expect(response.body).toEqual({ email: 'bob@test.com' });
  });
  
  afterEach(async () => {
    await testBedSetup.cleanup();
  });

);
```

### Constructing test request

Marble.js defines similar pipeable API as for constructing HTTP routes. It defines a set of useful functions for building and sending a request in a functional way.

```
request :: HttpMethod -> HttpTestBedRequest
```

```
withPath :: string -> HttpTestBedRequest -> HttpTestBedRequest
```

```haskell
withHeaders :: HttpHeaders -> HttpTestBedRequest -> HttpTestBedRequest
```

```haskell
withBody :: Body -> HttpTestBedRequest -> HttpTestBedRequest & WithBodyApplied
```

```haskell
send :: HttpTestBedRequest -> Promise HttpTestBedRequest
```

```typescript
// const { request } = await testBedSetup.useTestBed();
// const { request } = await httpTestBed();
    
const response = await pipe(
  request('POST'),
  request.withPath('/api/v1/user'),
  request.withHeaders({ 'Authorization': 'Bearer FAKE_TOKEN' }),
  request.withBody({ email: 'bob@test.com' }),
  request.send,
);

typeof response === HttpTestBedResponse {
  req: HttpTestBedRequest<any>;
  metadata: TestingMetadata;
  statusCode: HttpStatus;
  statusMessage?: string;
  headers: HttpHeaders;
  body?: any;
}
```

### Cleanups

Sometimes there is a need to do some cleanup stuff after each test. Of course, you can inject and close all hanging connections manually for each dependency that requires it, but as you probably know\... it is not a best idea. Marble.js cannot automagically close all established connections that bound dependencies created, but you can instruct TestBedSetup by defining a set of cleanups to trigger a desired job after finish.

Let's assume that we have some custom dependency that their interface defines an async `close` method.

{% tabs %}
{% tab title="custom.reader.ts" %}

```typescript
interface CustomDependency {
  ...
  close: () => Promise<void>,
};

export const CustomDependency = createReader(_ => ... );

export const CustomDependencyToken = createContextToken<CustomDependency>('CustomDependency');
```

{% endtab %}
{% endtabs %}

In order to create a `DependencyCleanup` you have to provide a lookup (context) token and implement a cleanup method that will return a promise.

```typescript
import { bindTo } from '@marblejs/testing';
import { DependencyCleanup, createTestBedSetup } from '@marblejs/testing';
import { listener } from './http.listener';
import { CustomDependency, CustomDependencyToken } from './custom.reader';

const customDependencyCleanup: DependencyCleanup<CustomDependency> = {
  token: CustomDependencyToken,
  cleanup: dep => dep.close(),
};

const testBed = createHttpTestBed({ listener }),

export const useTestBedSetup = createTestBedSetup({
  testBed,
  dependencies: [
    bindTo(CustomDependencyToken)(CustomDependency),
    ...
  ],
  cleanups: [
    customDependencyCleanup,
    ...
  ],
});
```


# How does it glue together?

Writing REST API in Marble.js isn't hard as you might think. The developer has to understand mostly only the main building block which is the Effect and how the data flows through it.

The aim of this chapter is to demonstrate how building blocks described in previous chapters glue together. For ease of understanding, lets build a tiny RESTful API for user handling. Lets omit the implementation details of database access and focus only on the Marble.js related things.

```typescript
import { createServer, combineRoutes, httpListener, r, HttpError, use, HttpStatus } from '@marblejs/core';
import { logger$ } from '@marblejs/middleware-logger';
import { bodyParser$ } from '@marblejs/middleware-body';
import { requestValidator$, t } from '@marblejs/middleware-io';
import { catchError, mergeMapTo, mergeMap, mapTo, map } from 'rxjs/operators';
import { of, throwError, from } from 'rxjs';
import { IO } from 'fp-ts/lib/IO';
import { pipe } from 'fp-ts/lib/pipeable';

/*------------------------
  👇 utility functions
-------------------------*/

const getUserCollection = () =>
  from([{ id: '1' }]);

const getUserById = (id: string) =>
  id === '1'
    ? of({ id: '1', name: 'Test' })
    : throwError(new Error('User not found'));

/*------------------------
  👇 USERS API definition
-------------------------*/

const validator$ = requestValidator$({
  params: t.type({
    id: t.string,
  }),
});

const getUserList$ = r.pipe(
  r.matchPath('/'),
  r.matchType('GET'),
  r.useEffect(req$ => req$.pipe(
    mergeMap(getUserCollection),
    map(body => ({ body })),
  )),
);

const getUser$ = r.pipe(
  r.matchPath('/:id'),
  r.matchType('GET'),
  r.useEffect(req$ => req$.pipe(
    use(validator$),
    mergeMap(req => pipe(
      getUserById(req.params.id),
      catchError(() => throwError(
        new HttpError('User does not exist', HttpStatus.NOT_FOUND)
      ))
    )),
    map(body => ({ body })),
  )),
);

const users$ = combineRoutes('/users', [
  getUser$,
  getUserList$,
]);


/*------------------------
  👇 ROOT API definition
-------------------------*/

const root$ = r.pipe(
  r.matchPath('/'),
  r.matchType('GET'),
  r.useEffect(req$ => req$.pipe(
    mapTo({ body: `API version: v1` }),
  )),
);

const api$ = combineRoutes('/api/v1', [
  root$,
  users$,
]);


/*------------------------
  👇 SERVER definition
-------------------------*/

const middlewares = [
  logger$(),
  bodyParser$(),
];

const effects = [
  api$,
];

const server = createServer({
  port: 1337,
  listener: httpListener({ middlewares, effects }),
});

const main: IO<void> = async () =>
  await (await server)();

main();
```


# Migration guides

This chapter provides a set of guidelines to help you migrate across Marble.js major releases,

It is hard to build a framework or big library that preserves the backward compatibility in every aspect from the very first iterations. We are still learning from release to release and want to deliver the best developer experience as possible without breaking changes, but as you know, it is not so simple. Sometimes you just find a better way of approaching the problem. Your point of view/perspective shifts as you mature as a developer — striving for perfection.

{% content-ref url="/pages/-M-RdyMDrSCSoT\_Y4v8f" %}
[Migration from version 2.x](/docs/v3/other/migration-guides/version-2)
{% endcontent-ref %}

{% content-ref url="/pages/-LXydGnyzBdwrEXMzDzm" %}
[Migration from version 1.x](/docs/v3/other/migration-guides/version-1)
{% endcontent-ref %}


# Migration from version 2.x

This chapter provides a set of guidelines to help you migrate from Marble.js version 2.x to the latest 3.x version.

The newest iteration comes with some API breaking change, but don’t worry, these are not game-changers, but rather convenient improvements that open the doors to new future possibilities. During the development process, the goal was to notify and discuss incoming changes within the community as early as possible. You can check here [what has changed since the latest version](https://github.com/marblejs/marble/issues/172).

## @marblejs/core

### fp-ts

`fp-ts@2.x` is a required peer dependency (next to `rxjs`)

{% content-ref url="/pages/-M-RbrBxxSSFYcBpIXZs" %}
[Installation](/docs/v3/getting-started/installation)
{% endcontent-ref %}

### Context API

`fp-ts@2.x` introduced changes that have a major impact to Context API (eg. Reader monad).

Version 3.0 introduces more explicit dependency binding. Previous API wasn't so precise, which could result to confusion, eg. when the dependency is lazily/eagerly evaluated.

{% content-ref url="/pages/-M-Rcrwhon3AXAhlHklH" %}
[Context](/docs/v3/http/context)
{% endcontent-ref %}

**❌ Old:**

```typescript
import { bindTo } from '@marblejs/core';

// eager
bindTo(WsServerToken)(websocketsServer.run),

// lazy
bindTo(WsServerToken)(websocketsServer),
```

**✅ New:**

```typescript
import { bindTo, bindLazilyTo, bindEagerlyTo } from '@marblejs/core';

// eager
bindEagerlyTo(WsServerToken)(websocketsServer),

// lazy
bindTo(WsServerToken)(websocketsServer),
bindLazilyTo(WsServerToken)(websocketsServer),
```

### Readers

**❌ Old:**

```typescript
import { reader } from '@marblejs/core';

const foo = reader.map(ctx => {
  // ...
});
```

**✅ New:**

You can create context readers via raw Reader monad composition (using available fp-ts toolset) or using `createReader` utility function that saves a lot of unnecessary boilerplate.

```typescript
import { createReader, reader } from '@marblejs/core';
import { pipe } from 'fp-ts/lib/pipeable';
import { map } from 'fp-ts/lib/Reader';

const foo1 = pipe(reader, map(ctx => {
  // ...
}));

// or much simpler

const foo2 = createReader(ctx => {
  // ...
});
```

### Server creators

The release of fp-ts also had an impact to HTTP and WebSocket server creators. `run()` method on Reader, etc. has been replaced with **IO** thunk. Additionally all server creators are promisified, which means that they will return an instance only when started listening. The change applies to all main modules: `@marblejs/core`, `@marblejs/websockets`, `@marblejs/messaging`. More info you can find in PR [#198](https://github.com/marblejs/marble/pull/198)

Bootstrapping:

**❌ Old:**

```typescript
const server = createServer({
  // ...
});

server.run();
```

**✅ New:**

```typescript
const server = createServer({
  // ...
});

await (await server)();
```

Unified config interfaces for all kind of server creators:

{% tabs %}
{% tab title="websockets" %}

```typescript
import { createWebSocketServer, webSocketListener } from '@marblejs/websockets';

const webSocketServer = createWebSocketServer({
  // ...
  listener: webSocketListener({
    middlewares: [...],
    effects: [...],
  }),
});
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="http" %}

```typescript
import { createServer, httpListener } from '@marblejs/core';

const server = createServer({
  // ...
  listener: httpListener({
    middlewares: [...],
    effects: [...],
  }),
});
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="messaging" %}

```typescript
import { createMicroservice, messagingListener } from '@marblejs/messaging';

const microservice = createMicroservice({
  // ...
  listener: messagingListener({
    middlewares: [...],
    effects: [...],
  }),
});
```

{% endtab %}
{% endtabs %}

### **Effect**

Marble.js v2.0 `Effect` interface defines three arguments where the second one is used for accessing contextual client, eg. *HttpResponse*, *WebSocketClient*, etc. Typically the second argument was not used very often. That's why in the next major version client parameter moves to context object. It results in reduced available number of parameters from 3 to 2.

{% hint style="info" %}
The change applies to all Effect interfaces, eg. `HttpEffect`, `WsEffect`, `MsgEffect`
{% endhint %}

**❌ Old:**

```typescript
const foo$: WsEffect = (event$, client, meta) =>
  event$.pipe(
    matchEvent('FOO'),
    // meta.ask       ---    context reader
  );
```

**✅ New:**

```typescript
const foo$: WsEffect = (event$, ctx) =>
  event$.pipe(
    matchEvent('FOO'),
    // ctx.client    ---    contextual client
    // ctx.ask       ---    context reader
  );
```

This change also implies a much cleaner base `Effect` interface:

```typescript
interface Effect<I, O, Client> {
  (input$: Observable<I>, ctx: EffectContext<Client>): Observable<O>;
}

interface EffectContext<T, U extends SchedulerLike = SchedulerLike> {
  ask: ContextProvider;
  scheduler: U;
  client: T;
}
```

With that change the last argument of Effect interface is no more called as `EffectMetadata` but rather as `EffectContext`.

### ErrorEffect

When dealing with error or output Effect, the developer had to use the attribute placed in the third effect argument. In Marble.js v3.0 the thrown error is passed to stream directly.

**❌ Old:**

```typescript
const error$: HttpErrorEffect<HttpError> = (req$, client, { error }) =>
  req$.pipe(
    map(req => {
      // ...
    }),
  );
```

**✅ New:**

```typescript
const error$: HttpErrorEffect<HttpError> = req$ =>
  req$.pipe(
    map(({ req, error }) => {
      // ...
    }),
  );
```

### OutputEffect

**❌ Old:**

```typescript
const output$: HttpOutputEffect = (res$, client, { initiator }) =>
  res$.pipe(
    map(res => {
      // ...
    }),
  );
```

**✅ New:**

```typescript
const output$: HttpOutputEffect = res$ =>
  res$.pipe(
    map(({ req, res }) => {
      // ...
    }),
  );
```

### HttpRequest

The HttpResponse object is no more carried separately but together with correlated HttpRequest.

```typescript
interface HttpRequest {
  url: string;
  method: HttpMethod;
  body: Body;
  params: Params;
  query: Query;
  response: HttpResponse;     // 👈 
}
```

```typescript
const effect$ = r.pipe(
  r.matchPath('/'),
  r.matchType('GET'),
  r.useEffect((req$, ctx) => req$.pipe(
    map(req => ...),
    // req.response -- HttpResponse object
    // ctx.client -- HttpServer object
  )));
```

## @marblejs/middleware-logger

The newest implementation of logger middleware uses underneath the pluggable Logger dependency, so dedicated log streaming is unnecessary. The developer can simply override default Logger binding and forward the incoming logs on his own. Also, since `HttpRequest` contains the response object attached to it - `res` attribute is redundant.

{% content-ref url="/pages/-M-WmDVZ0c-PhwiefmFn" %}
[Logging](/docs/v3/http/advanced/logging)
{% endcontent-ref %}

**❌ Old:**

```typescript
interface LoggerOptions {
  silent?: boolean;
  stream?: WritableLike;
  filter?: (res: HttpResponse, req: HttpRequest) => boolean;
}
```

**✅ New:**

```typescript
interface LoggerOptions {
  silent?: boolean;
  filter?: (req: HttpRequest) => boolean;
}
```


# Migration from version 1.x

This chapter provides a set of guidelines to help you migrate from Marble.js version 1.x to version 2.x.

If you are new to Marble.js, starting with 2.x is easy-peasy. The biggest question for current 1.x users though, is how to migrate to the new version. You can ask, how many of the API has changed? Just relax — about 90% of the API is the same and the core concepts haven’t changed.&#x20;

## @marblejs/core

### Type declarations

**#** `Effect`  👉 `HttpEffect`

\# `EffectResponse` 👉 `HttpEffectResponse`

**#** `Middleware`   👉 `HttpMiddlewareEffect`

**#** `ErrorEffect`  👉`HttpErrorEffect`&#x20;

### Effects - body, params, query

In order to improve request type inference HTTP Effect `req.params`, `req.body`, `req.query` are by default of `unknown` type instead of `any`.

**❌ Old:**

```typescript
const example$: Effect = (req$) =>
  req$.pipe(
    map(req => req.params.version),        // (typeof req.params) = any
    map(version => `Version: ${version}`), // (typeof version) = any
    map(message => ({ body: message })),
  );
```

**✅ New:**

```typescript
const example$: HttpEffect = (req$) =>
  req$.pipe(
    map(req => req.params.version),        // (typeof req.params) = unknown
    map(version => `Version: ${version}`), // ❌ type error!
    map(message => ({ body: message })),
  );
  
👇

const example$: HttpEffect = (req$) =>
  req$.pipe(
    map(req => req.params.version),        // (typeof req.params) = unknown
    map(version => version as string),     // or use validation middleware
    map(version => `Version: ${version}`), // ✅ looks fine!
    map(message => ({ body: message })),
  );
```

### Effects - third argument

From version 2.0 the effect function third argument is a common `EffectMetadata` object which can contain eventual error object or contextual injector.

**❌ Old:**

```typescript
const error$: ErrorEffect = (req$, _, error) =>
  req$.pipe(
    mapTo(error),
    // ...
  );
```

**✅ New:**

```typescript
const error$: HttpErrorEffect = (req$, _, meta) =>
  req$.pipe(
    mapTo(meta.error),
    // ...
  );
```

### httpListener error effect&#x20;

HTTP error effect is registered inside **httpListener** configuration object via `error$` instead of `errorEffect`.

**❌ Old:**

```typescript
export default httpListener({
  // ...
  errorEffect: // ...
});
```

**✅ New:**

```typescript
export default httpListener({
  // ...
  error$: // ...
});
```

### httpListener server bootstrapping

In order to use `httpListener` directly connected to Node.js `http.createServer` you have to run and apply Reader context firs&#x74;**.**

**❌ Old:**

```typescript
import { createContext } from '@marblejs/core';
import * as http from 'http';
import httpListener from './http.listener';
  
const server = http
  .createServer(httpListener)
  .listen(1337);
```

**✅ New:**

* **direct usage**

```typescript
import { createContext } from '@marblejs/core';
import * as http from 'http';
import httpListener from './http.listener';

const httpListenerWithContext = httpListener
  .run(createContext());
  
const server = http
  .createServer(httpListenerWithContext)
  .listen(1337);
```

* **using `createServer`**&#x20;

```typescript
import { createContext, createServer } from '@marblejs/core';
import httpListener from './http.listener';

const server = createServer({
  port: 1337,
  httpListener,
});

server.run();
```

## @marblejs/middleware-body

Every body parsing middleware should be registered via function invocation. It allows you to pass an optional middleware configuration object.&#x20;

**❌ Old:**

```typescript
import { bodyParser$ } '@marblejs/middleware-body';

httpListener({
  middlewares: [bodyParser$],
  // ...
});
```

**✅ New:**

```typescript
import { bodyParser$ } '@marblejs/middleware-body';

httpListener({
  middlewares: [bodyParser$()],
  // ...
});
```

## @marblejs/middleware-logger

Because previous `logger$` wasn't exposed as a function, it was very hard to extend it. Version 1.2.0 deprecated it in favor of `loggerWithOpts$` entry point which was more maintainable and could be extended easier. From the version **v2.x** the `logger$` entry point is be swapped with `loggerWithOpts$` implementation.

**❌ Old:**

```typescript
import { logger$, loggerWithOpts$ } '@marblejs/middleware-logger';

httpListener({
  middlewares: [
    logger$,
    // or
    loggerWithOpts$(),
  ],
  // ...
});
```

**✅ New:**

```typescript
import { bodyParser$ } '@marblejs/middleware-body';

httpListener({
  middlewares: [logger$()],
  // ...
});
```


# API reference

The complete API reference will be available soon.

![Soon...](/files/-M0OZl-N_3ClgSVnYnyM)


# core

This section documents the complete @marblejs/core package API.

![Soon...](/files/-M0OZl-N_3ClgSVnYnyM)


# bindTo

Binds injection token to lazy dependency.

### **Importing** <a href="#importing" id="importing"></a>

```typescript
import { bindTo, bingLazilyTo } from '@marblejs/core';
```

### **Type declaration**

```
bindTo ::  ContextToken -> ContextReader -> BoundDependency
bindLazilyTo ::  bindTo
```

The function is responsible for binding context token to `ContextReader` which can be a **fp-ts** `Reader` instance or plain a `() => T`. The function is producing a lazy binding, which means that, the dependency will be evaluated on it's first call (injection).

`bindTo` is an alias of `bindLazilyTo`.&#x20;

### **Example**

```typescript
import { reader, bindTo, createServer, createContextToken } from '@marblejs/core';
import { pipe } from 'fp-ts/lib/pipeable';
import * as R from 'fp-ts/lib/Reader';

// create reader

const FooToken = createContextToken<Foo>('FooToken');

const foo = pipe(reader, R.map(ask => {
  const otherDependency = ask(OtherToken);
  
  return { ... };
});


// bind reader to token

const boundDependency = bindTo(FooToken)(foo);
```


# bindEagerlyTo

Binds injection token to eager dependency.

### **Importing** <a href="#importing" id="importing"></a>

```typescript
import { bindEagerlyTo } from '@marblejs/core';
```

### **Type declaration**

```
bindEagerlyTo ::  ContextToken -> ContextReader -> BoundDependency

```

The function is responsible for binding context token to `ContextReader` which can be a **fp-ts** `Reader` instance or plain **sync/async** `() => T`. The function is producing a eager binding, which means that, the dependency will be evaluated on startup.

### **Example**

```typescript
import { reader, bindEagerlyTo, createServer, createContextToken } from '@marblejs/core';
import { pipe } from 'fp-ts/lib/pipeable';
import * as R from 'fp-ts/lib/Reader';

// create sync reader

const FooSyncToken = createContextToken<ReturnType<typeof fooSync>>('FooSyncToken');

const fooSync = pipe(reader, R.map(ask => {
  const otherDependency = ask(OtherToken);
  
  return { ... };
});

// create async reader

const FooAsyncToken = createContextToken<ReturnType<typeof fooSync>>('FooSyncToken');

const fooAsync = pipe(reader, R.map(async ask => {
  const otherDependency = ask(OtherToken);
  
  return { ... };
});


// bind readers to tokens

const boundSyncDependency  = bindEagerlyTo(FooSyncToken)(fooSync);
const boundAsyncDependency = bindEagerlyTo(FooAsyncToken)(fooAsync);

```


# createEvent

![Soon...](/files/-M0OZl-N_3ClgSVnYnyM)


# createServer

Creates HTTP server

### I**mporting**

```typescript
import { createServer } from '@marblejs/core';
```

### **Type declaration**

```haskell
createServer ::  CreateServerConfig -> () -> Promise<ServerIO<HttpServer>>
```

### **Parameters**

| *parameter* | definition           |
| ----------- | -------------------- |
| *config*    | `CreateServerConfig` |

#### ***CreateServerConfig***

| *parameter*    | definition                                |
| -------------- | ----------------------------------------- |
| *listener*     | `HttpListener`                            |
| *port*         | \<optional> `number`                      |
| *hostname*     | \<optional> `string`                      |
| *event$*       | \<optional> `HttpServerEffect`            |
| *options*      | \<optional> `ServerOptions`               |
| *dependencies* | \<optional> `Array<BoundDependency<any>>` |

### Returns

`ServerIO<HttpServer>is`&#x20;

### **Example**

```typescript
import { IO } from 'fp-ts/lib/IO';
import { listener } from './http.listener';
import { createServer, bindTo } from '@marblejs/core';

const httpsOptions: https.ServerOptions = {
  key: fs.readFileSync('key.pem'),
  cert: fs.readFileSync('cert.pem'),
};

const server = createServer({
  port: 1337,
  hostname: '127.0.0.1',
  httpListener,
  dependencies: [
    bindTo(fooToken)(foo),
  ],
  event$: (...args) => merge(
    listening$(...args),
    upgrade$(...args),
  ),
  options: { httpsOptions },
});

const main: IO<void> = async () =>
  await (await server)();

main();
```


# combineRoutes

Combines routing for different Effects, prefixed with path passed as a first argument.

### **Importing**

```typescript
import { combineRoutes } from '@marblejs/core';
```

### **Type declaration**

```
combineRoutes :: (string, RouteCombinerConfig) -> RouteEffectGroup
combineRoutes :: (string, (RouteEffect | RouteEffectGroup)[]) -> RouteEffectGroup
```

### **Parameters**

| *parameter*       | definition                                                      |
| ----------------- | --------------------------------------------------------------- |
| *path*            | `string`                                                        |
| *configOrEffects* | `RouteCombinerConfig \| Array<RouteEffect \| RouteEffectGroup>` |

#### ***RouteCombinerConfig***

| *parameter* | definition                                |
| ----------- | ----------------------------------------- |
| effects     | `Array<RouteEffect \| RouteEffectGroup>`  |
| middlewares | \<optional> `Array<HttpMiddlewareEffect>` |

### Returns

Factorized `RouteEffectGroup` object.

### Example

{% tabs %}
{% tab title="user.effects.ts" %}

```typescript
import { combineRoutes } from '@marblejs/core';
import { authorize$ } from 'auth.middleware';

// const getUsers$ = ...
// const postUser$ = ...

export const user$ = combineRoutes('/user', {
  middlewares: [authorize$],
  effects: [getUsers$, postUser$],
});
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="api.effects.ts" %}

```typescript
import { combineRoutes } from '@marblejs/core';
import { user$ } from './user.effects';

// const root$ = ...
// const notFound$ = ...

export const api$ = combineRoutes('/api/v1', [
  root$,
  user$,
  notFound$,
]);
```

{% endtab %}
{% endtabs %}


# createContextToken

A lookup token associated with a dependency provider, for use with the Marble.js context system.

### **Importing** <a href="#importing" id="importing"></a>

```typescript
import { createContextToken } from '@marblejs/core';
```

### **Type declaration**

```
createContextToken :: () -> ContextToken
createContextToken :: string -> ContextToken
```

### **Example**

The following example creates and associates injection token with Marble.js WebSocket server.

```typescript
import { createContextToken } from '@marblejs/core';
import { WebSocketServerConnection } from '@marblejs/websockets';

const WebSocketServerToken =
    createContextToken<WebSocketServerConnection>('WebSocketServerToken');
```

{% hint style="info" %}
Always remember add a string name for created lookup token.&#x20;
{% endhint %}


# EffectFactory

Set of factory functions for building router Effect.

{% hint style="warning" %}
**Deprecation warning**

With an introduction of Marble.js 3.0, old `EffectFactory` HTTP route builder is deprecated. Please use[`r.pipe`](/docs/v3/other/api-reference/core/r.pipe) builder instead.
{% endhint %}

## **Importing**

```typescript
import { EffectFactory } from '@marblejs/core';
```

## **`matchPath`**

`EffectFactory` namespace function. Matches request path for connected *Effect*.

### **Type declaration**

```typescript
matchPath :: string -> matchType
```

### **Parameters**

| *parameter* | definition |
| ----------- | ---------- |
| *path*      | `string`   |

### Returns

EffectFactory `matchType` function

## **`matchType`**

`EffectFactory` namespace function. Matches HTTP method type for connected *Effect*.

### **Type declaration**

```typescript
matchType :: HttpMethod -> use
```

### **Parameters**

| *parameter* | definition                                                                                                          |
| ----------- | ------------------------------------------------------------------------------------------------------------------- |
| *type*      | `HttpMethod = 'POST \| 'PUT' \| 'PATCH' \| 'GET' \| 'HEAD' \| 'DELETE' \| 'CONNECT' \| 'OPTIONS' \| 'TRACE' \| '*'` |

### Returns

EffectFactory *`use`* function

## **`use`**

`EffectFactory` namespace function. Connects *Effect* with path and HTTP method type.

### **Type declaration**

```typescript
use :: HttpEffect -> RouteEffect
```

### **Parameters**

| *parameter* | definition            |
| ----------- | --------------------- |
| *effect*    | `HttpEffect` function |

### Returns

Factorized `RouteEffect` object.

## Example

{% tabs %}
{% tab title="root.effect.ts" %}

```typescript
import { EffectFactory } from '@marblejs/core';
import { mapTo } from 'rxjs/operators';

export const root$ = EffectFactory
  .matchPath('/')
  .matchType('GET')
  .use(req$ => req$.pipe(
    mapTo({ body: `Hello, world! 👻` })
  ));
```

{% endtab %}
{% endtabs %}


# r.pipe

HttpEffect route builder based on IxMonad

## **Importing**

```typescript
import { r } from '@marblejs/core';
```

## `pipe`

`r` namespace function. Creates pipeable *RouteEffect* builder.

### **Type declaration**

```typescript
pipe :: ...Arity<IxBuilder, IxBuilder> -> RouteEffect
```

{% hint style="danger" %}
`r.pipe` builder pays attention to the order of applied operators.
{% endhint %}

```typescript
const example$ = r.pipe(
  r.matchPath('/'),
  r.matchType('GET'),
  r.use(middleware_1$),
  r.useEffect(req$ => req$.pipe(
    // ...
  )),
  r.use(middleware_2$), // ❌ type error!
);

// or 

const example$ = r.pipe(
  r.matchType('GET'),
  r.matchPath('/'), // ❌ type error!
  r.use(middleware_1$),
  r.use(middleware_2$), 
  r.useEffect(req$ => req$.pipe(
    // ...
  )),
);
```

**Correct order:**

1. **`<optional> applyMeta`**
2. **`matchPath`**
3. **`matchType`**
4. **`use`** \[...]
5. **`useEffect`**
6. **`applyMeta`** \[...]

## **`matchPath`**

`r` namespace function. Matches request path for connected *HttpEffect*.

### **Type declaration**

```typescript
matchPath :: string -> IxBuilder -> IxBuilder
```

### **Parameters**

| *parameter* | definition |
| ----------- | ---------- |
| *path*      | `string`   |

## **`matchType`**

`r` namespace function. Matches HTTP method type for connected *HttpEffect*.

### **Type declaration**

```typescript
matchType :: HttpMethod -> IxBuilder -> IxBuilder
```

### **Parameters**

| *parameter* | definition   |
| ----------- | ------------ |
| *path*      | `HttpMethod` |

## `use`

`r` namespace function. Registers HTTP middleware with connected *HttpEffect.*

### **Type declaration**

```typescript
use :: HttpMiddlewareEffect -> IxBuilder -> IxBuilder
```

### **Parameters**

| *parameter*  | definition             |
| ------------ | ---------------------- |
| *middleware* | `HttpMiddlewareEffect` |

## `useEffect`

`r` namespace function. Registers *HttpEffect.*

### **Type declaration**

```typescript
useEffect :: HttpEffect -> IxBuilder -> IxBuilder
```

### **Parameters**

| *parameter* | definition   |
| ----------- | ------------ |
| *effect*    | `HttpEffect` |

## `applyMeta`

`r` namespace function. Applies metadata to connected *HttpEffect*.

### **Type declaration**

```typescript
applyMeta :: RouteMeta -> IxBuilder -> IxBuilder
```

### **Parameters**

| *parameter* | definition  |
| ----------- | ----------- |
| meta        | `RouteMeta` |

`RouteMeta` attributes:

| parameter     | type                  | definition                                              |
| ------------- | --------------------- | ------------------------------------------------------- |
| `name`        | \<optional> `string`  | route/effect name                                       |
| `continuous`  | \<optional> `boolean` | enables [continuous mode](/docs/v3/http/advanced/modes) |
| `overridable` | \<optional> `boolean` | if true, the route can be overrode by another route     |

## Example

```typescript
import { r } from '@marblejs/core';

const example$ = r.pipe(
  r.applyMeta({ continuous: true }),
  r.matchPath('/'),
  r.matchType('GET'),
  r.use(middleware_1$),
  r.use(middleware_2$),
  r.useEffect(req$ => req$.pipe(
    // ...
  )),
  r.applyMeta({ meta_1: /* ... */ }),
  r.applyMeta({ meta_1: /* ... */ }),
);
```


# httpListener

Starting point of every Marble.js application. It includes definitions of all middlewares and API effects.

### **Importing**

```typescript
import { httpListener } from '@marblejs/core';
```

### **Type declaration**

```typescript
httpListener :: HttpListenerConfig -> Reader<Context, HttpListener>
```

### **Parameters**

| *parameter* | definition           |
| ----------- | -------------------- |
| *config*    | `HttpListenerConfig` |

#### ***HttpListenerConfig***

| *parameter*   | definition                                           |
| ------------- | ---------------------------------------------------- |
| *effects*     | \<optional> `Array<RouteEffect \| RouteEffectGroup>` |
| *middlewares* | \<optional> `Array<HttpMiddlewareEffect>`            |
| *error$*      | \<optional> `HttpErrorEffect`                        |
| *output$*     | \<optional> `HttpOutputEffect`                       |

### Returns

`Reader<Context, HttpListener>`

### **Example**

{% code title="http.listener" %}

```typescript
import { httpListener } from '@marblejs/core';
import { bodyParser$ } from '@marblejs/middleware-body';
import { logger$ } from '@marblejs/middleware-logger';
import { api$ } from './api';

const middlewares = [
  logger$(),
  bodyParser$(),
];

const effects = [
  api$,
];

export const listener = httpListener({ middlewares, effects });
```

{% endcode %}


# operator: matchEvent

Effect operator for matching incoming events.

### Importing

```typescript
import { matchEvent } from '@marblejs/core';
```

### **Type declaration**

```typescript
matchEvent :: (EventLike | EventCreator) -> Observable<Event> -> Observable<Event>
```

### Example

***WsEffect:***

```typescript
import { matchEvent } from '@marblejs/core';
import { WsEffect } from '@marblejs/websockets';
import { map } from 'rxjs/operators';

const add$: WsEffect = event$ =>
  event$.pipe(
    matchEvent('ADD'),
    map(event => event.payload), // (typeof payload) = unknown
    // ...
  );
```

***HttpServerEffect:***

```typescript
import { matchEvent, HttpServerEffect, ServerEvent } from '@marblejs/core';
import { map } from 'rxjs/operators';

const listening$: HttpServerEffect = event$ =>
  event$.pipe(
    matchEvent(ServerEvent.listening),
    map(event => event.payload), // (typeof payload) = { port: number; host: string; }
    // ...
  );
```

***MsgEffect:***

```typescript
import { matchEvent, createEvent, EventsUnion } from '@marblejs/core';
import { MsgEffect } from '@marblejs/messaging';
import { map } from 'rxjs/operators';

// Commands definition

export enum AddCommandType {
  ADD = 'ADD',
};

export const AddCommand = {
  add: createEvent(
    AddCommandType.ADD,
    (val: number) => ({ val }),
  ),
};

export type AddCommand = EventsUnion<typeof AddCommand>;

// Effect definition

const add$: MsgEffect = event$ =>
  event$.pipe(
    matchEvent(AddCommand.add),
    map(event => event.payload), // (typeof payload) = { val: number };
    // ...
  );
```


# operator: use

Effect operator for composing middleware directly inside stream pipeline.

### **Importing**

```typescript
import { use } from '@marblejs/core';
```

### **Type declaration**

```typescript
use :: <I, O>(MiddlewareLike<I, O>, <?>EffectContext) -> Observable<I>
```

### **Parameters**

| *parameter*  | definition                    |
| ------------ | ----------------------------- |
| *middleware* | `MiddlewareLike`              |
| ctx          | *\<optional>* `EffectContext` |

### **Returns**

`Observable<I>`

### Example

```typescript
import { r, use } from '@marblejs/core';

const foo$ = r.pipe(
  r.matchPath('/'),
  r.matchType('GET'),
  r.useEffet(req$ => req$.pipe(
    // ...
    use(authorize$),
    // ...
  )));
```


# operator: act

![Soon...](/files/-M0OZl-N_3ClgSVnYnyM)


# messaging

This section documents the complete @marblejs/messaging package API.

![Soon...](/files/-M0OZl-N_3ClgSVnYnyM)


# eventBus

Creates messaging client reader for LOCAL transport layer (Event Bus)

### **Importing** <a href="#importing" id="importing"></a>

```typescript
import { eventBus } from '@marblejs/messaging';
```

### **Type declaration**

```haskell
eventBus :: EventBusConfig
  -> Reader<Context, Promise<TransportLayerConnection>>
```

### **Parameters**

| *parameter* | definition       |
| ----------- | ---------------- |
| *config*    | `EventBusConfig` |

#### ***EventBusConfig***

| ***parameter*** | definition                      |
| --------------- | ------------------------------- |
| *listener*      | \<optional> `MessagingListener` |

{% hint style="warning" %}
Because of asynchronous nature of messaging client, all related readers have to be bound to server creators via eager binding 👉 [#bindEagerlyTo](/docs/v3/other/api-reference/core/bindeagerlyto)
{% endhint %}

To learn more about `eventBus` usage please visit:

{% content-ref url="/pages/-M-RdbkPqCRMgipLWj8i" %}
[CQRS](/docs/v3/messaging/cqrs)
{% endcontent-ref %}

### Example

The event bus can be attached to server creator, like basic HTTP or any other microservice.

`@marblejs/messaging` module exposes already existing messaging client for `eventBus` transport layer:

```typescript
import { eventBus } from '@marblejs/messaging';
```

Additionally it exports tokens for both `EventBus` and `EventBusClient` instances.

```typescript
import { EventBusToken, EventBusClientToken } from '@marblejs/messaging';
```

```typescript
import { httpListener, createServer, bindEagerlyTo } from '@marblejs/core';
import { messagingListener, EventBusToken, EventBusClientToken, eventBusClient, eventBus } from '@marblejs/messaging';
​
const eventBusListener = messagingListener(...);
const listener = httpListener(...);
​
export const server = createServer({
  listener,
  dependencies: [
    bindEagerlyTo(EventBusClientToken)(eventBusClient),
    bindEagerlyTo(EventBusToken)(eventBus({ listener: eventBusListener })),
  ],
});
​
const main: IO<void> = async () =>
  await (await server)();
​
main();
```


# messagingClient

Creates messaging client reader for given transport layer

### **Importing** <a href="#importing" id="importing"></a>

```typescript
import { messagingClient } from '@marblejs/messaging';
```

### **Type declaration**

```haskell
messagingClient :: MessagingClientConfig
    -> Reader<Context, Promise<MessagingClient>>
```

### **Parameters**

| *parameter* | definition              |
| ----------- | ----------------------- |
| *config*    | `MessagingClientConfig` |

#### ***MessagingClientConfig***

| ***parameter***  | definition                                                                                                                         |
| ---------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| *msgTransformer* | \<optional> `TransportMessageTransformer`                                                                                          |
| *transport*      | `Transport` (see: [#createMicroservice](/docs/v3/other/api-reference/messaging/createmicroservice#createmicroserviceconfig))       |
| options          | `StrategyOptions` (see: [#createMicroservice](/docs/v3/other/api-reference/messaging/createmicroservice#createmicroserviceconfig)) |

{% hint style="warning" %}
Because of asynchronous nature of messaging client, all created readers have to be bound to server creators via eager binding 👉 [#bindEagerlyTo](/docs/v3/other/api-reference/core/bindeagerlyto)
{% endhint %}

To learn more about `messagingClient` output interface please visit:

{% content-ref url="/pages/-M-Rdj4-gGMRcZJ09EsM" %}
[Microservices](/docs/v3/messaging/microservices)
{% endcontent-ref %}

### Example (AMQP):

```typescript
import { bindEagerlyTo, createContextToken } from '@marblejs/core';
import { messagingClient, Transport } from '@marblejs/messaging';

const AmqpClientToken = createContextToken<MessagingClient>('AmqpClient');

const AmqpClient = messagingClient({
  transport: Transport.AMQP,
  options: {
    host: 'amqp://localhost:5672',
    queue: 'some_queue_name',
    queueOptions: { durable: false },
    timeout: 360 * 1000,
  },
});

...

const dependencies = [
  bindEagerlyTo(AmqpClientToken)(AmqpClient),
];

```

### Example (REDIS):

```typescript
import { bindEagerlyTo, createContextToken } from '@marblejs/core';
import { messagingClient, Transport } from '@marblejs/messaging';

const RedisClientToken = createContextToken<MessagingClient>('RedisClient');

const RedisClient = messagingClient({
  transport: Transport.REDIS,
  options: {
    host: 'redis://127.0.0.1:6379',
    channel: 'some_channel_name',
    timeout: 360 * 1000,
  },
});

...

const dependencies = [
  bindEagerlyTo(RedisClientToken)(RedisClient),
];

```


# createMicroservice

Creates and bootstraps microservice for given transport layer

### **Importing** <a href="#importing" id="importing"></a>

```typescript
import { createMicroservice } from '@marblejs/messaging';
```

### **Type declaration**

```haskell
createMicroservice :: CreateMicroserviceConfig
    -> Promise<ServerIO<TransportLayerConnection>>
```

### **Parameters**

| *parameter* | definition                 |
| ----------- | -------------------------- |
| *config*    | `CreateMicroserviceConfig` |

####

#### ***CreateMicroserviceConfig***

| ***parameter*** | definition                                |
| --------------- | ----------------------------------------- |
| *listener*      | `MessagingListener`                       |
| *event$*        | \<optional> `HttpServerEffect`            |
| *dependencies*  | \<optional> `Array<BoundDependency<any>>` |
| transport       | `Transport`                               |
| options         | `StrategyOptions`                         |

#### ***StrategyOptions (**`Transport.AMQP`**)***

| *parameter*     | definition                                                                                                                      |
| --------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| *host*          | `string`                                                                                                                        |
| *queue*         | `string`                                                                                                                        |
| *queueOptions*  | \<optional> `Options.AssertQueue` (see: [amqplib](https://www.squaremobius.net/amqp.node/channel_api.html#channel_assertQueue)) |
| *prefetchCount* | \<optional> `number` (defaults to **1**)                                                                                        |
| *expectAck*     | \<optional> boolean                                                                                                             |
| *timeout*       | \<optional> `number` in ms (defaults to **120s**)                                                                               |

#### ***StrategyOptions (**`Transport.REDIS`**)***

| *parameter* | definition                                        |
| ----------- | ------------------------------------------------- |
| *host*      | `string`                                          |
| *channel*   | `string`                                          |
| port        | \<optional> `number`                              |
| *password*  | \<optional> `string`                              |
| *timeout*   | \<optional> `number` in ms (defaults to **120s**) |

### Example (AMQP):

```typescript
import { IO } from 'fp-ts/lib/IO';
import { createMicroservice, messagingListener, Transport } from '@marblejs/messaging';

const amqpMicroservice = createMicroservice({
  transport: Transport.AMQP,
  options: {
    host: 'amqp://localhost:5672',
    queue: 'some_queue_name',
    queueOptions: { durable: true },
    timeout: 360 * 1000,
  },
  listener: messagingListener(...),
  dependencies: [...],
});

const main: IO<void> = async () =>
  (await amqpMicroservice)()

main();
```

### Example (REDIS):

```typescript
import { IO } from 'fp-ts/lib/IO';
import { createMicroservice, messagingListener, Transport } from '@marblejs/messaging';

const redisMicroservice = createMicroservice({
  transport: Transport.REDIS,
  options: {
    host: 'redis://127.0.0.1:6379',
    channel: 'some_channelname',
    timeout: 360 * 1000,
  },
  listener: messagingListener(...),
  dependencies: [...],
});

const main: IO<void> = async () =>
  (await redisMicroservice)()

main();
```


# reply

Constructs a reply-event

### **Importing** <a href="#importing" id="importing"></a>

```typescript
import { reply } from '@marblejs/messaging';
```

### **Type declaration**

```haskell
reply :: string -> Event -> Event
reply :: EventMetadata -> Event -> Event
reply :: Event -> Event -> Event
```

The function is responsible for constructing a reply-event for a channel name, EventMetadata object or origin event.

### **Example**

**Reply to channel:**

```typescript
import { act, matchEvent } from '@marblejs/core';
import { reply, MsgEffect } from '@marblejs/messaging';

const foo$: MsgEffect = event$ =>
  event$.pipe(
    matchEvent('FOO'),
    act(event => reply('event_bus')({ type: 'FOO_RESPONSE' })),
  );
```

**Reply with metadata construct:**

```typescript
import { act, matchEvent } from '@marblejs/core';
import { reply, MsgEffect } from '@marblejs/messaging';

const foo$: MsgEffect = event$ =>
  event$.pipe(
    matchEvent('FOO'),
    act(event => reply({
      replyTo: event.metadata.replyTo,
      correlationId: event.metadata.correlationId,
    })({ type: 'FOO_RESPONSE' })),
  );
```

**Reply to event:**

```typescript
import { act, matchEvent } from '@marblejs/core';
import { reply, MsgEffect } from '@marblejs/messaging';

const foo$: MsgEffect = event$ =>
  event$.pipe(
    matchEvent('FOO'),
    act(event => reply(event)({ type: 'FOO_RESPONSE' })),
  );
```


# websockets

This section documents the complete @marblejs/websockets package API.

![Soon...](/files/-M0OZl-N_3ClgSVnYnyM)


# webSocketListener

### **Importing**

```typescript
import { webSocketListener } from '@marblejs/websockets';
```

### **Type declaration**

```typescript
webSocketListener :: WebSocketListenerConfig -> WebSocket.ServerOptions -> ContextReader
```

### **Parameters**

| *parameter* | definition                |
| ----------- | ------------------------- |
| *config*    | `WebSocketListenerconfig` |

#### ***WebSocketListenerConfig***

| *parameter*      | definition                              |
| ---------------- | --------------------------------------- |
| *effects*        | \<optional> `Array<WsEffect>`           |
| *middlewares*    | \<optional> `Array<WsMiddlewareEffect>` |
| *error$*         | \<optional> `WsErrorEffect`             |
| connection$      | \<optional> `WsConnectionEffect`        |
| output$          | \<optional> `WsOutputEffect`            |
| eventTransformer | \<optional> `EventTransformer`          |

### **Example**

{% code title="websocket.listener.ts" %}

```typescript
import { webSocketListener } from '@marblejs/websockets';
import { example$ } from './example.effect';
import { logger$ } from './logger.middleware';

export default webSocketListener({
  middlewares: [logger$],
  effects: [add$],
});
```

{% endcode %}


# operator: broadcast

Under construction 💩


# operator: mapToServer

Under construction 💩


# middleware-multipart

A multipart/form-data middleware based on busboy library.

### Installation

```bash
yarn add @marblejs/middleware-multipart
```

Requires `@marblejs/core` to be installed.

### Importing

```typescript
import { multipart$ } from '@marblejs/middleware-multipart';
```

### Type declaration <a href="#type-declaration" id="type-declaration"></a>

```
multipart$ :: ParserOpts -> HttpMiddlewareEffect
```

### Parameters

| parameter | definition               |
| --------- | ------------------------ |
| *options* | \<optional> `ParserOpts` |

***ParserOpts***

| ***parameter*** | definition                  |
| --------------- | --------------------------- |
| *files*         | \<optional> `Array<string>` |
| *stream*        | \<optional> `StreamHandler` |
| *maxFileSize*   | \<optional> `number`        |
| *maxFileCount*  | \<optional> `number`        |
| *maxFieldSize*  | \<optional> `number`        |
| *maxFieldCount* | \<optional> `number`        |

### Usage

{% hint style="warning" %}
Make sure that you always handle the files that a user uploads. Never add it as a global middleware since a malicious user could upload files to a route that you didn't handle. Only use this it on routes where you are handling the uploaded files.
{% endhint %}

**In-memory storage:**

```typescript
import { multipart$ } from '@marblejs/middleware-multipart';

const effect$ = r.pipe(
  r.matchPath('/'),
  r.matchType('POST'),
  r.useEffect(req$ => req$.pipe(
    use(multipart$()),
    map(req => ({ body: {
      files: req.files,    // file data
      body: req.body,      // all incoming body fields
    }}))
  )));
```

**Out-of-memory storage:**

```typescript
import { multipart$, StreamHandler } from '@marblejs/middleware-multipart';

const stream: StreamHandler = ({ file, fieldname }) => {
  // stream here incoming file to different location...
  const destination = // ... and grab the persisted file location
  return of({ destination });
};

const effect$ = r.pipe(
  r.matchPath('/'),
  r.matchType('POST'),
  r.useEffect(req$ => req$.pipe(
    use(multipart$({
      stream,
      maxFileCount: 1,
      files: ['image_1'],
    })),
    map(req => ({ body: {
      files: req.files['image_1'],  // file data
      body: req.body,               // all incoming body fields
    }}))
  )));
```

You can intercept incoming files and stream them to the different place, eg. to OS filesystem or AWS S3 bucket. The prervious example shows how you can specify constraints for *multipart/form-data* parsing the accepts only **one** `image_1` field.

Each file included inside `req.files` object contains the following information:

| key           | description                                                               |
| ------------- | ------------------------------------------------------------------------- |
| `fieldname`   | Field name specified in the form                                          |
| `filename`    | Name of the file on the user's computer                                   |
| `encoding`    | Encoding type of the file                                                 |
| `mimetype`    | Mime type of the file                                                     |
| `size`        | Size of the file in bytes **(in-memory parsing)**                         |
| `destination` | The place in which the file has been saved **(if not in-memory parsing)** |
| `buffer`      | A `Buffer` of the entire file **(in-memory parsing)**                     |

You can define the following middleware options:

| key             | description                                                                |
| --------------- | -------------------------------------------------------------------------- |
| `maxFileCount`  | The total count of files that can be sent                                  |
| `maxFieldCount` | The total count of fields that can be sent                                 |
| `maxFileSize`   | The max possible file size in bytes                                        |
| `files`         | An array of acceptable field names                                         |
| `stream`        | A handler which you can use to stream incoming files to different location |


# middleware-cors

A CORS middleware for Marble.js

### Installation

```bash
yarn add @marblejs/middleware-cors
```

Requires `@marblejs/core` to be installed.

### Importing

```typescript
import { cors$ } from '@marblejs/middleware-cors';
```

### Type declaration <a href="#type-declaration" id="type-declaration"></a>

```
cors$ :: CORSOptions -> HttpMiddlewareEffect
```

### Parameters

| parameter | definition                |
| --------- | ------------------------- |
| *options* | \<optional> `CORSOptions` |

***CORSOptions***

| ***parameter***      | definition                                 |
| -------------------- | ------------------------------------------ |
| origin               | \<optional> `string \| string[] \| RegExp` |
| methods              | \<optional> `HttpMethod[]`                 |
| optionsSuccessStatus | \<optional> `HttpStatus`                   |
| allowHeaders         | \<optional> `string \| string[]`           |
| exposeHeaders        | \<optional> `string[]`                     |
| withCredentials      | \<optional> `boolean`                      |
| maxAge               | \<optional> `number`                       |

This object allows you to configure CORS headers with various options. Both `methods` and `exposeHeaders` support wildcard. By default options are configured as following.

```typescript
{ 
  origin: '*',
  methods: ['HEAD', 'GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'],
  withCredentials: false,
  optionsSuccessStatus: HttpStatus.NO_CONTENT, // 204
}
```

Note that provided options are merged with default options so you need to overwrite each default parameter you want to customize.

### Basic usage

```typescript
import { httpListener } from '@marblejs/core';
import { cors$ } from '@marblejs/middleware-cors';

export const listener = httpListener({
  middlewares: [
    cors$({
      origin: '*',
      allowHeaders: '*',
      methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'],
    })
  ],
  effects: [/* ... */],
});
```

For security purpose it's better to be strict as possible when configuring CORS options.

### Strict usage

```typescript
import { httpListener } from '@marblejs/core';
import { cors$ } from '@marblejs/middleware-cors';

export const listener = httpListener({
  middlewares: [
    cors$({
      origin: ['http://example1.com', 'http://example2.com'],
      allowHeaders: ['Origin', 'Authorization', 'Content-Type'],
      methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'],
    })
  ],
  effects: [/* ... */],
});
```

Headers notation is case insensitive. `content-type` will also work.


# middleware-joi

A Joi validation middleware for Marble.js.

<div align="center"><img src="/files/-LLYJsPvN01UHocjSg46" alt=""></div>

[Joi](https://github.com/hapijs/joi) is an object schema description language and validator for JavaScript objects. Using its schema language, you can validate things like:

* HTTP request headers
* HTTP body parameters
* HTTP request query parameters
* URL parameters

You can find detailed API reference for Joi schemas [here](https://github.com/hapijs/joi/blob/v13.6.0/API.md).

{% hint style="warning" %}
For more advanced request or event validation purposes we highly recommend to use [@marblejs/middleware-io](/docs/v3/other/api-reference/middleware-io) package instead. It can better handle type inference for complex schemas.
{% endhint %}

### Installation

```bash
yarn add @marblejs/middleware-joi
```

Requires `@marblejs/core` to be installed.

### Importing

```typescript
import { validator$ } from '@marblejs/middleware-joi';
```

### Type declaration

```
validator$ :: (Schema, Joi.ValidationOptions) -> HttpMiddlewareEffect
```

### **Parameters**

| *parameter* | definition                                                                                                            |
| ----------- | --------------------------------------------------------------------------------------------------------------------- |
| *schema*    | `Schema`                                                                                                              |
| *options*   | \<optional> `Joi.ValidationOptions` (see: [Joi API reference](https://github.com/hapijs/joi/blob/v13.6.0/API.md#joi)) |

#### ***Schema***

| *parameter* | definition        |
| ----------- | ----------------- |
| *headers*   | \<optional> `any` |
| *params*    | \<optional> `any` |
| *query*     | \<optional> `any` |
| *body*      | \<optional> `any` |

### Usage

**1.** Example of using middleware on a *GET* route to validate query parameters:

{% code title="foo.effect.ts" %}

```typescript
import { r } from '@marblejs/core';
import { validator$, Joi } from '@marblejs/middleware-joi';

const foo$ = r.pipe(
  r.matchPath('/'),
  r.matchType('GET'),
  r.useEffect(req$ => req$.pipe(
    use(validator$({
      query: Joi.object({
        id: Joi.number().min(1).max(10),
      })
    }));
    // ...
  )));
```

{% endcode %}

Example above will validate each incoming request connected with `foo$` *Effect*. The validation blueprint defines that the `id` query parameter should be a number between *<1..10>*. If the schema requirements are not satisfied the middleware will throw an error with description what went wrong.

```typescript
{
  error: {
    status: 400,
    message: '"id" is required'
  }
}
```

**2.** Example of validating all incoming requests:

{% code title="app.ts" %}

```typescript
import { validator$, Joi } from '@marblejs/middleware-joi';

const middlewares = [
  // ...
  validator$(
    {
      headers: Joi.object({
        token: Joi.string().token().required(),
        accept: Joi.string().default('application/json')
      })
    },
    { stripUnknown: true },
  )
];

const effects = [
  endpoint1$,
  endpoint2$,
  ...
];

const app = httpListener({ middlewares, effects });
```

{% endcode %}

### Credits

Middleware author: [Lucio Rubens](https://github.com/luciorubeens)


# middleware-jwt

HTTP requests authentication middleware for Marble.js based on JWT mechanism.

This module lets you authenticate HTTP requests using JWT tokens in your **Marble.js** applications. JWTs are typically used to protect API endpoints, and are often issued using OpenID Connect.

{% hint style="info" %}
You can find more details about JWT (RFC 7519) standard [here](http://jwt.io).
{% endhint %}

The middleware uses `jsonwebtoken` package under the hood. It wraps the package API into more\
RxJS-friendly abstractions that can be partially applied and composed inside Effect streams.

### Installation

```bash
yarn add @marblejs/middleware-jwt
```

Requires `@marblejs/core` to be installed.

### Importing

```typescript
import { authorize$ } from '@marblejs/middleware-jwt';
```

### Type declaration

```
authorize$ :: (VerifyOptions, object -> Observable<object>) -> HttpMiddlewareEffect
```

### **Parameters**

| *parameter*      | definition                                |
| ---------------- | ----------------------------------------- |
| *config*         | `VerifyOptions`                           |
| *verifyPayload$* | `(payload: object) => Observable<object>` |

{% tabs %}
{% tab title="verifyPayload$" %}
A function used for payload verification. With this handler we can check if the payload extracted from the JWT token fulfills our security criterias (eg. we can verify if the given user identifier exists in the database). Besides the general verification, the function can return the streamed object, that will be available inside *HttpRequest* `req.user` parameter. If the stream throws an error (eg. during the validation) the *authorize$* middleware responds with `401 / Unauthorized` error.

**Type declaration**

```
verifyPayload$ :: object -> Observable<object>
```

**Example**

The function checks the presence of the user id in the database and then returns an *Observable* of found user instance.&#x20;

{% code title="" %}

```typescript
const verifyPayload$ = (payload: Payload) => UserDao
  .findById(payload._id)
  .pipe(flatMap(neverNullable));
```

{% endcode %}
{% endtab %}

{% tab title="VerifyOptions" %}
Config object, passed as a first argument, defines a set of parameters that are used during token verification process.

| *parameter*      | definition                       |
| ---------------- | -------------------------------- |
| *secret*         | `string \| Buffer`               |
| algorithms       | \<optional>  `string[]`          |
| audience         | \<optional> `string \| string[]` |
| clockTimestamp   | \<optional> `number`             |
| clockTolerance   | \<optional> `number`             |
| issuer           | \<optional> `string \| string[]` |
| ignoreExpiration | \<optional> `boolean`            |
| ignoreNotBefore  | \<optional> `boolean`            |
| jwtid            | \<optional> `string`             |
| subject          | \<optional> `string`             |
| {% endtab %}     |                                  |
| {% endtabs %}    |                                  |

{% hint style="info" %}
For more infos about *jwt.VerifyOptions* please read [jsonwebtoken docs](https://github.com/auth0/node-jsonwebtoken#jwtverifytoken-secretorpublickey-options-callback).
{% endhint %}

{% hint style="info" %}
You can read more about token creation [here](/docs/v3/other/api-reference/middleware-jwt/token-creation).
{% endhint %}

### **Usage**

It is recommended to extract the middleware configuration into separate file. This way you can reuse it in many places.

{% code title="auth.middleware.ts" %}

```typescript
import { authorize$ as jwt$ } from '@marblejs/middleware-jwt';
import { SECRET_KEY } from './config';

const config = { secret: SECRET_KEY };

const verifyPayload$ = (payload: Payload) => UserDao
  .findById(payload._id)
  .pipe(flatMap(neverNullable));

export const authorize$ = jwt$(config, verifyPayload$);
```

{% endcode %}

The configured middleware can be simply composed in any route, that should be validated.

```typescript
import { r } from '@marblejs/core';
import { authorize$ } from './auth-middleware';

const getUsers$ = r.pipe(
  r.matchPath('/'),
  r.matchType('GET'),
  r.useEffect(getUsersEffect$)));

const user$ = combineRoutes('/user', {
  effects: [getUsers$],
  middlewares: [authorize$], 👈
});
```

If the incoming request doesn't pass the authentication process (eg. token is invalid, expired or the `verifyPayload$` throws an error, the middleware responds with `401 / Unauthorized` error.


# Token signing

Besides the common things like token authorization, the middleware comes with handy functions responsible for token signing.

## + **generateToken**

The middleware wraps auth0 [jsonwebtoken](https://github.com/auth0/node-jsonwebtoken) API into more RxJS friendly functions that can be partially applied and composed inside Observable streams.

**generateToken** signs new JWT token with provided payload and configuration object which defines the way how the token is signed.&#x20;

### Importing

```typescript
import { generateToken } from '@marblejs/middleware-jwt';
```

### Type declaration

```
generateToken :: GenerateOptions -> Payload -> string
```

### Parameters

| *parameter* | definition                             |
| ----------- | -------------------------------------- |
| *options*   | `GenerateOptions`                      |
| *payload*   | `Payload = string \| object \| Buffer` |

{% tabs %}
{% tab title="GenerateOptions" %}
Config object which defines a set of parameters that are used for token signing.

| *parameter*   | definition                       |
| ------------- | -------------------------------- |
| *secret*      | `string \| Buffer`               |
| algorithm     | \<optional> `string`             |
| keyid         | \<optional> `string`             |
| expiresIn     | \<optional> `string \| number`   |
| notBefore     | \<optional> `string \| number`   |
| audience      | \<optional> `string \| string[]` |
| subject       | \<optional> `string`             |
| issuer        | \<optional> `string`             |
| jwtid         | \<optional> `string`             |
| noTimestamp   | \<optional> `boolean`            |
| header        | \<optional> `object`             |
| encoding      | \<optional> `string`             |
| {% endtab %}  |                                  |
| {% endtabs %} |                                  |

{% hint style="info" %}
For more details about JWT token signing, please visit [jsonwebtoken package docs](https://github.com/auth0/node-jsonwebtoken).
{% endhint %}

## + **generateExpirationInHours**

The standard for JWT defines an `exp` claim for expiration. The expiration is represented as a **NumericDate.** This means that the expiration should contain the number of seconds since the epoch.

**generateExpiratinoInHours** is a small, but handy function that returns an numeric date for given hours as a parameter. If the function is called without any parameter then the date is generated with 1 hour expiration.

### Importing

```typescript
import { generateExpirationInHours } from '@marblejs/middleware-jwt';
```

### Type declaration

```
generateExpirationInHours :: number -> number
```

## **Example**

{% code title="token.helper.ts" %}

```typescript
export const generateTokenPayload = (user: User) => ({
  id: user.id,
  email: user.email,
  exp: generateExpirationInHours(4), 
  // 👆 token will expire within the next 4 hours
});
```

{% endcode %}

{% code title="login.effect.ts" %}

```typescript
import { generateTokenPayload } from './token.helper';

const login$ = r.pipe(
  r.matchPath('/login'),
  r.matchType('POST'),
  r.useEffect(req$ => req$.pipe(
    map(req => req.body),
    mergeMap(UserDao.findByCredentials),
    map(generateTokenPayload),
    // 👇
    map(generateToken({ secret: Config.jwt.secret })),
    map(token => ({ body: { token } })),
    catchError(() => throwError(
      new HttpError('Unauthorized', HttpStatus.UNAUTHORIZED)
    )),
  )));
```

{% endcode %}


# middleware-io

A data validation middleware based on awesome [io-ts](https://github.com/gcanti/io-ts) library authored by [*gcanti*](https://github.com/gcanti).

### Installation

```bash
yarn add @marblejs/middleware-io
```

Requires `@marblejs/core` to be installed.

### Importing

```typescript
// HTTP
import { requestValidator$ } from '@marblejs/middleware-io';

// Events, eg. WebSockets
import { eventValidator$ } from '@marblejs/middleware-io';
```

### Type declaration <a href="#type-declaration" id="type-declaration"></a>

```haskell
requestValidator$ :: (RequestSchema, ValidatorOptions) -> Observable<HttpRequest> -> Observable<HttpRequest>
eventValidator$ :: (Schema, ValidatorOptions) -> Observable<Event> -> Observable<Event>
```

### Parameters

***requestValidator$***

| parameter | definition                                                                  |
| --------- | --------------------------------------------------------------------------- |
| *schema*  | `Partial<RequestSchema>`(see [io-ts](https://github.com/gcanti/io-ts) docs) |
| *options* | \<optional> `ValidatorOptions`                                              |

***eventValidator$***

| parameter | definition                                                   |
| --------- | ------------------------------------------------------------ |
| *schema*  | `Schema` (see [io-ts](https://github.com/gcanti/io-ts) docs) |
| *options* | \<optional> `ValidatorOptions`                               |

***ValidatorOptions***

| parameter  | definition             |
| ---------- | ---------------------- |
| *reporter* | \<optional> `Reporter` |
| *context*  | \<optional> `string`   |

### Usage

Let's define a user schema that will be used for I/O validation.

{% code title="user.schema.ts" %}

```typescript
export const userSchema = t.type({
  id: t.string,
  firstName: t.string,
  lastName: t.string,
  roles: t.array(t.union([
    t.literal('ADMIN'),
    t.literal('GUEST'),
  ])),
});

export type User = t.TypeOf<typeof userSchema>;
```

{% endcode %}

```typescript
import { use, r } from '@marblejs/core';
import { requestValidator$, t } from '@marblejs/middleware-io';
import { userSchema } from './user.schema.ts';

const effect$ = r.pipe(
  r.matchPath('/'),
  r.matchType('POST'),
  r.useEffect(req$ => req$.pipe(
    requestValidator$({ body: userSchema }),
    // ..
  )));
```

{% hint style="info" %}
For more validation use cases and recipes, visit [Validation](broken://pages/-LYw8KVuQ5ljVoRB2kao) chapter.
{% endhint %}

You can also reuse the same schema for Events validation if you want.

```typescript
import { matchEvent, act } from '@marblejs/core';
import { WsEffect } from '@marblejs/websockets';
import { eventValidator$, t } from '@marblejs/middleware-io';
import { userSchema } from './user.schema.ts';

const postUser$: WsEffect = event$ =>
  event$.pipe(
    matchEvent('CREATE_USER'),
    act(eventValidator$(userSchema)),
    act(event => { ... }),
  );
```

The inferred `req.body` / `event.payload` type of provided schema, will be of the following form:

```typescript
type User = {
  id: string;
  firstName: string;
  lastName: string;
  roles: ('ADMIN' | 'GUEST')[];
};
```

{% hint style="warning" %}
Please note that **each** `eventValidator$` **must be** applied inside `act` operator to prevent closing of the main observable stream.
{% endhint %}

### Validation errors

Lets take a look at the default reported validation error thrown by `eventValidator$` . Let's assume that client passed wrong values for `firstName` and `roles`  fields.

```javascript
payload.lastName = false;
payload.roles = ['TEST'];
```

The reported error intercepted via default error effect will look like follows.

```javascript
{
  type: 'CREATE_USER',
  error: {
    message: 'Validation error',
    data: [
      {
        path: 'lastName',
        expected: 'string',
        got: 'false'
      },
      {
        path: 'roles.0.0',
        got: '"TEST"',
        expected: '"ADMIN"'
      },
      {
        path: 'roles.0.1',
        got: '"TEST"',
        expected: '"GUEST"'
      }
    ]
  }
}
```

### Reporters

You can create custom reporters by conforming to [io-ts](https://github.com/gcanti/io-ts#error-reporters) `Reporter` interface.

```typescript
interface Reporter<A> {
  report: (validation: Validation<any>) => A
}
```

In order to use custom reporter you have to pass it with `options` object as a second argument.

```typescript
requestValidator$(schema, { reporter: customReporter });
```


# middleware-logger

HTTP request logger middleware for Marble.js

**Simple** middleware for request logging inside your console. It displays the outgoing request events using the following format:

```
{HTTP_METHOD} {PATH} {HTTP_STATUS} {TIME}
```

```
POST /api/v1/user 200 1ms
```

### Installation

```bash
$ yarn add @marblejs/middleware-logger
```

Requires `@marblejs/core` to be installed.

### Importing

```typescript
import { logger$ } from '@marblejs/middleware-logger';
```

### Type declaration

```
logger$ :: LoggerOptions -> HttpMiddlewareEffect
```

### **Parameters**

| *parameter* | definition                  |
| ----------- | --------------------------- |
| *options*   | \<optional> `LoggerOptions` |

#### ***LoggerOptions***

| *parameter* | definition                           |
| ----------- | ------------------------------------ |
| *silent*    | \<optional> `boolean`                |
| *filter*    | \<optional> `HttpRequest -> boolean` |

### Usage

1. Default behavior. Log every response to *process*.*stdout*:

```typescript
import { httpListener } from '@marblejs/core';
import { logger$ } from '@marblejs/middleware-logger';

const middlewares = [
  logger$(),
  ...
];

export const listener = httpListener({
  middlewares,
  effects: [],
});
```

2\. Customized logging behavior:

```typescript
import { httpListener } from '@marblejs/core';
import { logger$ } from '@marblejs/middleware-logger';
import { isTestEnv } from './util';

const middlewares = [
  logger$({
    silent: isTestEnv(),
    filter: req => req.res.status >= 400;
  }),
  ...
];

export const listener = httpListener({
  middlewares,
  effects: [],
});
```

* **silent** - When `true` the logging is turned off (usually useful during testing),
* **filter** - Filter outgoing responses or incoming requests based on given predicate. For example we can log only HTTP status codes above *400*.


# middleware-body

HTTP request body parser middleware for Marble.js.

## Installation

```bash
yarn add @marblejs/middleware-body
```

Requires `@marblejs/core` to be installed.

## Importing

```typescript
import { bodyParser$ } from '@marblejs/middleware-body';
```

## Type declaration <a href="#type-declaration" id="type-declaration"></a>

```haskell
bodyParser$ :: BodyParserOptions -> HttpMiddlewareEffect
```

## Parameters

| parameter | definition                      |
| --------- | ------------------------------- |
| *options* | \<optional> `BodyParserOptions` |

***BodyParserOptions***

| ***parameter*** | definition                      |
| --------------- | ------------------------------- |
| *parser*        | \<optional> `RequestBodyParser` |
| *type*          | \<optional> `Array<string>`     |

The `type` option is used to determine what media type the middleware will parse. It is passed directly to the [type-is](https://www.npmjs.org/package/type-is#readme) library and this can be an extension name (like `json`), a mime type (like `application/json`), or a mime type with a wildcard (like `*/*` or `*/json`). Defaults to `*/*`.

## Basic usage

{% code title="app.ts" %}

```typescript
import { bodyParser$ } from '@marblejs/middleware-body';

export default httpListener({
  middlewares: [bodyParser$()],
  effects: [/* ... */],
});
```

{% endcode %}

Lets assume that we have the following *CURL* command, which triggers `POST /api/login` endpoint:

```bash
$ curl --header "Content-Type: application/json" \
  --request POST \
  --data '{ "username": "foo", "password": "bar" }' \
  http://localhost:3000/api/login
```

Using previously connected `bodyParser$` middleware, the app will intercept the following payload object:

```typescript
req.body = {
  username: 'foo',
  password: 'bar',
};
```

The *POST* request body can be intercepted like follows.

{% code title="login.effect.ts" %}

```typescript
import { r } from '@marblejs/core';

export const login$ = r.pipe(
  r.matchPath('/login'),
  r.matchType('POST'),
  r.useEffect(req$ => req$.pipe(
    map(req => req.body as { username: string, password: string }),
    map(body => ({ body: `Hello, ${body.username}!` }))
  )));
```

{% endcode %}

{% hint style="danger" %}
All properties and values in `req.body` object are untrusted (unknown) and should be validated before trusting.
{% endhint %}

{% hint style="info" %}
This middleware does not handle multipart bodies.
{% endhint %}

## Advanced usage

The middleware does nothing if request *Content-Type* is not matched, which makes a possibility for chaining multiple parsers one after another. For example, we can register multiple middlewares that will parse only a certain set of possible *Content-Type* headers.

**Default parser:**

```typescript
import { bodyParser$ } from '@marblejs/middleware-body';

bodyparser$();
```

Parses *application/json* (to JSON), *application/x-www-form-urlencoded* (to JSON), *application/octet-stream* (to Buffer) and *text/plain* (to string) content types

**JSON parser:**

```typescript
import { bodyParser$, jsonParser } from '@marblejs/middleware-body';

bodyParser$({
  parser: jsonParser,
  type: ['*/json', 'application/vnd.api+json'],
})
```

Parses `req.body` to JSON object.

**URLEncoded parser:**

```typescript
import { bodyParser$, urlEncodedParser } from '@marblejs/middleware-body';

bodyParser$({
  parser: urlEncodedParser,
  type: ['*/x-www-form-urlencoded'],
});
```

Parses encoded URLs `req.body` to JSON object.

**Text parser:**

```typescript
import { bodyParser$, textParser } from '@marblejs/middleware-body';

bodyParser$({
  parser: textParser,
  type: ['text/*'],
});
```

Parses `req.body` to string.

**Raw parser:**

```typescript
import { bodyParser$, rawParser } from '@marblejs/middleware-body';

bodyParser$({
  parser: rawParser,
  type: ['application/octet-stream'],
}),
```

Parses `req.body` to Buffer.

## Custom parsers

If the available parsers are not enough, you can create your own body parsers by conforming to `RequestBodyParser` interface. The example below shows how the `jsonParser` looks underneath.

```typescript
export const jsonParser: RequestBodyParser = req => body =>
  JSON.parse(body.toString());
```


# Style Guide

{% hint style="info" %}
The style guide is mostly based on author experience in using Marble.js on large production-ready projects following microservice/event-driven architecture style.
{% endhint %}

## Project organization

Marble.js framework doesn't define any strict file structures and conventions from the organization-level perspective that each developer should enforce. Below you can find some useful hints that you can follow when organizing your Marble.js app.

### Keep server and connected listeners in separate files

From the framework perspective, **listeners** and **servers** are separate layers that are responsible for different things. [#createServer](/docs/v3/other/api-reference/core/createserver) and similar factory functions are responsible for handling transport-layer-related processes, like: bootstrapping server and bounded context, listening for incoming messages or reacting for transport-layer events, where for the contrast, listeners are responsible for processing I/O messages that go through underlying transport layer in order to fulfill business needs. Basically, it is just about the single responsibility principle.

By convention Marble.js follows suffixed file naming which results in:

| Server                   | Listener                   |
| ------------------------ | -------------------------- |
| `http.server.ts`         | `http.listener.ts`         |
| `microservice.server.ts` | `microservice.listener.ts` |
| `websocket.server.ts`    | `websocket.listener.ts`    |
| `NONE`                   | `eventbus.listener.ts`     |

### Keep HTTP route with its corresponding HttpEffect

In Marble.js HTTP effects are tightly connected to the route on which they operate. Having them in a separation makes the code more less readable and understandable. Always try to keep them as a one unit. Every HttpEffect that comes through `r.pipe` route builder is accessible via `.effect` property of the returned `RouteEffect` object. You can access it via this way if you want to unit test only the effect function.

**❌ Bad**

{% tabs %}
{% tab title="getFoo.route.ts" %}

```typescript
import { r } from '@marblejs/core';
import { getFooEffect } from './getFoo.effect';

const getFoo = r.pipe(
  r.matchPath('/foo'),
  r.matchType('GET'),
  r.useEffect(getFooEffect));
```

{% endtab %}

{% tab title="getFoo.effect.ts" %}

```typescript
import { HttpEffect } from '@marblejs/core';

export const getFooEffect: HttpEffect = (req$, ctx) => req$.pipe(
  ...
);
```

{% endtab %}
{% endtabs %}

✅ **Good**

{% tabs %}
{% tab title="getFoo.effect.ts" %}

```typescript
import { r } from '@marblejs/core';

const getFoo$ = r.pipe(
  r.matchPath('/foo'),
  r.matchType('GET'),
  r.useEffect((req$, ctx) => req$.pipe(
    ...
  )));
```

{% endtab %}
{% endtabs %}

### Use index files for combining related effects

Index files are good for combining and re-exporting related files as a one module.

```
/user
  + ── /getUserList
  │      + ── getUserList.effect.spec.ts
  │      └─── getUserList.effect.ts
  │
  + ── /getUser
  │      + ── getUser.effect.spec.ts
  │      └─── getUser.effect.ts
  │
  + ── /postUser
  │      + ── getUser.effect.spec.ts
  │      └─── getUser.effect.ts
  │
  └─── index.ts
  
```

{% tabs %}
{% tab title="index.ts" %}

```typescript
import { combineRoutes } from '@marblejs/core';

export const user$ = combineRoutes('/user', {
  middlewares: [
    authorize$,
  ],
  effects: [
    getUserList$,
    getUser$,
    postUser$,
  ],
});
```

{% endtab %}

{% tab title="http.listener.ts" %}

```typescript
import { httpListener } from '@marblejs/core';
import { user$ } from './user';

export const listener = httpListener({
  effects: [
    user$,
  ],
});
```

{% endtab %}
{% endtabs %}

Or in case basic effects:

{% tabs %}
{% tab title="index.ts" %}

```typescript
import { combineEffects } from '@marblejs/core';

export const user$ = combineEffects(
  userCreated$,
  userRemoved$,
  ...
);
```

{% endtab %}

{% tab title="eventBus.listener.ts" %}

```typescript
import { messagingListener } from '@marblejs/messaging';
import { user$ } from './user';

export const listener = messagingListener({
  effects: [
    user$,
  ],
});
```

{% endtab %}
{% endtabs %}

## Context

### Token naming and creation

* Use PascalCase naming convention with `Token` suffix for token definitions.
* Always remember to define a context token name identifier. It will help you quickly recognize what dependency is missing when asking for it via `useContext` hook function.
* Place token next to reader definition. It is easier to navigate to reader implementation via popular "*Go to Implementation*" mechanism.

❌ **Bad**

{% tabs %}
{% tab title="tokens.ts" %}

```typescript
import { createContextToken } from '@marblejs/core';

export const userRepository = createContextToken<UserRepository>();
```

{% endtab %}

{% tab title="user.repository.ts" %}

```typescript
import { createReader } from '@marblejs/core';

export const userRepository = createReader(() => ...);
```

{% endtab %}
{% endtabs %}

✅ **Good**

{% tabs %}
{% tab title="user.repository" %}

```typescript
import { createContextToken, createReader } from '@marblejs/core';

export type UserRepository = ReturnType<typeof UserRepository>;

export const UserRepository = createReader(() => ...);

export const UserRepositoryToken = createContextToken<UserRepository>('UserRepository');
```

{% endtab %}
{% endtabs %}

### Eager vs Lazy binding

Identify which dependencies should be bound to the app context eagerly (before app startup) and which lazily.

**Given:**

```typescript
import { createContextToken, createReader } from '@marblejs/core';

export type DatabaseConnection = Connection;

export const DatabaseConnection = createReader(async _ => ...);

export const DatabaseConnectionToken = createContextToken<DatabaseConnection>('DatabaseConnection');
```

Note that in case of [async readers](/docs/v3/http/context#async-readers) the type of created reader will be: `Reader<Context, Promise<Connection>>`

❌ **Bad**

```typescript
import { bindTo, bindLazilyTo, useContext } from '@marblejs/core';

const dependencies = [
  bindTo(DatabaseConnectionToken)(DatabaseConnection),
  // or 
  bindLazilyTo(DatabaseConnectionToken)(DatabaseConnection),  
];

...

const connection = useContext(DatabaseConnectionToken)(ask);

// typeof connection === Promise<Connection>;
```

✅ **Good**

```typescript
import { bindEagerlyTo, useContext } from '@marblejs/core';

const dependencies = [
  bindEagerlyTo(DatabaseConnectionToken)(DatabaseConnection),
];

...

const connection = useContext(DatabaseConnectionToken)(ask);

// typeof connection === Connection;
```

### Injection

Always try to inject bound dependencies at the top level of your effects (before returned Observable stream). All effects are evaluated eagerly, so in case of missing context dependency the framework will be able to spot issues during initial bootstrap.&#x20;

❌ **Bad**

```typescript
const postUser$ = r.pipe(
  r.matchPath('/'),
  r.matchType('POST'),
  r.useEffect((req$, ask) => req$.pipe(
    validateRequest,
    mergeMap(req => {
      const userRepository = useContext(UserRepositoryToken)(ask);
      const { body } = req;
      
      return userRepository
        .persist(body)
        .pipe(
          mergeMap(userRepository.getById),
          map(user => ({ body: user })),
        );
    }),
  ));
```

✅ **Good**

```typescript
const postUser$ = r.pipe(
  r.matchPath('/'),
  r.matchType('POST'),
  r.useEffect((req$, ask) => {
    const userRepository = useContext(UserRepositoryToken)(ask);

    return req$.pipe(
      validateRequest,
      map(req => req.body),
      mergeMap(userRepository.persist),
      mergeMap(userRepository.getById),
      map(user => ({ body: user })),
    );
  }));
```

## Messaging

### Event encoding/decoding

* Use **UPPER\_SNAKE\_CASE** event type naming
* Use enumerable string literal type or plain const record for gathering a map of all possible event types for given context
* Use [`event`](/docs/v3/messaging/core-concepts/events#i-o-event-decoding-encoding) builder for I/O encoding/decoding
* Group your messages into `Events`, `Commands` and `Queries` (see: [CQRS](/docs/v3/messaging/cqrs) chapter)

❌ **Bad**

{% tabs %}
{% tab title="user.event.ts" %}

```typescript
import { Event } from '@marblejs/core';
import * as t from 'io-ts';

export const UserCreated = (id: string): Event => ({
  type: 'UserCreated',
  payload: { id },
});

export const UserUpdated = (id: string): Event => ({
  type: 'UserUpdated',
  payload: { id },
});

export const UserCreatedCodec = t.type({
  type: t.literal('UserCreated'),
  payload: t.type({ id: t.string }),
});

export const UserUpdatedCodec = t.type({
  type: t.literal('UserUpdated'),
  payload: t.type({ id: t.string }),
});
```

{% endtab %}
{% endtabs %}

**✅ Good**

```typescript
import { event } from '@marblejs/core';
import * as t from 'io-ts';

export enum UserEventType {
  USER_CREATED = 'USER_CREATED',
  USER_UPDATED = 'USER_UPDATED',
}

export const UserCreatedEvent =
  event(UserEventType.USER_CREATED)(t.type({
    id: t.string,
  }));
  
export const UserUpdatedEvent =
  event(UserEventType.USER_UPDATED)(t.type({
    id: t.string,
  }));
```

### Event matching and validation

* Always try match events by event I/O codec - avoid raw literals since they don't carry the actual event payload type
* Event-based communication follows the same laws as request-based communication - each incoming event should be validated before usage (eg. using previously mentioned `event` codec).

❌ **Bad**

{% tabs %}
{% tab title="userCreated.effect.ts" %}

```typescript
import { act, matchEvent } from '@marblejs/core';
import { MsgEffect } from '@marblejs/messaging';

export const userCreated$: MsgEffect = event$ =>
  event$.pipe(
    // event payload is unknown, no type is inferred... 
    matchEvent('USER_CREATED'),
    act(event => ...),
  );
```

{% endtab %}
{% endtabs %}

❌ / **✅ Better**

{% tabs %}
{% tab title="userCreated.effect.ts" %}

```typescript
import { act, matchEvent } from '@marblejs/core';
import { MsgEffect } from '@marblejs/messaging';
import { UserCreatedEvent } from './user.event.ts';

export const userCreated$: MsgEffect = event$ =>
  event$.pipe(
    // type is inferred but event still requires validation...
    matchEvent(UserCreatedEvent),
    act(event => ...),
  );
```

{% endtab %}
{% endtabs %}

**✅ Good**

{% tabs %}
{% tab title="userCreated.effect.ts" %}

```typescript
import { act, matchEvent } from '@marblejs/core';
import { MsgEffect } from '@marblejs/messaging';
import { UserCreatedEvent } from './user.event.ts';

export const userCreated$: MsgEffect = event$ =>
  event$.pipe(
    matchEvent(UserCreatedEvent),
    act(eventValidator$(UserCreatedEvent)),
    act(event => ...),
  );
```

{% endtab %}
{% endtabs %}

### Effect output

* Each processed event should be mapped to a different event type to avoid infinite-loops.
* In case you don't want to emit anything in the effect stream you can skip emitted values, eg. by `ignoreElements` operator.

❌ **Bad**

```typescript
import { matchEvent } from '@marblejs/core';
import { MsgEffect } from '@marblejs/messaging';

const foo$: MsgEffect = event$ =>
  event$.pipe(
    matchEvent('FOO'),
    tap(doSomeWork),
  );
```

**✅ Good**

```typescript
import { act, matchEvent } from '@marblejs/core';
import { MsgEffect } from '@marblejs/messaging';
import { pipe } from 'fp-ts/lib/pipeable';

const foo$: MsgEffect = event$ =>
  event$.pipe(
    matchEvent('FOO'),
    act(event => pipe(
      doSomeWork(event),
      map(payload => ({ type: 'FOO_RESULT', payload })),
    )),
  );
```

### Error handling

* Each messaging effect should handle errors in a disposable streams either via `mergeMap/switchMap/...` operators with combination of `catchError` or via`act` operator.

❌ **Bad**

```typescript
import { matchEvent } from '@marblejs/core';
import { MsgEffect } from '@marblejs/messaging';

const foo$: MsgEffect = event$ =>
  event$.pipe(
    matchEvent('FOO'),
    mergeMap(doSomeWork),
    map(payload => ({ type: 'FOO_RESULT', payload }),
  );
```

✅ **Good**

```typescript
import { act, matchEvent } from '@marblejs/core';
import { MsgEffect } from '@marblejs/messaging';
import { pipe } from 'fp-ts/lib/pipeable';
import { catchError } from 'rxjs/operators';

const foo$: MsgEffect = event$ =>
  event$.pipe(
    matchEvent('FOO'),
    mergeMap(event => pipe(
      doSomeWork(event),
      map(payload => ({ type: 'FOO_RESULT', payload })),
      catchError(error => ({ type: 'FOO_ERROR', error })),
    )),
  );
```

**✅ Even better**

```typescript
import { act, matchEvent } from '@marblejs/core';
import { MsgEffect } from '@marblejs/messaging';
import { pipe } from 'fp-ts/lib/pipeable';

const foo$: MsgEffect = event$ =>
  event$.pipe(
    matchEvent('FOO'),
    act(event => pipe(
      doSomeWork(event),
      map(payload => ({ type: 'FOO_RESULT', payload })),
    )),
  );
```


# FAQ

## Does Marble.js uses Express underneath?

No! Express is a cool library but it shows its age. From the very beginning the aim of Marble.js was to build it from scratch with its own philosophy in mind. Thanks to the design decisions that were set at the beginning of its existence, Marble.js is faster than Express and comparable to the most performant HTTP libraries available on the Node.js platform.

## Why should I choose Marble.js?

There are many alternatives available on Node.js platform. Marble.js defines a uniform interface for asynchronous processing of incoming events, which makes the processing easy to adapt to different forms of transport protocols. Marble.js fits best in event-based architectures, like: CQRS, Event Sourcing or microservices, but you can also build a CRUD-like systems with ease without touching previously mentioned concepts. Besides that, if you like of functional programming you should definitely check it out.

## Why the heck I need here RxJS?

Despite the single event nature of basic HTTP, there are no contradictions against using it for single events, like in HTTP. Marble.js uses RxJS as a hammer for expressing asynchronous flow with monadic manner, even if you have to deal with only one event. Marble.js doesn't operate only over basic [HTTP](/docs/v3/http/effects) protocol but can be used also for both [WebSocket](/docs/v3/messaging/websockets) and event-based [messaging](/docs/v3/messaging/core-concepts/effects) patterns, where the multi-event nature fits best. Don't be scared of the complexity and abstractions presented in RxJS API — the Marble.js framework, in general, is incredibly simple.

## Does Marble.js has a built-in ORM support?

As a design decision, the framework focus areas are oriented around request/message processing, which means that Marble.js tries to be database agnostic in any aspect, allowing you to easily integrate with any SQL or NoSQL database provider or ORM framework. You have a number of options available to you, depending on your preferences.

## How to use Marble.js with GraphQL?

There is no official module for GraphQL yet. Sorry.


# Introduction

![](/files/-LDJDdlYVE7PgLeUq66C)

**Marble.js** is a functional reactive [Node.js](http://nodejs.org) framework for building **server-side** applications, based on [TypeScript](https://www.typescriptlang.org) and [RxJS](http://reactivex.io/rxjs).

{% hint style="info" %}
**Brace yourself Marble.js v3.0 is coming!**
{% endhint %}

{% embed url="<https://medium.com/@jflakus/announcing-marble-js-3-0-a-marbellous-evolution-ba9cdc91d591>" %}

## Philosophy

The core concept of **Marble.js** assumes that almost everything is a stream. The main building block of the whole framework is an Effect, which is just a function that returns a stream of events.

The purely functional languages like [Haskell](https://en.wikipedia.org/wiki/Haskell_\(programming_language\)) express side effects such as IO and other stateful computations using monadic actions. With the big popularity of [RxJS](http://rxjs.dev) Observable monad, you can create a referential transparent program specification made up of functions that may produce side effects like network, logging, database access, etc. Using its monadic nature we can map I/O operations over effects and flat them to bring in other sequences of operations. Marble.js is a functional reactive framework, that's why RxJS is a first class citizen here.

When looking at Marble.js you can ask: **"Why do we need RxJS for HTTP?"**. Despite the single event nature of basic HTTP, there are no contradictions against using it for single events. In Marble, RxJS is used as a hammer for expressing asynchronous flow with monadic manner, even if you have to deal with only one event passing over time. Marble.js doesn't operate only over basic [HTTP](/docs/v2/overview) protocol but can be used also for both [WebSocket](/docs/v2/websockets) and event sourcing purposes, where the multi-event nature fits best. Don't be scared of the complexity and abstractions presented in RxJS API — the Marble.js framework, in general, is incredibly simple. For more details about its specifics, please visit the next chapters that will guide you through the framework environment and implementation details.

*For those who are curious about the framework name - it comes from a popular way of visually expressing the time-based behavior of event streams, aka marble diagrams. This kind of domain-specific language is a popular way of testing asynchronous streams, especially in RxJS environments.*

{% hint style="success" %}
👉 If you have ever worked with libraries like [Redux Observable](https://redux-observable.js.org), [@ngrx/effects](https://github.com/ngrx/platform/blob/master/docs/effects/README.md) or other libraries that leverage functional reactive paradigm, you will feel like in home.
{% endhint %}

{% hint style="info" %}
👉 If you don't have any experience with functional reactive programming, we strongly recommend to gain some basic overview first with [ReactiveX intro](http://reactivex.io/intro.html) or with [The introduction to Reactive Programming you've been missing](https://gist.github.com/staltz/868e7e9bc2a7b8c1f754) written by [@andrestaltz](https://twitter.com/andrestaltz).
{% endhint %}

## Installation

**Marble.js** requires node **v8.0** or higher:

```bash
$ npm i @marblejs/core rxjs
```

or if you are a hipster:

```bash
$ yarn add @marblejs/core rxjs
```

## Examples

If you would like to get a quick glimpse of a simple RESTful API built with Marble.js, visit the following link:

{% content-ref url="/pages/-Ler2Smap1L-AGziPaTE" %}
[How does it glue​ together?](/docs/v2/overview/how-does-it-fit-together)
{% endcontent-ref %}

To view the example project, visit the [example](https://github.com/marblejs/example) repository.


# Overview

In this guide, we'll walk you through the basics of a Marble.js.

&#x20;After reading this chapter you will know how to:

* bootstrap a HTTP server
* create the basic REST API routing using *Effects*
* create you own and reuse build-in middlewares
* handle API errors

### *Getting started*

{% content-ref url="/pages/-LDRJ3VIi6Pd2us9\_vKy" %}
[Getting started](/docs/v2/overview/getting-started)
{% endcontent-ref %}

### Effects

{% content-ref url="/pages/-LDRMXWyBYY3cHs9NMj4" %}
[Effects](/docs/v2/overview/effects)
{% endcontent-ref %}

### Routing

{% content-ref url="/pages/-LDRN-W5HZ2wx3xRzuI-" %}
[Routing](/docs/v2/overview/routing)
{% endcontent-ref %}

### Middlewares

{% content-ref url="/pages/-LDRN65LZbLHGUs2oaIJ" %}
[Middlewares](/docs/v2/overview/middlewares)
{% endcontent-ref %}

### Error handling

{% content-ref url="/pages/-LDRNAmublBDucTZkteC" %}
[Error handling](/docs/v2/overview/error-handling)
{% endcontent-ref %}


# Getting started

## Installation

**Marble.js** requires node **v8.0** or higher:

```bash
$ npm i @marblejs/core @marblejs/middleware-logger @marblejs/middleware-body rxjs
```

or if you are a hipster:

```bash
$ yarn add @marblejs/core @marblejs/middleware-logger @marblejs/middleware-body rxjs
```

## Bootstrapping

The very basic configuration consists of two steps: *HTTP listener* definition and *HTTP server* configuration.

`httpListener` is the basic starting point of every Marble application. It includes definitions of all *middlewares* and API *effects*.

{% code title="http.listener.ts" %}

```typescript
import { httpListener } from '@marblejs/core';
import { logger$ } from '@marblejs/middleware-logger';
import { bodyParser$ } from '@marblejs/middleware-body';
import { api$ } from './api.effects';

const middlewares = [
  logger$(),
  bodyParser$(),
  // ...
];

const effects = [
  api$,
  // endpoint2$
  // ...
];

export default httpListener({ middlewares, effects });
```

{% endcode %}

And here is our simple "hello world" endpoint.

{% code title="api.effects.ts" %}

```typescript
import { r } from '@marblejs/core';
import { mapTo } from 'rxjs/operators';

export const api$ = r.pipe(
  r.matchPath('/'),
  r.matchType('GET'),
  r.useEffect(req$ => req$.pipe(
     mapTo({ body: 'Hello, world!' }),
  )));
```

{% endcode %}

To create Marble app instance, we can use [`createServer`](/docs/v2/api-reference/core/createserver), which is a wrapper around Node.js server creator with much more possibilities and goods inside. When created, it won't automatically start listening to given port and hostname until you call `.run()` method on it.

{% code title="server.ts" %}

```typescript
import { createServer } from '@marblejs/core';
import httpListener from './http.listener';

export const server = createServer({
  port: 1337,
  hostname: '127.0.0.1',
  httpListener,
});

server.run();
```

{% endcode %}

{% hint style="info" %}
you can always visit [example repository](https://github.com/marblejs/example) for a complete Marble.js app example.
{% endhint %}

We'll use [TypeScript](https://www.typescriptlang.org/) in the documentation but you can always write Marble apps in standard JavaScript (and any other language that transpiles to JavaScript).

To test run your server you can install `typescript` compiler and `ts-node`:

```bash
$ yarn add typescript ts-node
```

then add the following script to your `package.json` file:

```javascript
"scripts": {
  "start": "ts-node server.ts"
}
```

Now go ahead, create `server.ts`, `http.listener.ts`, `api.effects.ts` modules in your project and run your server:

```bash
$ yarn start
```

finally test your "functional" server by visiting [http://localhost:1337](/docs/v2/overview/getting-started)

{% hint style="info" %}
For more API specific details about server bootstraping, visit [createServer](/docs/v2/api-reference/core/createserver) API reference.
{% endhint %}

If you prefer to have standard Node.js control over server creation, you can also easily hook the app directly into Node.js `http.createServer`

{% code title="server.ts" %}

```typescript
import { createContext } from '@marblejs/core';
import * as http from 'http';
import httpListener from './http.listener';

const httpServer = httpListener
  .run(createContext());

export const server = http
  .createServer(httpServer)
  .listen(1337, '127.0.0.1');
```

{% endcode %}

In the next chapter you will learn how to create basic **Marble.js** endpoints using [Effects](/docs/v2/overview/effects).


# Effects

## **Hello, world!**

**Effect** is the main building block of the whole framework. It is just a function which returns a stream of events. Using its generic interface we can define API endpoints, [middlewares](/docs/v2/overview/middlewares), [error handlers](/docs/v2/overview/error-handling) and much more (see next chapters). Let's define our first "hello world" `HttpEffect`!

```typescript
const helloEffect$: HttpEffect = req$ => req$.pipe(
  mapTo({ body: 'Hello, world!' }),
);
```

The *Effect* above responds to incoming request with `Hello, world!` message. In Marble.js, every *Effect* tries to be referentailly transparent, which means that each incoming request has to be mapped to an object with attributes like `body`, `status` or `headers`. If the *status* code or *headers* are not defined, then the API by default responds with *200* status and *application/json* header.

In order to route our first *Effect,* we have to define the path and HTTP method that the incoming request should be matched to. The simplest implementation of an HTTP API endpoint can look like this.

{% tabs %}
{% tab title="effect-with-pipe.ts" %}

```typescript
const hello$ = r.pipe(
  r.matchPath('/'),
  r.matchType('GET'),
  r.useEffect(helloEffect$));
```

{% endtab %}

{% tab title="effect-with-EffectFactory.ts" %}

```typescript
const hello$ = EffectFactory
  .matchPath('/')
  .matchType('GET')
  .use(req$ => req$.pipe(
    mapTo({ body: `Hello, world!` })
  ));
```

{% endtab %}
{% endtabs %}

Lets define a little bit more complex endpoint.

{% tabs %}
{% tab title="postUser.effect.1.ts" %}

```typescript
const postUser$ = r.pipe(
  r.matchPath('/user'),
  r.matchType('POST'),
  r.useEffect(req$ => req$.pipe(
    map(req => req.body as User),
    mergeMap(Dao.postUser),
    map(response => ({ body: response }))
  )));
```

{% endtab %}

{% tab title="postUser.effect.2.ts" %}

```typescript
const postUser$ = EffectFactory
  .matchPath('/user')
  .matchType('POST')
  .use(req$ => req$.pipe(
    map(req => req.body),
    mergeMap(Dao.postUser),
    map(response => ({ body: response }))
  );
```

{% endtab %}
{% endtabs %}

The example above will match every *POST* request that matches to `/user` url. Using previously parsed *POST* body (see [bodyParser$](/docs/v2/api-reference/middleware-body) middleware) we can map it to example *DAO* which returns a `HttpEffectResponse` object as an action confirmation.

{% hint style="info" %}
Since Marble.js 2.0, you can build HTTP API routes using [`EffectFactory`](/docs/v2/api-reference/core/core-effectfactory) builder or using new, pipeable functions inside[`r.pipe`](/docs/v2/api-reference/core/r.pipe) function.
{% endhint %}

## HttpRequest

Every *HttpEffect* has an access to two most basics objects created by *http.Server*. **HttpRequest** is an abstraction over the basic *Node.js* [http.IncomingMessage](https://nodejs.org/dist/latest-v10.x/docs/api/http.html#http_class_http_incomingmessage) object. It may be used to access response status, headers and data, but in most scenarios you don't have to deal with all available APIs offered by *IncomingMessage* class. The most common properties available in request object are:

* *url*
* *method*
* *headers*
* *body (see* [*bodyParser$*](/docs/v2/api-reference/middleware-body) *section)*
* *params (see* [*routing*](/docs/v2/overview/routing) *chapter)*
* *query (see* [*routing*](/docs/v2/overview/routing) *chapter)*

{% hint style="info" %}
For more details about available API offered in `http.IncomingMessage`, please visit [official Node.js docummentation](https://nodejs.org/dist/latest-v10.x/docs/api/http.html#http_class_http_incomingmessage).
{% endhint %}

## HttpResponse

Like the previously described *HttpRequest*, the **HttpResponse** object is also an abstraction over basic *Node.js* [http.ServerResponse](https://nodejs.org/dist/latest-v10.x/docs/api/http.html#http_class_http_serverresponse) object. Besides the default API, the response object exposes an `res.send` method, which can be a handy wrapper over *Marble.js* responding mechanism. For more information about the *res.send* method, visit [Middlewares](/docs/v2/overview/middlewares#sending-a-response-earlier) chapter.

{% hint style="info" %}
For more details about the available API offered in `http.ServerResponse`, please visit [official Node.js docummentation](https://nodejs.org/dist/latest-v10.x/docs/api/http.html#http_class_http_serverresponse).
{% endhint %}


# Routing

Routing determines how an application responds to a client request to a particular endpoint, which is a path and a specific HTTP method (eg. GET, POST).

## Route composition

As we know - every API requires composable routing. Lets assume that we have a separate **User** feature where its API endpoints respond to *GET* and *POST* methods on `/user` path.

{% hint style="info" %}
Since Marble.js. v2.0, you can choose between two ways of defining HTTP routes - using [`EffectFactory`](/docs/v2/api-reference/core/core-effectfactory) or using [`r.pipe`](/docs/v2/api-reference/core/r.pipe) operators. In this example we will stick to the second, newer way, which has a more functional flavor and is more composable.
{% endhint %}

`r.pipe` is an indexed monad builder used for collecting information about Marble REST route details, like: *path*, request *method type*, *middlewares* and connected *Effect*.

{% tabs %}
{% tab title="user.effects.ts" %}

```typescript
import { combineRoutes, r } from '@marblejs/core';

const getUsers$ = r.pipe(
  r.matchPath('/'),
  r.matchType('GET'),
  r.useEffect(req$ => req$.pipe(
    // ...
  )));

const postUser$: r.pipe(
  r.matchPath('/'),
  r.matchType('POST'),
  r.useEffect(req$ => req$.pipe(
    // ...
  )));

export const user$ = combineRoutes(
  '/user',
  [ getUsers$, postUser$ ],
);
```

{% endtab %}
{% endtabs %}

Defined *HttpEffects* can be grouped together using `combineRoutes` function, which combines routing for a prefixed path passed as a first argument. Exported group of *Effects* can be combined with other *Effects* like in the example below.

{% tabs %}
{% tab title="api.effects.ts" %}

```typescript
import { combineRoutes, r } from '@marblejs/core';
import { user$ } from './user.effects';

const root$ = r.pipe(
  r.matchPath('/'),
  r.matchType('GET'),
  r.useEffect(req$ => req$.pipe(
    // ...
  )));

const foo$ = r.pipe(
  r.matchPath('/foo'),
  r.matchType('GET'),
  r.useEffect(req$ => req$.pipe(
    // ...
  )));

export const api$ = combineRoutes(
  '/api/v1',
  [ root$, foo$, user$ ],
);
```

{% endtab %}
{% endtabs %}

As you can see, the previously defined routes can be combined together, so as a result the routing is built in a much more structured way. If we analyze the above example, the routing will be mapped to the following routing table.

```
GET    /api/v1
GET    /api/v1/foo
GET    /api/v1/user
POST   /api/v1/user
```

There are some cases where there is a need to compose a bunch of middlewares before grouped routes, e.g. to authenticate requests only for a selected group of endpoints. Instead of composing middlewares using [use operator](/docs/v2/api-reference/core/operator-use) for each route separately, you can compose them via the extended second parameter in`combineRoutes()` function.

```typescript
const user$ = combineRoutes('/user', {
  middlewares: [authorize$],
  effects: [getUsers$, postUser$],
});
```

## Body parameters

Marble.js doesn't come with a built-in mechanism for parsing *POST*, *PUT* and *PATCH* request bodies. In order to get the parsed request body you can use dedicated *@marblejs/middleware-body* package. A new `req.body` object containing the parsed data will be populated on the request object after the middleware, or undefined if there was no body to parse, the `Content-Type` was not matched, or an error occurred. To learn more about body parsing middleware visit the [@marblejs/middleware-body](/docs/v2/api-reference/middleware-body) API specification.

{% hint style="danger" %}
All properties and values in `req.body`object are untrusted and should be validated before usage.
{% endhint %}

{% hint style="danger" %}
By design, the `req.body, req.params, req.query`are of type `unknown`. In order to work with decoded values you should validate them before (e.g. using dedicated validator middleware) or explictly assert attributes to the given type. We highly recommend to use the [@marblejs/middlware-io](/docs/v2/api-reference/middleware-io) package which allows you to properly infer the type of validated properties.
{% endhint %}

## URL parameters

The `combineRoutes` function and the `matchPath` allows you to define parameters in the path argument. All parameters are defined by the syntax with a colon prefix.

```typescript
const foo$ = r.pipe(
  r.matchPath('/:foo/:bar'),
  // ...
);
```

Decoded path parameters are placed in the `req.params` property. If there are no decoded URL parameters then the property contains an empty object. For the above example and route `/bob/12` the `req.params` object will contain the following properties:

```typescript
{
  foo: 'bob',
  bar: '12',
}
```

For parsing and decoding URL parameters, Marble.js makes use of [`path-to-regexp`](https://github.com/pillarjs/path-to-regexp) library.

{% hint style="danger" %}
All properties and values in `req.params` object are untrusted and should be validated before usage.
{% endhint %}

{% hint style="info" %}
You should validate incoming URL params using dedicated [requestValidator$](/docs/v2/api-reference/middleware-io) middleware.
{% endhint %}

Path parameters can be suffixed with an asterisk (`*`) to denote a zero or more parameter matches. The code snippet below shows an example use case of a "zero-or-more" parameter. For example, it can be useful for defining routing for static assets.

{% tabs %}
{% tab title="getFile.effect.ts" %}

```typescript
const getFile$ = r.pipe(
  r.matchPath('/:dir*'),
  r.matchType('GET'),
  r.useEffect(req$ => req$.pipe(
    // ...
    map(req => req.params.dir),
    mergeMap(readFile(STATIC_PATH)),
    map(body => ({ body }))
  )));
```

{% endtab %}
{% endtabs %}

## Query parameters

Except intercepting URL params, the routing is able to parse query parameters provided in path string. All decoded query parameters are located inside `req.query` property. If there are no decoded query parameters then the property contains an empty object. For parisng and decoding query parameters, Marble.js makes use of [`qs`](https://github.com/ljharb/qs) libray.

**Example 1:**

```
GET /user?name=Patrick
```

```typescript
req.query = {
  name: 'Patrick',
};
```

**Example 2:**

```
GET /user?name=Patrick&location[country]=Poland&location[city]=Katowice
```

```typescript
req.query = {
  name: 'Patrick',
  location: {
    country: 'Poland',
    city: 'Katowice',
  },
};
```

{% hint style="danger" %}
All properties and values in `req.query` object are untrusted and should be validated before usage.
{% endhint %}

{% hint style="info" %}
You should validate incoming `req.query` parameters using dedicated[ requestValidator$](/docs/v2/api-reference/middleware-io) middleware.
{% endhint %}


# Middlewares

It is a common requirement to encounter the necessity of having various operations needed around incoming HTTP requests to your server. In *Marble.js* middlewares are streams of side-effects that can be composed and plugged-in to our request lifecycle to perform certain actions before reaching the designated *Effect*.

## Building your own middleware

Because everything here is a stream, the plugged-in middlewares are also based on a similar *Effect* interface. By default, framework comes with composable middlewares like: [logging](/docs/v2/api-reference/middleware-logger), request [body parsing](/docs/v2/api-reference/middleware-body) or request [validator](/docs/v2/api-reference/middleware-io). Below you can see how simple can a dummy HTTP request logging middleware look.

```typescript
const logger$ = (req$: Observable<HttpRequest>, res: HttpResponse): Observable<HttpRequest> =>
  req$.pipe(
    tap(req => console.log(`${req.method} ${req.url}`)),
  );
```

In the example above we get a stream of requests, then tap the `console.log` side effect and return the same stream as a response from our middleware pipeline. The middleware, compared to the basic effect, must return the request at the end.

If you prefer shorter type definitions, you can use the `HttpMiddlewareEffect` function interface.

```typescript
const logger$: HttpMiddlewareEffect = (req$, res) =>
  req$.pipe(
    // ...
  );
```

In order to use our custom middleware, we need to attach the defined middleware to the `httpListener` config.

```typescript
const middlewares = [
  // 👇 our custom middleware 
  logger$,
];

const app = httpListener({ middlewares, effects });
```

### Parameterized middleware

There are some cases when our custom middleware needs to be parameterized - for example, the dummy *logger$* middleware should *console.log* request URL's conditionally. To achieve this behavior we can make our middleware function *curried*, where the last returned function should conform to`HttpMiddlewareEffect` interface.

```typescript
interface LoggerOpts {
  showUrl?: boolean;
}

const logger$ = (opts: LoggerOpts = {}): HttpMiddlewareEffect => req$ =>
  req$.pipe(
    tap(req => console.log(`${req.method} ${opts.showUrl ? req.url : ''}`)),
  );
```

The improved logging middleware, can be composed like in the following example:

```typescript
const middlewares = [
  // 👇 our custom middleware
  logger$({ showUrl: true }),
];
```

### Sending a response earlier

Some types of middlewares need to send an HTTP response earlier. For this case Marble.js exposes a dedicated `res.send` method which allows to send an HTTP response using the same common interface that we use for sending a response inside API *Effects*. The mentioned method returns an empty *Observable* (*Observable that immediately completes*) as a result, so it can be composed easily inside a middleware pipeline.

```typescript
const middleware$: HttpMiddlewareEffect = (req$, res) =>
  req$.pipe(
    switchMap(() => res.send({ body: 💩, status: 304, headers: /* ... */ }),
  );
```

If the HTTP response is sent ealier than inside the target Effect, the execution of all following middlewares and Effects will be skipped.

## Middlewares composition

In *Marble.js* you can compose middlewares in four ways:

* globally (inside `httpListener` configuration object),
* inside grouped effects (via `combineRoutes` function),
* or by composing it directly inside *Effect* request pipeline.

### via *Effect*

There are many scenarios where we would like to apply middlewares inside our API *Effects*. One of them is to authorize only specific endpoints. Going to meet the requirements, *Marble.js* allows us to compose them using dedicated [use operator](/docs/v2/api-reference/core/operator-use), directly inside request stream pipeline.

Lets say we have an endpoint for getting list of all users registered in the system, but we would like to make it secure, and available only for authorized users. All we need to do is to compose authorization middleware using dedicated for this case `use` operator which takes as an argument our middleware.

{% tabs %}
{% tab title="getUsers.effect.ts" %}

```typescript
import { use, r } from '@marblejs/core';
import { authorize$ } from './auth.middleware';

const getUsers$ = r.pipe(
  r.matchPath('/'),
  r.matchType('GET'),
  // 👇 here...
  r.use(authorize$),
  r.useEffect(req$ => req$.pipe(
    // 👇 or here...
    use(authorize$),
    // ...
  )));
```

{% endtab %}
{% endtabs %}

Using `r.pipe` operators, the middlwares can be composed in two ways. The first one doesn't infer the returned `HttpRequest` type of chained middlewares.

The example implementation of `authorize$` middleware can look like in the following snippet:

{% tabs %}
{% tab title="auth.middleware.ts" %}

```typescript
const authorize$: HttpMiddlewareEffect = req$ =>
  req$.pipe(
    mergeMap(req => iif(
      () => !isAuthorized(req),
      throwError(new HttpError('Unauthorized', HttpStatus.UNAUTHORIZED)),
      of(req),
    )),
  );
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
As you probably noticed, `auth.middleware` introduces an example use case of error handling. You can read more about it in dedicated [Error handling](/docs/v2/overview/error-handling) chapter.
{% endhint %}

### via *combineRoutes*

There are some cases where you have to compose a bunch of middlewares before grouped routes, e.g. to authorize only a selected group of endpoints. Instead of composing middlewares for each route separately, using [use operator](/docs/v2/api-reference/core/operator-use), you can also compose them via the extended second parameter in`combineRoutes()` function.

```typescript
const api$ = combineRoutes('api/v1', {
  middlewares: [ authorize$ ],
  effects: [ user$, movie$, actor$ ],
});
```

### via *httpListener*

If your middleware should operate globally, e.g. in case of request logging, the best place is to compose it inside `httpListener`. In this case the middleware will operate on each request that goes through your HTTP server.

```typescript
const middlewares = [
  logger$(),
  bodyParser$(),
];

const effects = [
  // ...
];

export default httpListener({ middlewares, effects });
```

{% hint style="info" %}
The stacking order of middlewares inside `httpListener` and `combineRoutes` matters, because middlewares are run sequentially (one after another).
{% endhint %}


# Error handling

## Error handling

Lets take a look again at the previous example of authorization middleware.

{% tabs %}
{% tab title="auth.middleware.ts" %}

```typescript
import { HttpError, HttpStatus } from '@marblejs/core';

const authorize$: HttpMiddlewareEffect = req$ =>
  req$.pipe(
    switchMap(req => iif(
      () => !isAuthorized(req),
      throwError(new HttpError('Unauthorized', HttpStatus.UNAUTHORIZED)),
      of(req),
    )),
  );
```

{% endtab %}
{% endtabs %}

*Marble.js comes with a dedicated `HttpError`* class for defining request related errors that can be caught easily via error middleware. Using the *RxJS* built-in `throwError` method, we can throw an error and catch it on an upper level (e.g. directly inside *Effect* or *ErrorEffect*).

The `HttpError` class resides in the `@marblejs/core` package. The constructor takes as a first parameter an error message and as a second parameter a `HttpStatus` code that can be a plain *JavaScript* `number` or *TypeScript* enum type that can also be imported via core package. Optionally you can pass the third argument, which can contain any other error related values.

```typescript
new HttpError('Forbidden', HttpStatus.FORBIDDEN, { resource: 'index.html' });
```

## 404 error handling

*404 (Not Found)* responses are not the result of an error, so the error handler will not capture them. This behavior is because a *404* response simply indicates the absence of matched *Effect* in request lifecycle; in other words, request didn't find a proper route. All you need to do is to define a dedicated *Effect* at the very end of the effects stack to handle a 404 response.

```typescript
const notFound$ = r.pipe(
  r.matchPath('*'),
  r.matchType('*'),
  r.useEffect(req$ => req$.pipe(
    mergeMap(() =>
      throwError(new HttpError('Route not found', HttpStatus.NOT_FOUND))
    )
  )));
```

The *HttpEffect* above handles **all** paths and **all** method types *\*\**&#x61;nd throws an 404 error code that can be intercepted via *HttpErrorEffect*.

`notFound$` *Effects* can be placed in any layer you want, eg. you can have multiple *Effects* that will handle missing routes in dedicated organization levels of your API structure.

## Custom error handling effect

By default *Marble.js* comes with simple and lightweight error handling *Effect*. Because middlewares and *Effects* are based on the same generic interface, your error handlers can work very similar.

{% tabs %}
{% tab title="error.middleware.ts" %}

```typescript
const customError$: HttpErrorEffect<ThrownError> = (req$, res, meta) =>
  req$.pipe(
    mapTo(meta.error),
    map(error => ({
     status: error.status
     body: error.data
    }),
  );
```

{% endtab %}
{% endtabs %}

As any other *Effect*, error handler maps the stream of errored requests to objects of type *HttpEffectResponse* (`status`, `body`, `headers`). The *HttpErrorEffect* can retrieve from the third argument an intercepted error object which can be used for error handling-related logic.

To connect the custom error handler, all you need to do is to attach it to `error$` property in `httpListener` config object.

{% tabs %}
{% tab title="http.listener.ts" %}

```typescript
httpListener({
  middlewares,
  effects,
  // Custom error effect 👇
  error$: customError$,
});
```

{% endtab %}
{% endtabs %}


# How does it glue​ together?

Writing REST API in Marble.js isn't hard as you might think. The developer has to understand mostly only the main building block which is the *Effect* and how the data flows through it.

The aim of this chapter is to demonstrate how building blocks described in previous chapters glue together. For ease of understaning lets build a tiny RESTful API for user handling. Lets omit the implementation details of database access and focus only on the Marble.js related things.

```typescript
import { createServer, combineRoutes, httpListener, r, HttpError, use, HttpStatus } from '@marblejs/core';
import { logger$ } from '@marblejs/middleware-logger';
import { bodyParser$ } from '@marblejs/middleware-body';
import { requestValidator$, t } from '@marblejs/middleware-io';
import { mergeMapTo, mergeMap, catchError, mapTo, map } from 'rxjs/operators';
import { of, throwError, from } from 'rxjs';


function getUserCollection() {
  return from([{ id: '1' }]);
}

function getUserById(id: string) {
  if (id !== '1') {
    throw new Error('User not found');
  }
  return of({ id: '1', name: 'Test' });
}

/*------------------------
  👇 USERS API definition
-------------------------*/

const getUserValidator$ = requestValidator$({
  params: t.type({
    id: t.string,
  }),
});

const getUserList$ = r.pipe(
  r.matchPath('/'),
  r.matchType('GET'),
  r.useEffect(req$ => req$.pipe(
    mergeMapTo(getUserCollection()),
    map(body => ({ body })),
  )),
);

const getUser$ = r.pipe(
  r.matchPath('/:id'),
  r.matchType('GET'),
  r.useEffect(req$ => req$.pipe(
    use(getUserValidator$),
    mergeMap(req$ => of(req$.params.id).pipe(
      mergeMap(getUserById),
      map(body => ({ body })),
      catchError(() => throwError(
        new HttpError('User does not exist', HttpStatus.NOT_FOUND)
      ))
    )),
  )),
);

const users$ = combineRoutes('/users', [
  getUser$,
  getUserList$,
]);


/*------------------------
  👇 ROOT API definition
-------------------------*/

const root$ = r.pipe(
  r.matchPath('/'),
  r.matchType('GET'),
  r.useEffect(req$ => req$.pipe(
    mapTo({ body: `API version: v1` }),
  )),
);

const notFound$ = r.pipe(
  r.matchPath('*'),
  r.matchType('*'),
  r.useEffect(req$ => req$.pipe(
    mergeMapTo(throwError(
      new HttpError('Route not found', HttpStatus.NOT_FOUND)
    )),
  )),
);

const api$ = combineRoutes('/api/v1', [
  root$,
  users$,
  notFound$,
]);


/*------------------------
  👇 SERVER definition
-------------------------*/

const middlewares = [
  logger$(),
  bodyParser$(),
];

const effects = [
  api$,
];

const server = createServer({
  port: 1337,
  httpListener: httpListener({ middlewares, effects }),
});

server.run();
```


# Advanced


# Context

> From version 2.0, **Marble.js** takes even bigger steps in being a **functional** reactive framework. Besides the monadic flavour of Effect streams we try to incorporate more functional patterns and concepts which can fit well in the framework ecosystem.

## Dependency Injection

Dependency Injection (DI) is a very simple concept, which can be implemented in many different ways. It means to get dependencies of a class passed in by using constructor, or to get dependencies of a function passed in by using arguments, or even more advanced techniques. If we step back and look at the concept in a more abstract way, the only thing to remember is that we gain the possibility to provide dependencies to any of our entities any point in time. Now we can provide different implementations of those dependencies by using extension (polymorphism), interface implementation, or whatever technique we want to use.

Marble.js comes to the DI concept in a different, more functional way, that can be very similar to popular pure functional languages like eg. Haskell. From version 2.0, Marble.js introduces a **Context**, which is an abstraction over Reader monad implementation of the DI system.

What [Haskell docs](http://hackage.haskell.org/package/mtl-2.2.2/docs/Control-Monad-Reader.html) says about the Reader monad?

> The [`Reader`](http://hackage.haskell.org/package/mtl-2.2.2/docs/Control-Monad-Reader.html#t:Reader) monad (also called the Environment monad), represents a computation, which can read values from a shared environment, pass values from function to function, and execute sub-computations in a modified environment. \[...]

## The basics

In Marble.js you don't have to create the app context explicitly. In order to create a basic environment you can use `createServer` function which prepares underneath a basic application context.

Every dependency that you would like to register inside the Context has to conform to `ContextReader` interface, which means that the registered function should be able to read from the bootstrapped server context. Knowing the basics, let's create some readers!

{% code title="example.ts" %}

```typescript
import { createContextToken, reader } from '@marblejs/core';

export const d1Token = createContextToken<string>();
export const d2Token = createContextToken<string>();

export const d1 = reader.map(() => 'Hello');
export const d2 = reader.map(ask =>
  ask(d1Token).map(v => v + ', world!').getOrElse('')
);
```

{% endcode %}

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

```typescript
import { bindTo createServer } from '@marblejs/core';
import { d1, d2, d1Token, d2Token } from './example';

createServer({
  // ...
  dependencies: [
    bindTo(d1Token)(d1),
    bindTo(d2Token)(d2),
  ],
  // ...
});
```

{% endcode %}

Having our dependencies defined, let's define some test Effect where we can test how our dependency can be consumed.

{% code title="example.effect.ts" %}

```typescript
import { r } from '@marblejs/core';
import { d2Token } from './example';

export const example$ = r.pipe(
  r.matchPath('/'),
  r.matchType('GET'),
  r.useEffect((req$, _, { ask }) => req$.pipe(
    mapTo(ask(d2Token).getOrElse('')),
    map(msg => ({ body: msg })),
  )));
```

{% endcode %}

The type safety is very important. If you are percipient, you'll notice that using previously defined `d2Token` together with provided dependency we can also grab its inferred type. Reading from the context is not safe every time, thats why the provided dependency is wrapped arround [`Option`](https://gcanti.github.io/fp-ts/Option.html) monad that you can work on. As you can see the real benefit of using Readers is to be able to provide that context in an implicit way without the need to state it explicitly on each one of the functions that needs it.

If you will try to do a `GET /` request, you should see in the `Hello, world!` message in the respone. Thats how Dependency Injection work in Marble.js!

## Eager vs lazy readers

Let's say you have a HTTP server that would like to connect with a WebSocket server. When bootstrapping a WebSocket server we want to instantiate it as soon as possible (aka eagerly). The Marble.js Context was designed with a need for flexible way of connecting dependent modules - eagerly and lazily.

**By default Instances are created lazily when they are needed**. If a dependency is never used by another component, then it won’t be created at all. This is usually what you want. For most components there’s no point creating them until they’re needed. However, in some cases you want dependencies to be started up straight away or even if they’re not used by another function. For example, you might want to send a message to a remote system, warm up a cache when the application starts or boostrapp a WebSocket server. You can force a dependency to be created eagerly by using an **eager binding**.

Lets look at an example of eagerly binding of a WebSocket server.

{% code title="tokens.ts" %}

```typescript
import { createContextToken } from '@marblejs/core';
import { MarbleWebSocketServer } from '@marblejs/websockets';

export const WsServerToken = createContextToken<MarbleWebSocketServer>();
```

{% endcode %}

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

```typescript
import { createServer, bindTo } from '@marblejs/core';
import { mapToServer } from '@marblejs/websockets';
import { WsServerToken } from './tokens';
import httpListener from './http.listener';
import webSocketListener from './ws.listener';

const server = createServer({
  port: 1337,
  httpListener,
  dependencies: [
    bindTo(WsServerToken)(webSocketListener({ port: 8080 }).run),
  ],
});

server.run();
```

{% endcode %}

In order to instantiate our registered dependency as soon as possible, you have to run it inside `bindTo` function. It means that the registered dependency will try to resolve its dependencies during the binding, using previously registered context.

{% hint style="warning" %}
Note that in order to run registered dependency eagerly you have the provide proper context by registering dependent component before the eager dependency.
{% endhint %}

```typescript
// lazy binding
bindTo(Token)(dependency());

// eager binding
bindTo(Token)(dependency().run);
```

Having the WebSocket dependency eagerly registered we can ask for it eg. inside HTTP Effect. Note that provided dependency won't be instantiated while asking - we can easily grab previously instantiated WebSocket server on demand. 😎

{% code title="http.listener.ts" %}

```typescript
import { httpListener } from '@marblejs/core';
import { requestValidator$ } from '@marblejs/middleware-io';
import { bodyParser$ } from '@marblejs/middleware-body';
import { WsServerToken } from './tokens';

const postItem$ = r.pipe(
  r.matchPath('/items'),
  r.matchType('POST'),
  r.useEffect((req$, _, { ask }) => req$.pipe(
    use(requestValidator$({ body: itemDto }),
    // ...
    tap(payload => ask(WsServerToken)
      .map(server => server.sendBroadcastResponse({ type: 'ADDED_ITEM', payload }))
      .getOrElse(EMPTY)),
    map(body => ({ body })),
  )));

export default httpListener({
  middlewares: [bodyParser$()],
  effects: [postItem$],
});
```

{% endcode %}


# Server events

The Node.js server after startup can emit a variety of different events that the app can listen to, eg. `upgrade`, `listening`, etc. As you know, streams are the main building block of Marble.js. **@marblejs/core** [createServer](/docs/v2/api-reference/core/createserver) function allows you to listen to emitted server events via exposed `event$` attribute, where you can hook your stream.

Similar to WebSocket and HTTP Effects, `HttpServerEffect` is used for dealing with stream of incoming server events, but in comparison to others, the Effect doesn't specify what will be the stream output.

```typescript
import { createServer, matchEvent, ServerEvent, HttpServerEffect, bindTo } from '@marblejs/core';

const listening$: HttpServerEffect = (event$, server, meta) =>
  event$.pipe(
    matchEvent(ServerEvent.listening),
    map(event => event.payload),
    tap(({ port, host }) => console.log(`Running @ http://${host}:${port}/`)),
  );

const server = createServer({
  // ...
  event$: (...args) => merge(
    listening$(...args),
    // ...
  ),
});

server.run();
```

As in the case of WebSockets, you can match incoming events using the same `matchEvent` operator.  `ServerEvent`  contains a full list of events that you can match to, preserving at the same time type correctness of matched events.

## Upgrading HTTP connections

> The [HTTP/1.1 protocol](https://developer.mozilla.org/en-US/docs/Web/HTTP) provides a special mechanism that can be used to upgrade an already established connection to a different protocol, using the [`Upgrade`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Upgrade) header field.
>
> This mechanism is optional; it cannot be used to insist on a protocol change. Implementations can choose not to take advantage of an upgrade even if they support the new protocol, and in practice, this mechanism is used mostly to bootstrap a WebSockets connection.
>
> \---\
> source: [MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Protocol_upgrade_mechanism)

```typescript
import { createServer, matchEvent, ServerEvent, HttpServerEffect, bindTo } from '@marblejs/core';
import { mapToServer } from '@marblejs/websockets';
import { WsServerToken } from './tokens';
import httpListener from './http.listener';
import webSocketListener from './ws.listener';

const upgrade$: HttpServerEffect = (event$, server, { ask }) =>
  event$.pipe(
    matchEvent(ServerEvent.upgrade),
    mapToServer({
      path: '/api/:version/ws',
      server: ask(WsServerToken),
    }),
  );

const server = createServer({
  port: 1337,
  httpListener,
  dependencies: [
    bindTo(WsServerToken)(webSocketListener().run),
  ],
  event$: (...args) => merge(
    upgrade$(...args),
    // ...
  ),
});

server.run();
```

Marble.js [Context](/docs/v2/advanced/context) API plays well also with HTTP server Effects. You can upgrade running WebSocket server using dedicated [`mapToServer`](/docs/v2/api-reference/websockets/operator-maptoserver) operator. This kind of mechanism allows you to hook multiple WebSocket servers into already running HTTP server on different paths.

```typescript
// `createServer`
bindTo(WsServerToken_1)(webSocketListener_1().run),
bindTo(WsServerToken_2)(webSocketListener_2().run),

// upgrade$
mapToServer({
  path: '/ws_1',
  server: ask(WsServerToken_1),
}, {
  path: '/ws_2',
  server: ask(WsServerToken_2),
}),
```


# Validation

This chapter will demonstrate how you can apply different validation strategies for the [@marblejs/middleware-io](/docs/v2/api-reference/middleware-io) validator using [io-ts](https://github.com/gcanti/io-ts) schemas.

[io-ts](https://github.com/gcanti/io-ts) is a nifty library that validates and checks at runtime that incoming data has the shape that you expect. This powerful library can extract a static type from the validator that is guaranteed to match any values that pass validation.

## String literals

You can create string literals using combination of `t.union` and `t.literal` codecs. Lets say that we would like to validate users that can contain different roles from the given set: `'ADMIN' | 'GUEST'`.

```typescript
const userSchema = t.type({
  id: t.string,
  name: t.string,
  roles: t.array(t.union([
    t.literal('ADMIN'),
    t.literal('GUEST'),
  ])),
});

type User = t.TypeOf<typeof userSchema>;

👇

type User = {
  id: string;
  name: string;
  roles: ('ADMIN' | 'GUEST')[];
};
```

## Branded types

[io-ts](https://github.com/gcanti/io-ts) allows you to create a custom codec validators that must match to given predicate. There are ton of use cases where you can use this mechanism, eg. you would like to validate users which are adult (age is bigger or equal 18).

```typescript
interface AgeAdultBrand {
  readonly AgeAdult: unique symbol;
}

const AdultAge = t.brand(
  t.number,
  (age): age is t.Branded<number, AgeAdultBrand> => age >= 18,
  'AgeAdult'
);

const userSchema = t.type({
  id: t.string,
  name: t.string,
  age: AdultAge,
}),

type User = t.TypeOf<typeof userSchema>;

👇

type User = {
  id: string;
  name: string;
  age: t.Branded<number, NumberAdultBrand>;
};
```

As you can see, [io-ts](https://github.com/gcanti/io-ts) requires some boilerplate in order to have it properly typed, but the benefits are invaluable.

## Optional properties

According to [io-ts](https://github.com/gcanti/io-ts) documentation you can define a validator with optional values as an intersection of optional and required properties.

```typescript
const StorySchema = t.intersection([
  t.type({
    type: t.literal('story'),
    commentsTotal: t.number,
  }),
  t.partial({
    description: t.string,
    url: t.string,
  })
]);

type Story = t.TypeOf<typeof StorySchema>;

👇

type Story = {
  type: 'story';
  commentsTotal: number;
} & {
  description?: string | undefined;
  url?: string | undefined;
}
```

As you can see in the example above, the generated `Story` type is not as clean as it might be. [Jasse Hallett](https://www.olioapps.com/blog/checking-types-real-world-typescript/) in his article proposed a slightly different approach to defining optional values in validator schemas. Lets define a handy `optional` combinator!

```typescript
export const optional = <T extends t.Any>(
  type: T,
  name = `${type.name} | undefined`
): t.UnionType<
  [T, t.UndefinedType],
  t.TypeOf<T> | undefined,
  t.OutputOf<T> | undefined,
  t.InputOf<T> | undefined
> =>
  t.union<[T, t.UndefinedType]>([type, t.undefined], name);
```

> Technically this implies that we expect the given property to be present in every case, but that the value might be `undefined`. In practice, that distinction often does not matter, and io-ts will validate an object that is missing a required property if the type of that property is allowed to be `undefined`.

Using the introduced combinator our `StorySchema` definition can be much more cleaner and readable.

```typescript
const StorySchema = t.type({
  type: t.literal('story'),
  commentsTotal: t.number,
  description: optional(t.string),
  url: optional(t.string),
});

type Story = t.TypeOf<typeof StorySchema>;

👇

type Story = {
  type: 'story';
  commentsTotal: number;
  description: string | undefined;
  url: string | undefined;
}
```


# Streaming

Node.js streams are collections of data that might not be available all at once, and they don’t have to fit in memory. This makes streams really powerful when working with large amounts of data, or data that’s coming from an external source one *chunk* at a time.

Since Marble.js **v2.1** you can send Node.js streams directly through *HttpEffectResponse* `body` attribute which will be piped internally as client response.

```typescript
import { r, combineRoutes, use } from '@marblejs/core';
import { requestValidator$, t } from '@marblejs/middleware-io';
import { readFile } from '@marblejs/core/dist/+internal';

const getFileValidator$ = requestValidator$({
  params: t.type({ dir: t.string })
});

const getFile$ = r.pipe(
  r.matchPath('/static/:dir*'),
  r.matchType('GET'),
  r.useEffect(req$ => req$.pipe(
    use(getFileValidator$),
    map(req => req.params.dir),
    map(dir => fs.createReadStream(path.resolve(STATIC_PATH, dir))),
    map(body => ({ body }))
  )),
);
```


# Output interceptor

[httpListener](/docs/v2/api-reference/core/core-httplistener) and [webSocketListener](/docs/v2/api-reference/websockets/websocketlistener) allows to intercept outgoing messages via `output$` attribute. Using `HttpOutputEffect` or `WsOutputEffect` you can grab an outgoing HTTP/Event response and map it into another form of outgoing message. Using this kind of response interceptor you can modify certain type of responses on demand. For example, in case of `Accept: application/vnd.api+json`  you would like to adjust the response accordingly to fit the needs of JSON API specification.

**HTTP:**

```typescript
import { HttpOutputEffect, httpListener } from '@marblejs/core';

const output$: HttpOutputEffect = res$ =>
  res$.pipe(
    map(res =>  ... ),
  );
  
export default httpListener({
  middlewares: [ ... ],
  effects: [ ... ],
  output$,
});
```

HTTP output interceptor allows you to grab the initial request via `EffectMetadata.initiator`. You can use it eg. for creating a compression middleware.

```typescript
import { HttpOutputEffect } from '@marblejs/core';

const output$: HttpOutputEffect = (res$, _, { initiator }) =>
  res$.pipe(
    map(res =>  {
      switch(initiator.headers['accept-encoding']) {
        case 'br':
          return ({
            ...res,
            headers: { ...res.headers, 'Content-Encoding': 'br' },
            body: res.body.pipe(zlib.createBrotliDecompress()),
          });
        case 'gzip':
          return ({
            ...res,
            headers: { ...res.headers, 'Content-Encoding': 'gzip' },
            body: res.body.pipe(zlib.createGunzip()),
          });
        case 'deflate':
          return ({
            ...res,
            headers: { ...res.headers, 'Content-Encoding': 'deflate' },
            body: res.body.pipe(zlib.createInflate()),
          });
        default:
          return res;
      }
    }),
  );
```

**WebSockets:**

```typescript
import { WsOutputEffect, webSocket } from '@marblejs/websockets';

const output$: WsOutputEffect = event$ =>
  event$.pipe(
    map(event =>  ... ),
  );
  
export default webSocketListener({
  middlewares: [ ... ],
  effects: [ ... ],
  output$,
});
```


# WebSockets

**@marblejs/websockets** module implements the [RFC 6455](https://www.google.com/url?sa=t\&rct=j\&q=\&esrc=s\&source=web\&cd=1\&ved=2ahUKEwiByOfquMPgAhWBpIsKHXWED_wQFjAAegQICRAB\&url=https%3A%2F%2Ftools.ietf.org%2Fhtml%2Frfc6455\&usg=AOvVaw06SuiDfKSSeLd0cvyIYrrM) WebSocket protocol, which means that by design it is not compatible with *Socket.io* or any other non-standard WS implementations. The module that will be introduced is based on lightweight [ws](https://github.com/websockets/ws) package.


# Getting started

## Installation

```
$ npm i @marblejs/websockets
```

or if you are a hipster:

```bash
$ yarn add @marblejs/websockets
```

## Bootstrapping

Like [*httpListener*](/docs/v2/api-reference/core/core-httplistener) the WebSocket module defines a similar way of bootstrapping the app. The [*webSocketListener*](/docs/v2/api-reference/websockets/websocketlistener) includes definitions of all *middlewares* and WebSocket *effects*.

{% code title="webSocket.listener.ts" %}

```typescript
const effects = [
  effect1$,
  effect2$,
  // ...
];

const middlewares = [
  middleware1$,
  middleware2$,
  // ...
];

export default webSocketListener({ effects, middlewares });
```

{% endcode %}

To connect the previously configured WebSocket listener, you have to create a context token first.

{% code title="tokens.ts" %}

```typescript
import { createContextToken } from '@marblejs/core';
import { MarbleWebSocketServer } from '@marblejs/websockets';

export const WebSocketServerToken = createContextToken<MarbleWebSocketServer>();
```

{% endcode %}

{% hint style="info" %}
You can learn more about Marble.js Context mechanism [here](/docs/v2/advanced/context).
{% endhint %}

Then all you have to do is to register the defined module inside *createServer* `dependencies`.

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

```typescript
import { bindTo createServer } from '@marblejs/core';
import { WebSocketServerToken } from './tokens.ts';
import httpListener from './http.listner.ts';
import webSocketListener from './webSocket.listner.ts';

const server = createServer({
  // ...
  httpListener,
  dependencies: [
    bindTo(WebSocketServerToken)(webSocketListener({ port: 8080 }).run),
  ],
  // ...
});

server.run();
```

{% endcode %}

You can create and run a WebSocket server by providing the port value in `webSocketListener` config object. You can also upgrade the currently running http server by providing `noServer: true` in config object or by ommiting it.

{% hint style="info" %}
If you are curious about other ways of bootstrapping the WebSocket server, reach out the [Server events](/docs/v2/advanced/server-events) chapter.
{% endhint %}


# Effects

Marble.js defines a common interface for many different kinds Effects. As you probably know, **@marblejs/core** defines a `HttpEffect` type for dealing with HTTP request streams. In case of **@marblejs/websockets**, the module defines a `WsEffect` which works within WebSocket protocol and deals with streams of Events.

## Hello, world!

Lets start with typical hello world example. The very basic implementation of WebSocket Effect can look like in the code snipped below.

{% code title="hello.ws-effect.ts" %}

```typescript
export const hello$: WsEffect = event$ =>
  event$.pipe(
    matchEvent('HELLO'),
    mapTo({ type: 'HELLO', payload: 'Hello, world!' }),
  );
```

{% endcode %}

Like any other Effect, it is just a function which returns a stream of outgoing events. As we previously mentioned, in case of WebSocket protocol, we have to deal with Events instead of requests.

The Effect above responds to *HELLO* events with `Hello, world!` message. In case of default `WsEffect` interface, each incoming event has to be mapped to an outgoing event which is just an object with `type` and `payload` attributes.

## Calculator

Lets do some cool math! In the next example we will try to build a very basic calculator using only streams! For the example purpose we will only need two Effects: the first that will match *ADD* events and the second that will match *SUM* events.

{% code title="calculator.effect.ts" %}

```typescript
import { use, matchEvent } from '@marblejs/core';
import { WsEffect } from '@marblejs/websockets';
import { t, eventValidator$ } from '@marblejs/middleware-io';
import { buffer, map } from 'rxjs/operators';

export const sum$: WsEffect = event$ =>
  event$.pipe(
    matchEvent('SUM')
  );

export const add$: WsEffect = (event$, ...args) =>
  event$.pipe(
    matchEvent('ADD'),
    use(eventValidator$(t.number)),
    buffer(sum$(event$, ...args)),
    map(events => events.reduce((a, e) => e.payload + a, 0)),
    map(payload => ({ type: 'SUM_RESULT', payload })),
  );
```

{% endcode %}

As you can see, the WebSocket protocol is an ideal place for dealing with reactive streams, especially in Marble.js. In the example above we did a little bit of RxJS magic using `buffer` operator, which buffers the source Observable values until closing notifier emits (in this case `sum$`). Additionaly to be sure that incoming *ADD* events are sent with payload of type number, we used [@marblejs/middleware-io](/docs/v2/api-reference/middleware-io) validator, which is able to infer payload type from defined schema.

Lets examine in steps how the server will respond to given equation: $$7 + 3 + 1$$&#x20;

```javascript
// #1 sent to server
{
  "type": "ADD",
  "payload": 7
}

// #2 sent to server
{
  "type": "ADD",
  "payload": 3
}

// #3 sent to server
{
  "type": "ADD",
  "payload": 1
}

// #4 sent to server
{
  "type": "SUM",
}

// #5 response from server
{
  "type": "SUM_RESULT",
  "payload": 11
}
```

Cool, right?! 😎 Don't forget to include the `add$` Effect in `webSocketListener`.

{% code title="webSocket.listener.ts" %}

```typescript
import { webSocketListener } from '@marblejs/websockets';
import { add$ } from './calculator.effect';

export const webSocketServer = webSocketListener({
  effects: [add$],
});

```

{% endcode %}


# Middlewares

## Custom middleware

Like any other Effect, Marble.js defines a similar way for defining middlewares. In case of WebSocket protocol it is a function that transforms *stream of incoming events* 👉 *stream of outgoing events*.

Lets create a simple logger middleware like we previously did in case of HTTP.

{% code title="logger.ws-middleware.ts" %}

```typescript
import { Event } from '@marblejs/core';
import { WsMiddlewareEffect } from '@marblejs/websockets';

export const logger$: WsMiddlewareEffect = event$ =>
  event$.pipe(
    tap(e => console.log(`type: ${e.type}, payload: ${e.payload}`)),
  );
  
// or an equivalent

export const logger$ = (event$: Observable<Event>): Observable<Event> =>
  event$.pipe(
    tap(e => console.log(`type: ${e.type}, payload: ${e.payload}`)),
  );
```

{% endcode %}

Similar to any other middleware or effect, we have to register it inside the listener.

{% code title="webSocket.listener.ts" %}

```typescript
import { webSocketListener } from '@marblejs/websockets';
import { logger$ } from './logger.ws-middleware';

export const webSocketServer = webSocketListener({
  middlewares: [logger$],
  // ...
});
```

{% endcode %}

## Middlewares composition

Similar to HTTP routes, you can compose middlewares in two ways:

* globally (inside `webSocketListener` configuration object),
* by composing it directly inside *Effect* event pipeline.

The [use](/docs/v2/api-reference/core/operator-use) operator availabe in [@marblejs/core](/docs/v2/api-reference/core) package allows you to compose multiple types of middlewares - not only HTTP-related. Lets examine how can we compose the [@marblejs/middleware-io](/docs/v2/api-reference/middleware-io) middleware in `event$` pipeline.

```typescript
import { use } from '@marblejs/core';
import { WsEffect } from '@marblejs/websockets';
import { eventValidator$, t } from '@marblejs/middleware-io';

const User = t.type({
  name: t.string,
  age: t.number,
});

export const createUser$: WsEffect = event$ =>
  event$.pipe(
    matchEvent('CREATE_USER'),
    use(eventValidator$(User)),
    // ...   event.payload: { name: string, age: number }
  );
```


# Error handling

## Error handling

The event nature of WebSocket protocol defines how app errors should be handled. Once a connection has been established between the client and the server, communitation between these two points should be handled only through events - that also concerns errors.

{% hint style="danger" %}
Avoid throwing exceptions explicitly when possible. If the exception is thrown, try to catch it and send *Event* instead.
{% endhint %}

```typescript
export const saveUser$: WsEffect = event$ =>
  event$.pipe(
    matchEvent('SAVE_USER'),
    map(event => event.payload),
    mergeMap(Dao.saveUser),
    catchError(error => of({
      type: 'SAVE_USER_ERROR',
      payload: error.message,
    })),
  );
```

If you are building a reusable middleware or you really need to throw an exception, [@marblejs/core](/docs/v2/api-reference/core) exports a dedicated event error constructor which can be intercepted via listener error handler. The `EventError` constructor takes as a first parameter an event object and as a second parameter a string message. Optionally you can pass the third argument, which can contain any other error related value.

```typescript
new EventError(event, 'some error message', additionalData);
```

## Custom error handling effect

By default *Marble.js* comes with simple and lightweight error handling effect, but you can define a custom one if you want.

{% code title="error.ws-effect.ts" %}

```typescript
export const customError$: WsErrorEffect<ThrownError> = (event$, client, meta) =>
  req$.pipe(
    map(event => ({
      type: 'ERROR',
      payload: meta.error.message
    }),
  );
```

{% endcode %}

As any other Effect, error handler maps the stream of errored events to objects of type *Event* (`type`, `payload`). The *WsErrorEffect* can retrieve from the third argument an intercepted error object which can be used for error handling-related logic.

To connect the custom error effect, all you have to do is to attach it to `error$` property in `webSocketListener` config object.

{% code title="webSocket.listener.ts" %}

```typescript
import { webSocketListener } from '@marblejs/websockets';
import { customError$ } from './error.ws-effect';

const webSocketServer = webSocketListener({
  middlewares,
  effects,
  // Custom error effect 👇
  error$: customError$,
});
```

{% endcode %}


# Connections handling

The WebSocket protocol doesn’t handle authorization or authentication. Practically, this means that a WebSocket opened from a page behind auth doesn’t “automatically” receive any sort of auth; you need to take steps to *also* secure the WebSocket connection.

This can be done in a variety of ways, as WebSockets will pass through standard HTTP headers commonly used for authentication. This means you could use the same authentication mechanism you’re using on WebSocket connections as well.

The first possible solution assumes that the client will be authenticated during initial WebSocket connection. The `webSocketListener` config exposes a `connection$` stream of incoming connections that the developer can listen to and do some action on it. For example we can validate the incoming request headers and check for JWT token validity. In negative scenario we should throw an connection error with reason why it failed, and in positive scenario we should just pass the request through.

```typescript
import {
  webSocketListener,
  WebSocketConnectionError,
  WsConnectionEffect,
} from '@marblejs/websockets';

const connection$: WsConnectionEffect = req$ =>
  req$.pipe(
    mergeMap(req => iif(
      () => !isAuthorized(req)
      throwError(new WebSocketConnectionError('Unauthorized', 4000)),
      of(req),
    )),
  );
  
export const webSocketServer = webSocketListener({
  middlewares,
  effects,
  connection$,
});
```


# core

This section documents the complete @marblejs/core package API.


# bindTo

Binds injection token to dependency.

### **Importing** <a href="#importing" id="importing"></a>

```typescript
import { bindTo } from '@marblejs/core';
```

### **Type declaration**

```
bindTo ::  ContextToken -> ContextDependency -> BoundDependency
```

### **Example**

Bind context token to basic types (eg. object):

```typescript
import { reader, bindTo, createServer, createContextToken } from '@marblejs/core';

const config: Config = { /* ... */ };
const configReader = reader.map(() => config);
const Token = createContextToken<Config>();

// ----------------

createServer({
  // ...
  dependencies: [
    bindTo(Token)(configReader),
  ],
});
```

Bind context token to injectable factory function:

```typescript
import { reader, bindTo, createServer, createContextToken } from '@marblejs/core';

const fooReader = reader.map(ctx => {
  const dependency = context.get(...);
  // ...
};
const Token = createContextToken<Foo>();

// ----------------

createServer({
  // ...
  dependencies: [
    bindTo(Token)(fooReader);
  ],
});
```


# createServer

Marble.j abstraction over Node.js server creation with additional features.

### I**mporting**

```typescript
import { createServer } from '@marblejs/core';
```

### **Type declaration**

```
createServer ::  CreateServerConfig -> Server
```

### **Parameters**

| *parameter* | definition           |
| ----------- | -------------------- |
| *config*    | `CreateServerConfig` |

#### ***CreateServerConfig***

| *parameter*    | definition                                |
| -------------- | ----------------------------------------- |
| *httpListener* | `HttpListener`                            |
| *port*         | \<optional> `number`                      |
| *hostname*     | \<optional> `string`                      |
| *event$*       | \<optional> `HttpServerEffect`            |
| *options*      | \<optional> `ServerOptions`               |
| *dependencies* | \<optional> `Array<BoundDependency<any>>` |

### Returns

| parameter | definitoin                                |
| --------- | ----------------------------------------- |
| *run*     | `boolean? -> https.Server \| http.Server` |
| *info*    | `ServerInfo`                              |
| *server*  | `https.Server \| http.Server`             |

***ServerInfo***

| parameter | definitoin           |
| --------- | -------------------- |
| *routing* | `Array<RoutingItem>` |

### **Example**

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

```typescript
import httpListener from './http.listener';
import { createServer, bindTo } from '@marblejs/core';

const httpsOptions: https.ServerOptions = {
  key: fs.readFileSync('key.pem'),
  cert: fs.readFileSync('cert.pem'),
};

export const server = createServer({
  port: 1337,
  hostname: '127.0.0.1',
  httpListener,
  dependencies: [
    bindTo(fooToken)(foo),
  ],
  event$: (...args) => merge(
    listening$(...args),
    upgrade$(...args),
  ),
  options: { httpsOptions },
});

server.run(
  process.env.NODE_ENV !== 'test'
);
```

{% endcode %}


# combineRoutes

Combines routing for different Effects, prefixed with path passed as a first argument.

### **Importing**

```typescript
import { combineRoutes } from '@marblejs/core';
```

### **Type declaration**

```
combineRoutes :: (string, RouteCombinerConfig) -> RouteEffectGroup
combineRoutes :: (string, (RouteEffect | RouteEffectGroup)[]) -> RouteEffectGroup
```

### **Parameters**

| *parameter*       | definition                                                      |
| ----------------- | --------------------------------------------------------------- |
| *path*            | `string`                                                        |
| *configOrEffects* | `RouteCombinerConfig \| Array<RouteEffect \| RouteEffectGroup>` |

#### ***RouteCombinerConfig***

| *parameter* | definition                                |
| ----------- | ----------------------------------------- |
| effects     | `Array<RouteEffect \| RouteEffectGroup>`  |
| middlewares | \<optional> `Array<HttpMiddlewareEffect>` |

### Returns

Factorized `RouteEffectGroup` object.

### Example

{% code title="user.effects.ts" %}

```typescript
import { combineRoutes } from '@marblejs/core';
import { authorize$ } from 'auth.middleware';

// const getUsers$ = ...
// const postUser$ = ...

export const user$ = combineRoutes('/user', {
  middlewares: [authorize$],
  effects: [getUsers$, postUser$],
});
```

{% endcode %}

{% code title="api.effects.ts" %}

```typescript
import { combineRoutes } from '@marblejs/core';
import { user$ } from './user';

// const root$ = ...
// const notFound$ = ...

export const api$ = combineRoutes('/api/v1', [
  root$, user$, notFound$,
]);
```

{% endcode %}


# createContextToken

A lookup token associated with a dependency provider, for use with the Marble.js context system.

### **Importing** <a href="#importing" id="importing"></a>

```typescript
import { createContextToken } from '@marblejs/core';
```

### **Type declaration**

```
createContextToken :: () -> ContextToken
```

### **Example**

The following example creates and associates injection token with Marble.js WebSocket server.

```typescript
import { createContextToken } from '@marblejs/core';
import { MarbleWebSocketServer } from '@marblejs/websockets';

export const WebSocketServerToken = createContextToken<MarbleWebSocketServer>();
```


# EffectFactory

Set of factory functions for building router Effect.

## **Importing**

```typescript
import { EffectFactory } from '@marblejs/core';
```

## + **matchPath**

`EffectFactory` namespace function. Matches request path for connected *Effect*.

### **Type declaration**

```typescript
matchPath :: string -> matchType
```

### **Parameters**

| *parameter* | definition |
| ----------- | ---------- |
| *path*      | `string`   |

### Returns

EffectFactory `matchType` function

## + **matchType**

`EffectFactory` namespace function. Matches HTTP method type for connected *Effect*.

### **Type declaration**

```typescript
matchType :: HttpMethod -> use
```

### **Parameters**

| *parameter* | definition                                                                                                          |
| ----------- | ------------------------------------------------------------------------------------------------------------------- |
| *type*      | `HttpMethod = 'POST \| 'PUT' \| 'PATCH' \| 'GET' \| 'HEAD' \| 'DELETE' \| 'CONNECT' \| 'OPTIONS' \| 'TRACE' \| '*'` |

### Returns

EffectFactory *`use`* function

## + **use**

`EffectFactory` namespace function. Connects *Effect* with path and HTTP method type.

### **Type declaration**

```typescript
use :: HttpEffect -> RouteEffect
```

### **Parameters**

| *parameter* | definition            |
| ----------- | --------------------- |
| *effect*    | `HttpEffect` function |

### Returns

Factorized `RouteEffect` object.

## Example

{% code title="root.effect.ts" %}

```typescript
import { EffectFactory } from '@marblejs/core';

export const root$ = EffectFactory
  .matchPath('/')
  .matchType('GET')
  .use(req$ => req$.pipe(
    mapTo({ body: `Hello, world! 👻` })
  ));
```

{% endcode %}


# r.pipe

HttpEffect route builder based on IxMonad

## **Importing**

```typescript
import { r } from '@marblejs/core';
```

## + pipe

`r` namespace function. Creates pipeable *RouteEffect* builder.

### **Type declaration**

```typescript
pipe :: ...Arity<IxBuilder, IxBuilder> -> RouteEffect
```

{% hint style="danger" %}
`r.pipe` builder pays attention to the order of applied operators.
{% endhint %}

```typescript
const example$ = r.pipe(
  r.matchPath('/'),
  r.matchType('GET'),
  r.use(middleware_1$),
  r.useEffect(req$ => req$.pipe(
    // ...
  )),
  r.use(middleware_2$), // ❌ type error!
);

// or 

const example$ = r.pipe(
  r.matchType('GET'),
  r.matchPath('/'), // ❌ type error!
  r.use(middleware_1$),
  r.use(middleware_2$), 
  r.useEffect(req$ => req$.pipe(
    // ...
  )),
);
```

**Correct order:**

1. **`matchPath`**
2. **`matchType`**
3. **`use`** ...
4. **`useEffect`**
5. **`applyMeta` ...**

## + **matchPath**

`r` namespace function. Matches request path for connected *HttpEffect*.

### **Type declaration**

```typescript
matchPath :: string -> IxBuilder -> IxBuilder
```

### **Parameters**

| *parameter* | definition |
| ----------- | ---------- |
| *path*      | `string`   |

## + **matchType**

`r` namespace function. Matches HTTP method type for connected *HttpEffect*.

### **Type declaration**

```typescript
matchType :: HttpMethod -> IxBuilder -> IxBuilder
```

### **Parameters**

| *parameter* | definition   |
| ----------- | ------------ |
| *path*      | `HttpMethod` |

## + use

`r` namespace function. Registers HTTP middleware with connected *HttpEffect.*

### **Type declaration**

```typescript
use :: HttpMiddlewareEffect -> IxBuilder -> IxBuilder
```

### **Parameters**

| *parameter*  | definition             |
| ------------ | ---------------------- |
| *middleware* | `HttpMiddlewareEffect` |

## + useEffect

`r` namespace function. Registers *HttpEffect.*

### **Type declaration**

```typescript
useEffect :: HttpEffect -> IxBuilder -> IxBuilder
```

### **Parameters**

| *parameter* | definition   |
| ----------- | ------------ |
| *effect*    | `HttpEffect` |

## + applyMeta

`r` namespace function. Applies metadata to connected *HttpEffect*.

### **Type declaration**

```typescript
applyMeta :: Record<string, any> -> IxBuilder -> IxBuilder
```

### **Parameters**

| *parameter* | definition            |
| ----------- | --------------------- |
| meta        | `Record<string, any>` |

## Example

```typescript
import { r } from '@marblejs/core';

const example$ = r.pipe(
  r.matchPath('/'),
  r.matchType('GET'),
  r.use(middleware_1$),
  r.use(middleware_2$),
  r.useEffect(req$ => req$.pipe(
    // ...
  )),
  r.applyMeta({ meta_1: /* ... */ }),
  r.applyMeta({ meta_1: /* ... */ }),
);
```


# httpListener

Starting point of every Marble.js application. It includes definitions of all middlewares and API effects.

### **Importing**

```typescript
import { httpListener } from '@marblejs/core';
```

### **Type declaration**

```typescript
httpListener :: HttpListenerConfig -> (IncomingMessage, OutgoingMessage) -> void;
```

### **Parameters**

| *parameter* | definition                     |
| ----------- | ------------------------------ |
| *config*    | `HttpListenerConfig`           |
| *req*       | Node.js `Http.IncomingMessage` |
| res         | Node.js `Http.OutgoingMessage` |

#### ***HttpListenerConfig***

| *parameter*   | definition                                |
| ------------- | ----------------------------------------- |
| *effects*     | `Array<RouteEffect \| RouteEffectGroup>`  |
| *middlewares* | \<optional> `Array<HttpMiddlewareEffect>` |
| *error$*      | \<optional> `HttpErrorEffect`             |

### Returns

Besides the default http server handler, the `httpListener` returns also an configuration object.

| parameter | definitoin           |
| --------- | -------------------- |
| *routing* | `Array<RoutingItem>` |
| injector  | `StaticInjector`     |

### **Example**

{% code title="http.listener" %}

```typescript
import { httpListener } from '@marblejs/core';
import { bodyParser$ } from '@marblejs/middleware-body';
import { logger$ } from '@marblejs/middleware-logger';
import { api$ } from './api';

const middlewares = [
  logger$(),
  bodyParser$(),
];

const effects = [
  api$,
];

export default httpListener({ middlewares, effects });
```

{% endcode %}


# operator: matchEvent

Effect operator for matching incoming events.

### Importing

```typescript
import { matchEvent } from '@marblejs/core';
```

### **Type declaration**

```typescript
matchEvent :: (EventLike | EventCreator) -> Observable<Event> -> Observable<Event>
```

### Example

***WebSockets:***

```typescript
import { matchEvent } from '@marblejs/core';
import { WsEffect } from '@marblejs/websockets';

const add$: WsEffect = event$ =>
  event$.pipe(
    matchEvent('ADD'),
    map(event => event.payload), // (typeof payload) = unknown
    // ...
  );
```

***HttpServerEffect:***

```typescript
import { matchEvent, HttpServerEffect, ServerEvent } from '@marblejs/core';

const listening$: HttpServerEffect = event$ =>
  event$.pipe(
    matchEvent(ServerEvent.listening),
    map(event => event.payload), // (typeof payload) = { port: number; host: string; }
    // ...
  );
```


# operator: use

Effect operator for composing middleware directly inside stream pipeline.

### **Importing**

```typescript
import { use } from '@marblejs/core';
```

### **Type declaration**

```typescript
use :: <I, O>(MiddlewareLike<I, O>, <?>any, <?>any) -> Observable<I>
```

### **Parameters**

| *parameter*  | definition                                     |
| ------------ | ---------------------------------------------- |
| *middleware* | `MiddlewareLike`                               |
| *client*     | <*optional*> protocol specific client instance |
| *meta*       | *\<optional>* `EffectMetadata`                 |

### **Returns**

`Observable<I>`

### Example

```typescript
import { r, use } from '@marblejs/core';

const foo$ = r.pipe(
  r.matchPath('/'),
  r.matchType('GET'),
  r.useEffet(req$ => req$.pipe(
    // ...
    use(authorize$),
    // ...
  )));
```


# websockets

This section documents the complete @marblejs/websockets package API.


# webSocketListener

### **Importing**

```typescript
import { webSocketListener } from '@marblejs/websockets';
```

### **Type declaration**

```typescript
webSocketListener :: WebSocketListenerConfig -> WebSocket.ServerOptions -> ContextReader
```

### **Parameters**

| *parameter* | definition                |
| ----------- | ------------------------- |
| *config*    | `WebSocketListenerconfig` |

#### ***WebSocketListenerConfig***

| *parameter*      | definition                              |
| ---------------- | --------------------------------------- |
| *effects*        | \<optional> `Array<WsEffect>`           |
| *middlewares*    | \<optional> `Array<WsMiddlewareEffect>` |
| *error$*         | \<optional> `WsErrorEffect`             |
| connection$      | \<optional> `WsConnectionEffect`        |
| output$          | \<optional> `WsOutputEffect`            |
| eventTransformer | \<optional> `EventTransformer`          |

### **Example**

{% code title="websocket.listener.ts" %}

```typescript
import { webSocketListener } from '@marblejs/websockets';
import { example$ } from './example.effect';
import { logger$ } from './logger.middleware';

export default webSocketListener({
  middlewares: [logger$],
  effects: [add$],
});
```

{% endcode %}


# operator: broadcast

Under construction 💩


# operator: mapToServer

Under construction 💩


# middleware-body

HTTP request body parser middleware for Marble.js.

### Installation

```bash
$ npm i @marblejs/middleware-body
```

Requires `@marblejs/core` to be installed.

### Importing

```typescript
import { bodyParser$ } from '@marblejs/middleware-body';
```

### Type declaration <a href="#type-declaration" id="type-declaration"></a>

```
bodyParser$ :: BodyParserOptions -> HttpMiddlewareEffect
```

### Parameters

| parameter | definition                      |
| --------- | ------------------------------- |
| *options* | \<optional> `BodyParserOptions` |

***BodyParserOptions***

| ***parameter*** | definition                      |
| --------------- | ------------------------------- |
| *parser*        | \<optional> `RequestBodyParser` |
| *type*          | \<optional> `Array<string>`     |

The `type` option is used to determine what media type the middleware will parse. It is passed directly to the [type-is](https://www.npmjs.org/package/type-is#readme) library and this can be an extension name (like `json`), a mime type (like `application/json`), or a mime type with a wildcard (like `*/*` or `*/json`). Defaults to `*/*`.

### Basic usage

{% code title="app.ts" %}

```typescript
import { bodyParser$ } from '@marblejs/middleware-body';

export default httpListener({
  middlewares: [bodyParser$()],
  effects: [/* ... */],
});
```

{% endcode %}

Lets assume that we have the following *CURL* command, which triggers `POST /api/login` endpoint:

```bash
$ curl --header "Content-Type: application/json" \
  --request POST \
  --data '{ "username": "foo", "password": "bar" }' \
  http://localhost:3000/api/login
```

Using previously connected `bodyParser$`  middleware, the app will intercept the following payload object:

```typescript
req.body = {
  username: 'foo',
  password: 'bar',
};
```

The *POST* request body can be intercepted like follows.

{% code title="login.effect.ts" %}

```typescript
import { r } from '@marblejs/core';

export const login$ = r.pipe(
  r.matchPath('/login'),
  r.matchType('POST'),
  r.useEffect(req$ => req$.pipe(
    map(req => req.body as { username: string, password: string })
    map(body => ({ body: `Hello, ${body.username}!` }))
  )));
```

{% endcode %}

{% hint style="danger" %}
All properties and values in `req.body` object are untrusted (unknown) and should be validated before trusting.
{% endhint %}

{% hint style="info" %}
This middleware does not handle multipart bodies.
{% endhint %}

### Advanced usage

The middleware does nothing if request *Content-Type* is not matched, which makes a possibility for chaining multiple parsers one after another. For example, we can register multiple middlewares that will parse only a certain set of possible *Content-Type* headers.&#x20;

**Default parser:**

```typescript
import { bodyParser$ } from '@marblejs/middleware-body';

bodyparser$();
```

Parses *application/json* (to JSON), *application/x-www-form-urlencoded* (to JSON), *application/octet-stream* (to Buffer) and *text/plain* (to string) content types

**JSON parser:**

```typescript
import { bodyParser$, jsonParser } from '@marblejs/middleware-body';

bodyParser$({
  parser: jsonParser,
  type: ['*/json', 'application/vnd.api+json'],
})
```

Parses `req.body` to JSON object.

**URLEncoded parser:**

```typescript
import { bodyParser$, urlEncodedParser } from '@marblejs/middleware-body';

bodyParser$({
  parser: urlEncodedParser,
  type: ['*/x-www-form-urlencoded'],
});
```

Parses encoded URLs `req.body` to JSON object.

**Text parser:**

```typescript
import { bodyParser$, textParser } from '@marblejs/middleware-body';

bodyParser$({
  parser: textParser,
  type: ['text/*'],
});
```

Parses `req.body` to string.

**Raw parser:**

```typescript
import { bodyParser$, rawParser } from '@marblejs/middleware-body';

bodyParser$({
  parser: rawParser,
  type: ['application/octet-stream'],
}),
```

Parses `req.body` to Buffer.

### Custom parsers

If the available parsers are not enough, you can create your own body parsers by conforming to `RequestBodyParser` interface. The example below shows how the `jsonParser` looks underneath.

```typescript
export const jsonParser: RequestBodyParser = req => body =>
  JSON.parse(body.toString());
```


# middleware-logger

HTTP request logger middleware for Marble.js

**Simple** middleware for request logging inside your console. It displays the outgoing request events using the following format:

```
{HTTP_METHOD} {PATH} {HTTP_STATUS} {TIME}
```

```
POST /api/v1/user 200 1ms
```

### Installation

```bash
$ npm i @marblejs/middleware-logger
```

Requires `@marblejs/core` to be installed.

### Importing

```typescript
import { logger$ } from '@marblejs/middleware-logger';
```

### Type declaration

```
logger$ :: LoggerOptions -> HttpMiddlewareEffect
```

### **Parameters**

| *parameter* | definition                  |
| ----------- | --------------------------- |
| *options*   | \<optional> `LoggerOptions` |

#### ***LoggerOptions***

| *parameter* | definition                                           |
| ----------- | ---------------------------------------------------- |
| *silent*    | \<optional> `boolean`                                |
| *stream*    | \<optional> `WritableLike`                           |
| *filter*    | \<optional> `(HttpResponse, HttpRequest) => boolean` |

### Usage

1. Default behaviour. Log every response to *process*.*stdout*:

{% code title="logger.middleware.ts" %}

```typescript
import { logger$ } from '@marblejs/middleware-logger';

const middlewares = [
  logger$(),
  ...
];

export const app = httpListener({ middlewares, effects: [] });
```

{% endcode %}

2\. Customized logging behaviour:

{% code title="logger.middleware.ts" %}

```typescript
import { logger$ } from '@marblejs/middleware-logger';
import { isTestEnv } from './util';

const middlewares = [
  logger$({
    silent: isTestEnv(),
    stream: createWriteStream(PATH, { flags: 'a' });;
    filter: (res, req) => res.status >= 400;
  }),
  ...
];

export const app = httpListener({ middlewares, effects: [] });
```

{% endcode %}

* **silent** - When `true` the logging is turned off (usually useful during testing),
* **stream** - Output stream for writing log messages, defaults to *process.stdout*. In the example above every response will be written to file pointed by provided `PATH` variable,
* **filter** - Filter outgoing responses or incoming requests based on given predicate. For example we can log only HTTP status codes above *400*.


# middleware-io

A data validation middleware based on awesome [io-ts](https://github.com/gcanti/io-ts) library authored by [*gcanti*](https://github.com/gcanti).

### Installation

```bash
$ npm i @marblejs/middleware-io
```

Requires `@marblejs/core` to be installed.

### Importing

```typescript
// HTTP
import { requestValidator$ } from '@marblejs/middleware-io';

// Events, eg. WebSockets
import { eventValidator$ } from '@marblejs/middleware-io';
```

### Type declaration <a href="#type-declaration" id="type-declaration"></a>

```
requestValidator$ :: (RequestSchema, ValidatorOptions) -> Observable<HttpRequest> -> Observable<HttpRequest>
eventValidator$ :: (Schema, ValidatorOptions) -> Observable<Event> -> Observable<Event>
```

### Parameters

***requestValidator$***

| parameter | definition                                                                  |
| --------- | --------------------------------------------------------------------------- |
| *schema*  | `Partial<RequestSchema>`(see [io-ts](https://github.com/gcanti/io-ts) docs) |
| *options* | \<optional> `ValidatorOptions`                                              |

***eventValidator$***

| parameter | definition                                                   |
| --------- | ------------------------------------------------------------ |
| *schema*  | `Schema` (see [io-ts](https://github.com/gcanti/io-ts) docs) |
| *options* | \<optional> `ValidatorOptions`                               |

***ValidatorOptions***

| parameter  | definition             |
| ---------- | ---------------------- |
| *reporter* | \<optional> `Reporter` |
| *context*  | \<optional> `string`   |

### Usage

Let's define a user schema that will be used for I/O validation.

{% code title="user.schema.ts" %}

```typescript
export const userSchema = t.type({
  id: t.string,
  firstName: t.string,
  lastName: t.string,
  roles: t.array(t.union([
    t.literal('ADMIN'),
    t.literal('GUEST'),
  ])),
});

export type User = t.TypeOf<typeof userSchema>;
```

{% endcode %}

```typescript
import { use, r } from '@marblejs/core';
import { requestValidator$, t } from '@marblejs/middleware-io';
import { userSchema } from './user.schema.ts';

const effect$ = r.pipe(
  r.matchPath('/'),
  r.matchType('POST'),
  r.useEffect(req$ => req$.pipe(
    use(requestValidator$({ body: userSchema })),
    // ..
  )));
```

{% hint style="info" %}
For more validation use cases and recipes, visit [Validation](/docs/v2/advanced/validation) chapter.
{% endhint %}

You can also reuse the same schema for Events validation if you want.

```typescript
import { matchEvent, use } from '@marblejs/core';
import { WsEffect } from '@marblejs/websockets';
import { eventValidator$, t } from '@marblejs/middleware-io';
import { userSchema } from './user.schema.ts';

const postUser$: WsEffect = event$ =>
  event$.pipe(
    matchEvent('CREATE_USER'),
    use(eventValidator$(userSchema)),
    // ...
  );
```

The inferred `req.body` / `event.payload` type of provided schema, will be of the following form:

```typescript
type User = {
  id: string;
  firstName: string;
  lastName: string;
  roles: ('ADMIN' | 'GUEST')[];
};
```

### Validation errors

Lets take a look at the default reported validation error thrown by `eventValidator$` . Let's assume that client passed wrong values for `firstName` and `roles`  fields.

```javascript
payload.lastName = false;
payload.roles = ['TEST'];
```

The reported error intercepted via default error effect will look like follows.

```javascript
{
  type: 'CREATE_USER',
  error: {
    message: 'Validation error',
    data: [
      {
        path: 'lastName',
        expected: 'string',
        got: 'false'
      },
      {
        path: 'roles.0.0',
        got: '"TEST"',
        expected: '"ADMIN"'
      },
      {
        path: 'roles.0.1',
        got: '"TEST"',
        expected: '"GUEST"'
      }
    ]
  }
}
```

### Reporters

You can create custom reporters by conforming to [io-ts](https://github.com/gcanti/io-ts#error-reporters) `Reporter` interface.

```typescript
interface Reporter<A> {
  report: (validation: Validation<any>) => A
}
```

In order to use custom reporter you have to pass it with `options` object as a second argument.

```typescript
requestValidator$(schema, { reporter: customReporter });
```


# middleware-jwt

HTTP requests authentication middleware for Marble.js based on JWT mechanism.

This module lets you authenticate HTTP requests using JWT tokens in your **Marble.js** applications. JWTs are typically used to protect API endpoints, and are often issued using OpenID Connect.

{% hint style="info" %}
You can find more details about JWT (RFC 7519) standard [here](http://jwt.io).
{% endhint %}

The middleware uses `jsonwebtoken` package under the hood. It wraps the package API into more\
RxJS-friendly abstractions that can be partially applied and composed inside Effect streams.

### Installation

{% code title="" %}

```bash
$ npm i @marblejs/middleware-jwt
```

{% endcode %}

Requires `@marblejs/core` to be installed.

### Importing

```typescript
import { authorize$ } from '@marblejs/middleware-jwt';
```

### Type declaration

```
authorize$ :: (VerifyOptions, object -> Observable<object>) -> HttpMiddlewareEffect
```

### **Parameters**

| *parameter*      | definition                                |
| ---------------- | ----------------------------------------- |
| *config*         | `VerifyOptions`                           |
| *verifyPayload$* | `(payload: object) => Observable<object>` |

{% tabs %}
{% tab title="verifyPayload$" %}
A function used for payload verification. With this handler we can check if the payload extracted from the JWT token fulfills our security criterias (eg. we can verify if the given user identifier exists in the database). Besides the general verification, the function can return the streamed object, that will be available inside *HttpRequest* `req.user` parameter. If the stream throws an error (eg. during the validation) the *authorize$* middleware responds with `401 / Unauthorized` error.

**Type declaration**

```
verifyPayload$ :: object -> Observable<object>
```

**Example**

The function checks the presence of the user id in the database and then returns an *Observable* of found user instance.&#x20;

{% code title="" %}

```typescript
const verifyPayload$ = (payload: Payload) => UserDao
  .findById(payload._id)
  .pipe(flatMap(neverNullable));
```

{% endcode %}
{% endtab %}

{% tab title="VerifyOptions" %}
Config object, passed as a first argument, defines a set of parameters that are used during token verification process.

| *parameter*      | definition                       |
| ---------------- | -------------------------------- |
| *secret*         | `string \| Buffer`               |
| algorithms       | \<optional>  `string[]`          |
| audience         | \<optional> `string \| string[]` |
| clockTimestamp   | \<optional> `number`             |
| clockTolerance   | \<optional> `number`             |
| issuer           | \<optional> `string \| string[]` |
| ignoreExpiration | \<optional> `boolean`            |
| ignoreNotBefore  | \<optional> `boolean`            |
| jwtid            | \<optional> `string`             |
| subject          | \<optional> `string`             |
| {% endtab %}     |                                  |
| {% endtabs %}    |                                  |

{% hint style="info" %}
For more infos about *jwt.VerifyOptions* please read [jsonwebtoken docs](https://github.com/auth0/node-jsonwebtoken#jwtverifytoken-secretorpublickey-options-callback).
{% endhint %}

{% hint style="info" %}
You can read more about token creation [here](/docs/v2/api-reference/middleware-jwt/token-creation).
{% endhint %}

### **Usage**

It is recommended to extract the middleware configuration into separate file. This way you can reuse it in many places.

{% code title="auth.middleware.ts" %}

```typescript
import { authorize$ as jwt$ } from '@marblejs/middleware-jwt';
import { SECRET_KEY } from './config';

const config = { secret: SECRET_KEY };

const verifyPayload$ = (payload: Payload) => UserDao
  .findById(payload._id)
  .pipe(flatMap(neverNullable));

export const authorize$ = jwt$(config, verifyPayload$);
```

{% endcode %}

The configured middleware can be simply composed in any route, that should be validated.

```typescript
import { r } from '@marblejs/core';
import { authorize$ } from './auth-middleware';

const getUsers$ = r.pipe(
  r.matchPath('/'),
  r.matchType('GET'),
  r.useEffect(getUsersEffect$)));

const user$ = combineRoutes('/user', {
  effects: [getUsers$],
  middlewares: [authorize$], 👈
});
```

If the incoming request doesn't pass the authentication process (eg. token is invalid, expired or the `verifyPayload$` throws an error, the middleware responds with `401 / Unauthorized` error.


# Token signing

Besides the common things like token authorization, the middleware comes with handy functions responsible for token signing.

## + **generateToken**

The middleware wraps auth0 [jsonwebtoken](https://github.com/auth0/node-jsonwebtoken) API into more RxJS friendly functions that can be partially applied and composed inside Observable streams.

**generateToken** signs new JWT token with provided payload and configuration object which defines the way how the token is signed.&#x20;

### Importing

```typescript
import { generateToken } from '@marblejs/middleware-jwt';
```

### Type declaration

```
generateToken :: GenerateOptions -> Payload -> string
```

### Parameters

| *parameter* | definition                             |
| ----------- | -------------------------------------- |
| *options*   | `GenerateOptions`                      |
| *payload*   | `Payload = string \| object \| Buffer` |

{% tabs %}
{% tab title="GenerateOptions" %}
Config object which defines a set of parameters that are used for token signing.

| *parameter*   | definition                       |
| ------------- | -------------------------------- |
| *secret*      | `string \| Buffer`               |
| algorithm     | \<optional> `string`             |
| keyid         | \<optional> `string`             |
| expiresIn     | \<optional> `string \| number`   |
| notBefore     | \<optional> `string \| number`   |
| audience      | \<optional> `string \| string[]` |
| subject       | \<optional> `string`             |
| issuer        | \<optional> `string`             |
| jwtid         | \<optional> `string`             |
| noTimestamp   | \<optional> `boolean`            |
| header        | \<optional> `object`             |
| encoding      | \<optional> `string`             |
| {% endtab %}  |                                  |
| {% endtabs %} |                                  |

{% hint style="info" %}
For more details about JWT token signing, please visit [jsonwebtoken package docs](https://github.com/auth0/node-jsonwebtoken).
{% endhint %}

## + **generateExpirationInHours**

The standard for JWT defines an `exp` claim for expiration. The expiration is represented as a **NumericDate.** This means that the expiration should contain the number of seconds since the epoch.

**generateExpiratinoInHours** is a small, but handy function that returns an numeric date for given hours as a parameter. If the function is called without any parameter then the date is generated with 1 hour expiration.

### Importing

```typescript
import { generateExpirationInHours } from '@marblejs/middleware-jwt';
```

### Type declaration

```
generateExpirationInHours :: number -> number
```

## **Example**

{% code title="token.helper.ts" %}

```typescript
export const generateTokenPayload = (user: User) => ({
  id: user.id,
  email: user.email,
  exp: generateExpirationInHours(4), 
  // 👆 token will expire within the next 4 hours
});
```

{% endcode %}

{% code title="login.effect.ts" %}

```typescript
import { generateTokenPayload } from './token.helper';

const login$ = r.pipe(
  r.matchPath('/login'),
  r.matchType('POST'),
  r.useEffect(req$ => req$.pipe(
    map(req => req.body),
    mergeMap(UserDao.findByCredentials),
    map(generateTokenPayload),
    // 👇
    map(generateToken({ secret: Config.jwt.secret })),
    map(token => ({ body: { token } })),
    catchError(() => throwError(
      new HttpError('Unauthorized', HttpStatus.UNAUTHORIZED)
    )),
  )));
```

{% endcode %}




---

[Next Page](/docs/llms-full.txt/1)

