# node-provide

> Async context based Dependency Injection for Node.JS

Latest version **2.0.1** (published 2020-04-16) · MIT license · 0 weekly downloads

> **Deprecated.** This package is deprecated.

## Install

```sh
npm install node-provide
pnpm add node-provide
yarn add node-provide
bun add node-provide
```

## Health

**Score 10/100 (F)** — status: deprecated.

Negative: deprecated.

## Facts

| | |
|---|---|
| Version | 2.0.1 |
| Published | 2020-04-16 |
| First published | 2019-06-07 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | CommonJS |
| Node | >=8.0.0 |
| Dependencies | 0 |
| Unpacked size | 26.9 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 16 |
| Author | Viacheslav Bereza |
| Maintainers | betula |
| Keywords | di, dependency injection, dependency provider, provide, injection, inject, zone, node |

## Links

- npm: https://www.npmjs.com/package/node-provide
- Repository: https://github.com/betula/node-provide
- Homepage: https://github.com/betula/node-provide#readme
- Issues: https://github.com/betula/node-provide/issues
- npm.io page: https://npm.io/package/node-provide

## Alternatives

- [memory-cache](https://npm.io/package/memory-cache.md) — 795.0K weekly downloads
- [@httptoolkit/proxy-agent](https://npm.io/package/@httptoolkit/proxy-agent.md) — 11.2K weekly downloads
- [express-cache-controller](https://npm.io/package/express-cache-controller.md) — 5.3K weekly downloads
- [http-cache-middleware](https://npm.io/package/http-cache-middleware.md) — 4.5K weekly downloads
- [cache2](https://npm.io/package/cache2.md) — 1.5K weekly downloads

## Recent versions

- 2.0.1 (latest) — 2020-04-16
- 2.0.0 — 2020-04-16
- 1.0.1 — 2020-02-18
- 1.0.0 — 2020-02-15
- 0.4.4 — 2020-01-20
- 0.4.3 — 2020-01-20
- 0.4.2 — 2020-01-13
- 0.4.1 — 2019-12-25
- 0.4.0 — 2019-12-25
- 0.3.0 — 2019-12-15
- 0.2.8 — 2019-07-09
- 0.2.7 — 2019-07-09
- 0.2.6 — 2019-06-28
- 0.2.5 — 2019-06-28
- 0.2.4 — 2019-06-27
- … 12 more at https://npm.io/package/node-provide/versions

## README

![node-provide](https://betula.github.io/node-provide/img/readme-logo.svg)

[![npm version](https://badge.fury.io/js/node-provide.svg)](https://badge.fury.io/js/node-provide)
[![Build Status](https://travis-ci.org/betula/node-provide.svg?branch=master)](https://travis-ci.org/betula/node-provide)
[![Coverage Status](https://coveralls.io/repos/github/betula/node-provide/badge.svg?branch=master)](https://coveralls.io/github/betula/node-provide?branch=master)

Async context based Dependency Injection for Node.JS without pain with Dependency Injection Container, dependency registration, and configuration.

- You can use it at any place of your application without rewrite your applications architecture or other preparations or initializations.
- Each dependency can be class, function, or any another value, and plain JavaScript object too.
- You can override your dependencies for organizing modules architecture, or unit testing without hack standard Node.JS require mechanism.
- You can use TypeScript or JavaScript.
- You can create isolate context for multiple instances of your application (Dependency Injection scopes) with a different set of dependencies, overrides, and instances.

## Install

```
npm i node-provide
```

## Example

```javascript
import { provide } from "node-provide";
// ...

class Db { /* ... */ }
class Server { /* ... */ }
// ...

// Inject dependencies using a provide function and class properties
export default class App {
  db = provide(Db);
  server = provide(Server);
  // ...
  start() {
    this.db.init();
    // ...
  }
}

// index.ts
new App().start(); // You can create an instance directly as usually class
```

## Override dependencies

If you use modules architecture of your application you can override your dependencies.

```javascript
import { override, provide } from "node-provide";

class BaseA {
  log() {
    throw new Error("log is not implemented");
  }
}

class A {
  log() {
    console.log("Log A!");
  }
}

class B {
  a = provide(BaseA);
  log() {
    this.a.log(); // Log A!
  }
}

override(BaseA, A); // After that BaseA and A dependencies will use only one instance of A
new B().log(); // "Log A!"
```

## Unit testing

You can use `assign` to provide mocks into your dependencies.

```javascript
// world.ts
export class World {
  hello() {
    // ...
  }
}

// hello.ts
import { provide } from "node-provide";
import { World } from "./world";

export class Hello {
  world = provide(World);

  world() {
    this.world.hello();
  }
}

// hello.test.ts
import { assign, cleanup } from "node-provide";
import { World } from "./world";
import { Hello } from "./hello";
// ...

afterEach(cleanup);

test("It works!", () => {
  const worldMock = {
    hello: jest.fn(),
  }
  assign(World, worldMock);
  new Hello().world();
  expect(worldMock.hello).toBeCalled();
})
```

If you use `Jest` for unit testing you need to add some code to your `jest.config.js` file.

```javascript
// jest.config.js
{
  // ...
  setupFilesAfterEnv: [ "node-provide/jest-cleanup-after-each" ],
  // ...
}
```

This code means that after each test cached dependency instances will be clear. For another testing frameworks, you need call `cleanup` after each test case manually for cleanup cached instances of dependencies.

```javascript
const { cleanup } = require("node-provide");
// ...
afterEach(cleanup);
// ...
```

## Isolate Dependency Injection context

If you want more then one instance of your application with different configuration or with a different overrides of dependencies, you can use `zone`. It works using async context for separate Dependency Injection scopes. Node.JS async hook will be created only once after the first call of `zone`. In each of `zone` section, you can define any overrides, scopes can be nested with inherit overrides.

```javascript
import { zone, provide } from "node-provide";

class A {
  private counter: number = 0;
  inc() {
    this.counter += 1;
  }
  print() {
    console.log(`Counter ${this.counter}`);
  }
}

class B {
  a = provide(A);
  incAndPrint() {
    a.inc();
    a.print();
  }
}

// Each section of `zone` use different dependency injection scopes and different instances of your dependencies
await zone(() => {
  const b = new B;
  b.incAndPrint(); // Counter 1
  b.incAndPrint(); // Counter 2
});
await zone(() => {
  const b = new B;
  b.incAndPrint(); // Counter 1
});
```

## API Reference

**resolve**

Returns instance of your dependency. Each dependency can be class, function or any value.
- For class. The class will be instantiated once and cached
- For function. The function will be called and result cached
- For any value. Return it value without any changes

```javascript
const depInstance = resolve(Dep);
```

**provide**

The function for providing an instance of dependency on the class property.

```javascript
class {
  dep1 = provide(Dep1);
  dep2 = provide(Dep2);
}
```

**override**

Override dependency.

```javascript
override(FromDep, ToDep);
// ...
console.log(resolve(FromDep) === resolve(ToDep)); // true
```

**assign**

Define any value as resolved value for any dependency.

```javascript
assign(Dep, value);
// ...
class A {}
assign(A, 10);
console.log(resolve(A)); // 10
```

**zone**

Run your app in isolated Dependency Injection scope. All instances cached for this instance application will be isolated from all cached instances in other scopes. All overrides defined here will be inherited for nested isolated scopes but not available for others. No return value.

```javascript
await zone(async () => {
  const app = new App(); // Run you app here
  await app.run();
  // ...
});
```

```javascript
await zone(async () => {
  override(Dep1, Dep2);

  await zone(async () => {
    override(Dep2, Dep3);
    // ...
    console.log(resolve(Dep1) instanceof Dep3); // true
  });
  // ...
  console.log(resolve(Dep1) instanceof Dep2); // true
})
```

**cleanup**

Clean all cached dependency instances. It's needed for testing. Has no parameters.

```javascript
// ...
afterEach(cleanup);
// ...
```

**reset**

Clean all cached dependency instances and overrides. Has no parameters.

```javascript
reset()
```

**factory**

Make new DI.

```javascript
const { provide, assign, override, cleanup, reset } = factory();
```
---

If you have questions or something else for me or this project, maybe architectures questions, improvement ideas or anything else, please make the issue.

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