# @yadah/data-manager

> Yadah data manager to co-ordinate backend subsystems and domains

Latest version **0.2.0** (published 2023-04-08) · ISC license · 0 weekly downloads

## Install

```sh
npm install @yadah/data-manager
pnpm add @yadah/data-manager
yarn add @yadah/data-manager
bun add @yadah/data-manager
```

## Health

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

Positive: esm support; no vulnerabilities.

Warnings: low downloads; no types; pre 1.0.

Negative: abandoned; low maintenance score.

## Facts

| | |
|---|---|
| Version | 0.2.0 |
| Published | 2023-04-08 |
| First published | 2022-07-12 |
| Weekly downloads | 0 |
| License | ISC |
| TypeScript types | none |
| Module format | ESM |
| Node | >=18.3.0 |
| Dependencies | 0 |
| Unpacked size | 7.6 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 1 |
| Author | ttoohey |
| Maintainers | ttoohey |
| Keywords | yadah |

## Links

- npm: https://www.npmjs.com/package/@yadah/data-manager
- Repository: https://github.com/ttoohey/yadah
- Homepage: https://github.com/ttoohey/yadah/tree/master/packages/data-manager#readme
- Issues: https://github.com/ttoohey/yadah/issues
- npm.io page: https://npm.io/package/@yadah/data-manager

## Recent versions

- 0.2.0 (latest) — 2023-04-08
- 0.1.1 — 2022-07-12
- 0.1.0 — 2022-07-12

## README

# yadah/data-manager

Provides logic for configuring an services's data layer, and creating
"domain classes" to provide a standard way for front-ends to interact with
subsystems.

## Usage

Create domain classes

```js
// my-package/domains.js
import { Domain } from "@yadah/data-manager";

export class DomainA extends Domain {
  doATask() {
    this.logger.info("in doATask");
  }
}

export class DomainB extends Domain {
  async doBTask() {
    await this.knex("tableB").insert({ text: "in doBTask" });
  }
}
```

Create a data manager

```js
// my-package/index.js
import DataManager from "@yadah/data-manager";
import createLogger from "@yadah/subsystem-logger";
import createKnex from "@yadah/subsystem-knex";
import * as modules from "./domains.js";

// setup subsystems
export const logger = createLogger(); // example
export const knex = createKnex(); // example
const subsystems = { logger, knex };

// initialise and boot the data manager
const dataManager = new DataManager(subsystems);
export const domains = dataManager.boot(modules);

// life-cycle functions to start and stop subsystems and domains
export async function startup() {
  await dataManager.startup();
}

export async function shutdown() {
  await dataManager.shutdown();
  await knex.destroy();
}
```

Access data package exports

```js
// other-package/example.js
import { domains, startup, shutdown } from "my-package";

await startup();
domains.DomainA.doATask();
await domains.DomainB.doBTask();
await shutdown();
```

## Mixins

Mixins are used to create common logic for domains.

Example: the `ListenerMixin` will call `registerListeners()` during the `boot`
lifecycle, and will automatically remove listeners during `shutdown`.

```js
// my-package/SomeDomain.js
import { Domain } from "@yadah/data-manager";
import ListenerMixin from "@yadah/domain-listener";
import { pipe } from "@yadah/mixin";

const mixins = pipe(Domain, ListenerMixin);
export class SomeDomain extends mixins {
  registerListeners() {
    this.on("someEvent", () => this.handleSomeEvent());
  }
  handleSomeEvent() {
    // code to handle 'someEvent' events
  }
}
```

### Creating a mixin

A mixin is a function that returns a class that extends a supplied class.

The `dedupe()` function is a wrapper for mixin functions that ensures they will
wrap a class only once. This allows mixin depdendencies to be well defined.

```js
// my-package/SomeMixin.js
import { dedupe } from "@yadah/mixin";

function SomeMixin(superclass) {
  return class Some extends superclass {
    someMixinFn() {
      // mixin logic
    }
  };
}
export default dedupe(SomeMixin);
```

A mixin can depend on another mixin by extending the `superclass`:

```js
// my-package/SomeMixin.js
import { dedupe, pipe } from "@yadah/mixin";
import OtherMixin from "other-package";

function SomeMixin(superclass) {
  const mixins = pipe(superclass, OtherMixin);
  return class Some extends mixins {
    someMixinFn() {
      const result = this.otherMixinFn();
      //
    }
  };
}

export default dedupe(SomeMixin);
```

## Domain class life-cycle functions

The `Domain` class provides three life-cycle functions:

1. `boot()`
2. `startup()`
3. `shutdown()`

The `boot()` function is executed synchronously. All subsystems and other
domain classes are visible via `this`. This function is typically used to allow
registering behaviours defined by mixins. `boot()` is called when the
`DataManager.boot()` function is called - typically during the services's
data-layer setup. `boot()` should be passed an object containing "domain
classes" which will be created as singletons and stored on the `this.domains`
object. `boot()` returns an object containing the domain class singletons.

The `startup()` function may be asynchronous. The `boot()` function should be
called prior to `startup()`. This function is called on each domain class
singleton when the `DataManager.startup()` function is called.

The `shutdown()` function may be asynchronous. This function is called on each
domain class singleton when the `DataManager.shutdown()` function is called.

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