# data-seep

> Reactive Data Seep

Latest version **0.3.4** (published 2023-06-25) · MIT license · 0 weekly downloads

## Install

```sh
npm install data-seep
pnpm add data-seep
yarn add data-seep
bun add data-seep
```

## Health

**Score 30/100 (F)** — status: abandoned.

Positive: has types; esm support; no vulnerabilities; high quality score.

Warnings: low downloads; pre 1.0.

Negative: abandoned; low maintenance score.

## Facts

| | |
|---|---|
| Version | 0.3.4 |
| Published | 2023-06-25 |
| First published | 2023-06-23 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | ESM |
| Dependencies | 2 |
| Unpacked size | 34.1 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 0 |
| Author | Ruslan Lopatin |
| Maintainers | lorus |
| Keywords | data-faucet, data-seep, data-sink |

## Links

- npm: https://www.npmjs.com/package/data-seep
- Repository: https://github.com/proc7ts/data-seep
- Issues: https://github.com/proc7ts/data-seep/issues
- npm.io page: https://npm.io/package/data-seep

## Dependencies (2)

- [@proc7ts/async](https://npm.io/package/@proc7ts/async.md) ^2.1.0
- [@proc7ts/primitives](https://npm.io/package/@proc7ts/primitives.md) ^4.0.1

## Recent versions

- 0.3.4 (latest) — 2023-06-25
- 0.3.3 — 2023-06-25
- 0.3.2 — 2023-06-25
- 0.3.1 — 2023-06-25
- 0.3.0 — 2023-06-25
- 0.2.0 — 2023-06-23

## README

# Reactive Data Seep

[![NPM][npm-image]][npm-url]
[![Build Status][build-status-img]][build-status-link]
[![Code Quality][quality-img]][quality-link]
[![Coverage][coverage-img]][coverage-link]
[![GitHub Project][github-image]][github-url]
[![API Documentation][api-docs-image]][api documentation]

Code utilizing Reactive Data Seep pattern looks like this:

```typescript
await withLogger({ level: LogLevel.DEBUG }, async logger => {
  logger.info('Connecting to database');

  await withDatabase(
    {
      uri: 'postgresql://dbuser:secretpassword@database.server.com:3211/mydb',
    },
    async db => {
      logger.info('Starting HTTP server');

      await withHttpServer(async server => {
        server.dispatch(
          {
            path: '/api/user',
            method: 'GET',
          },
          async ({ request, response }) => {
            const id = parseInt(request.url.searchParams.get('id'));
            const user = await db.query('SELECT name, email FROM user WHERE id = :id', { id });

            response.setHeader('Content-Type', 'application/json');

            await response.send(JSON.stringify(user));
          },
        );
        server.dispatch(
          {
            path: '/api/user',
            method: 'PUT',
          },
          async ({ request, response }) => {
            const user = JSON.parse(await request.read());
            const { id } = await db.query('INSERT INTO user (name, email) VALUES (:name, :email) RETURNING id', user);

            response.setHeader('Content-Type', 'application/json');

            await response.send(JSON.stringify({ id }));
          },
        );
        server.dispatchError(
          {
            type: NotFoundError,
          },
          async ({ response, error }) => {
            response.setHeader('Content-Type', 'application/json');
            response.setStatus(404);

            await response.send(JSON.stringify({ error: String(error.message) }));
          },
        );
        server.dispatchError(async ({ response, error }) => {
          response.setHeader('Content-Type', 'application/json');
          response.setStatus(500);

          await response.send(JSON.stringify({ error: String(error) }));
        });

        await Promise.any([
          withSignal(
            {
              signal: 'SIGINT',
            },
            signal => {
              logger.info('SIGINT received');

              return Promise.reject(signal);
            },
          ),
          server.listen({ post: 8080 }),
        ]);
      });

      logger.info('HTTP server stopped');
    },
  );

  logger.info('Disconnected from database');
});
```

The pattern relies on variable scoping rules. In particular, the data _inflow_ into outer scope _seeps through_ other
data _faucets_ to inner scopes.

A data _faucet_ function implementing this pattern accepts an asynchronous _sink_ function as its last argument.
A _sink_ function accepts an _inflow_ value as its only argument. The _inflow_ value exists while the _sink_ processing
it. After that, the value is no longer valid.

**Implementing this pattern does not require the knowledge or use of any third-party libraries or APIs**. However,
in more complicated scenarios the tools provided by this package may be of help.

[npm-image]: https://img.shields.io/npm/v/data-seep.svg?logo=npm
[npm-url]: https://www.npmjs.com/package/data-seep
[build-status-img]: https://github.com/proc7ts/data-seep/workflows/Build/badge.svg
[build-status-link]: https://github.com/proc7ts/data-seep/actions?query=workflow:Build
[quality-img]: https://app.codacy.com/project/badge/Grade/7b713de99b284eb1960b7b3ad9abf730
[quality-link]: https://app.codacy.com/gh/proc7ts/data-seep/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade
[coverage-img]: https://app.codacy.com/project/badge/Coverage/7b713de99b284eb1960b7b3ad9abf730
[coverage-link]: https://app.codacy.com/gh/proc7ts/data-seep/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_coverage
[github-image]: https://img.shields.io/static/v1?logo=github&label=GitHub&message=project&color=informational
[github-url]: https://github.com/proc7ts/data-seep
[api-docs-image]: https://img.shields.io/static/v1?logo=typescript&label=API&message=docs&color=informational
[api documentation]: https://proc7ts.github.io/data-seep/

---
_Source: https://npm.io/package/data-seep · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
