Simple dependency injection for Deno TypeScript projects

Simple dependency injection for Deno TypeScript projects

Simple dependency injection for Deno TypeScript projects.This module's aims to provide you with an extremely simple API, without any bells and whistles and the 100% test coverage that comes with such a minimal feature set.

Deno Dependency Injector

Simple dependency injection for Deno TypeScript projects.

This module's aims to provide you with an extremely simple API, without any bells and whistles and the 100% test coverage that comes with such a minimal feature set.

As such, this module allows you to

  • inject classes into other classes through their constructor
  • inject classes as singletons or inject a new instance of the class every time it is used
  • override/replace certain injected classes (e.g. for replacing them with a mock for testing purposes)

That's it.

Need to inject a plain string? Wrap it in a class! Need to inject a function? Wrap it in a class!

There's no need to make things more complicated than necessary.

Usage

1. Create @Injectable() classes

// class_a.ts
import { Injectable } from "https://deno.land/x/inject/mod.ts";

@Injectable()
export class ClassA {
  hello() {
    return "Hello from ClassA!";
  }
}

2. Inject Injectable classes through constructors

// class_b.ts
import { Injectable } from "https://deno.land/x/inject/mod.ts";
import { ClassA } from "./class_a.ts";

@Injectable()
export class ClassB {
  constructor(
    private readonly classA: ClassA,
  ) {}

  hello() {
    return `Hello from ClassB and ${this.classA.hello()}!`;
  }
}

3. Create a Bootstrapped class and let the injector take care of creation

// main.ts
import { Bootstrapped, bootstrap } from "https://deno.land/x/inject/mod.ts";
import { ClassB } from "./class_b.ts";

@Bootstrapped()
export class Main {
  constructor(
    private readonly classB: ClassB,
  ) {}

  hello() {
    return this.classB.hello();
  }
}

const main = bootstrap(Main);

console.log(main.hello());

4. Run your App!

deno run -c tsconfig.json main.ts
# Hello from ClassB and Hello from ClassA!!

Remember to have a tsconfig.json with the following content in your project's root directory and always call deno run with the additional -c tsconfig.json parameter or Deno will complain about missing experimental support for decorators.

{
  "compilerOptions": {
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true
  }
}

Overriding dependencies

During testing, it may be useful to override certain dependencies of the class under test with mocks. This module allows you to do just that:

import { Injectable, Bootstrappable, bootstrap } from "https://deno.land/x/inject/mod.ts";
import { assertEquals } from "https://deno.land/std/test/mod.ts";

@Injectable()
class Dependency {
  value = "Original dependency";
}

@Injectable()
class ClassUnderTest {
  constructor(public dependency: Dependency) {}

  getValue() {
    return this.dependency.value;
  }
}

@Injectable()
class OverrideDependency {
  constructor(public original: Dependency) {}

  value = "Override dependency";
}

Deno.test("ClassUnderTest dependency is overridden", () => {
  const instance = bootstrap(ClassUnderTest, new Map([[Dependency, OverrideDependency]]));

  assertEquals(instance.getValue(), "Override dependency");
  assertEquals((instance.dependency as unknown as OverrideDependency).original.value, "Original dependency");
});

Note that when overriding class A with class B, an instance of A can still be injected into B, but all other classes depending on A will get an instance of B instead.

API

@Injectable(options?: { isSingleton: boolean })

Decorator used to mark a class as injectable. You can only inject classes that are declared with the @Injectable() decorator.

You can pass an optional options parameter to the @Injectable() decorator:

  • isSingleton (default: true): wether the class should be injected as a singleton or if a new instance should be created for every class that injects this type.

    Checkout examples/instanced_counter.ts and examples/singleton_counter.ts for example usages of the isSingleton property.

@Bootstrapped()

Decorator used to make a class bootstrappable.

Doesn't do anything else but making the class known to the TypeScript's reflection system, which is required for the dependency injector to know the types you want to inject.

You can also bootstrap classes that are otherwise known to the reflection system, e.g. because they are @Injectable or bear any other decorator, but it is recommended to stick to using the @Bootstrapped decorator for consistency and making it easier to find your application's main entry point(s).

During testing, it is perfectly fine to bootstrap @Injectable classes, of course.

bootstrap<T>(Type: Constructor<T>, overrides?: Map<Constructor, Constructor>): T

The one function call to rule them all.

Automatically creates an instance of the class you pass it, as long as all dependencies in the constructor (and their dependency's constructors) are @Injectable.

Optionally takes a Map that you can use to override certain injected classes with some other @Injectable class, for example to mock dependencies during testing.

This function is shorthand for new Injector(overrides).bootstrap(Type).

Use the Injector class if you want to bootstrap more than one class using the same resolved dependencies and overrides.

Injector

The actual class responsible for discovering and creating all @Injectable classes required by your @Bootstrapped class.

new Injector(overrides?: Map<Constructor, Constructor>)

Creates a new Injector class with the optionally specified overrides for dependency resolution (see bootstrap(Type, overrides?) for more information).

bootstrap<T>(Type: Constructor<T>): T

Resolves the dependency tree of the given class and creates instances of all required dependencies, taking into account the overrides passed during creation of the Injector.

Download Details:

Author: cmd-johnson

Source Code: https://github.com/cmd-johnson/deno-dependency-injector

deno node nodejs javascript

Bootstrap 5 Complete Course with Examples

Bootstrap 5 Tutorial - Bootstrap 5 Crash Course for Beginners

Nest.JS Tutorial for Beginners

Hello Vue 3: A First Look at Vue 3 and the Composition API

Building a simple Applications with Vue 3

Deno Crash Course: Explore Deno and Create a full REST API with Deno

How to Build a Real-time Chat App with Deno and WebSockets

Convert HTML to Markdown Online

HTML entity encoder decoder Online

AEM Querybuilder for JavaScript (Browser, Node, Deno)

Helix Querybuilder .AEM Querybuilder for JavaScript (Browser, Node, Deno)

NKeys for JavaScript - Node.js, Browsers, and Deno

A public-key signature system based on Ed25519 for the NATS ecosystem system for JavaScript. The nkeys.js library works in Deno, Node.js, and the browser!

Javascript module for easily generating mazes,compatible with both Deno and Node

A work-in-progress Javascript maze generator module, compatible with both Deno and Node.

What is Deno? The Node.JS Killer? The Deno-minator to Node?

What is Deno? The Node.JS Killer? The Deno-minator to Node? Deno is the new hype and will it be better than node.js? Deno is a secure runtime for JavaScript and TypeScript that is based on the V8 JavaScript engine and the Rust programming language that addresses Node’s shortcomings

What is Deno and is Node.js Dying? | Deno vs Node

What is Deno? Deno vs Node. Is Node.js going to die? Deno is a runtime for JavaScript and TypeScript that is based on the V8 JavaScript engine and the Rust programming language. It was created by Ryan Dahl, original creator of Node.js, and is focused on productivity. It was announced by Dahl in 2018 during his talk "10 Things I Regret About Node.js"