0.0.132 • Published 1 month ago

@rhtml/di v0.0.132

Weekly downloads
60
License
MIT
Repository
github
Last release
1 month ago

@rhtml/di

Smallest Dependency Injection for Typescript and Javascript!

  • Only 1.42kb bundled size without Reflection, 2.49kb with @abraham/reflection;
  • Decorators available inside @rhtml/di/module Module, Component
  • Hooks available OnInit, OnDestroy class { OnDestroy() {} OnInit() {} }
  • 100% Code coverage and branches
  • No dependencies
  • Works with deno

Installation

npm i @rhtml/di

Usage

import { Inject, Injectable } from '@rhtml/di';

class Test {
  test = 42;
}
@Injectable()
class Test2 {
  constructor(@Inject(Test) public test: Test) {}
}
const test2 = set(Test2);
console.log(test2.test.test); // 42

With Deno using esm.sh as a cdn

Example can be found here Deno land https://deno.land/x/rdi

import 'https://deno.land/x/reflect_metadata@v0.1.12/mod.ts';

import {
  Bootstrap,
  Injectable,
  Module
} from 'https://cdn.esm.sh/v53/@rhtml/di@0.0.81';

@Injectable()
class MyService {
  OnInit() {
    console.log('[MyService]: initialized');
  }

  helloWorld() {
    return 'Hello World from @rhtml/di';
  }
}

@Injectable()
class MyService2 {
  constructor(private myService: MyService) {}
  OnInit() {
    console.log(this.myService.helloWorld());
  }
}

@Module({
  providers: [MyService, MyService2]
})
export class AppModule {}

await Bootstrap(AppModule);

With Reflection

npm i @abraham/reflection
import '@abraham/reflection';

import { Inject, Injectable } from '@rhtml/di';

class Test {
  test = 42;
}
@Injectable()
class Test2 {
  constructor(public test: Test) {}
}
const test2 = set(Test2);
console.log(test2.test.test); // 42

Token Injection

import { InjectionToken, Injectable, Inject } from '@rhtml/di';

const Token = new InjectionToken<Test>();

@Injectable()
class Test {
  myMethod() {}
}

set(Test, Token);

@Injectable()
class App {
  constructor(@Inject(Token) private test: Test) {}
}

console.log(get(App).test.myMethod());

Monadic approach

import { Inject, PrivateReader, Reader } from '@rhtml/di';

export class UserCache {
  name = '[UserCache]: My name is ';
}

export class UserService {
  @Inject(UserCache)
  public cache: UserCache;
}

const AppModule = [UserService, UserCache];

class App {
  @Reader(...AppModule)
  getPesho(name: string): Reader<[UserService], string> {
    return ([userService]) => userService.cache.name + name;
  }

  getPeshoAsync(
    name: string
  ): PrivateReader<[UserService, UserCache], Promise<string>> {
    return async ([userService, userCache]) =>
      userService.cache.name + name + userCache.name;
  }

  @Reader(...AppModule)
  test2(name: string): Reader<[UserService, UserCache], Promise<string>> {
    return async ([userService, userCache]) => {
      return (
        userService.cache.name +
        name +
        (await this.getPeshoAsync('omg')([userService, userCache]))
      );
    };
  }
}
const app = new App();
const action = app.getPesho('Kristiyan Tachev');
const asyncAction = app.test2('Kristiyan Tachev');
console.log(action());
asyncAction().then(console.log);
import { Inject, Reader, set } from '@rhtml/di';

export class UserCache {
  name = '[UserCache]: My name is ';
}

export class UserService {
  @Inject(UserCache)
  public cache: UserCache;
}

class App {
  @Reader(UserService)
  getPesho(name: string): Reader<[UserService], string> {
    return ([userService]) => userService.cache.name + name;
  }

  @Reader(UserService)
  getPeshoAsync(name: string): Reader<[UserService], Promise<string>> {
    return async ([userService]) => userService.cache.name + name;
  }
}
const app = set(App);
const action = app.getPesho('Kristiyan Tachev');
const asyncAction = app.getPeshoAsync('Kristiyan Tachev');
console.log(action());
asyncAction().then(console.log);
Using Static methods
import { Inject, Reader, set } from '@rhtml/di';

export class UserCache {
  name = '[UserCache]: My name is ';
}

export class UserService {
  @Inject(UserCache)
  public cache: UserCache;
}

const AppModule = [UserService, UserCache];

class App {
  @Reader(...AppModule)
  public static getPesho(name: string): Reader<[UserService], string> {
    return ([userService]) => userService.cache.name + name;
  }

  public static getPeshoAsync(
    name: string
  ): PrivateReader<NonNullable<[UserService, UserCache]>, Promise<string>> {
    return async ([userService, userCache]) =>
      userService.cache.name + name + userCache.name;
  }

  @Reader(...AppModule)
  public static test2(
    name: string
  ): Reader<[UserService, UserCache], Promise<string>> {
    return async ([userService, userCache]) => {
      return (
        userService.cache.name +
        name +
        (await this.getPeshoAsync('omg')([userService, userCache]))
      );
    };
  }
}
const asyncAction = App.test2('Kristiyan Tachev');
asyncAction().then(console.log);
Module decorator
import { Injectable, Inject, set, get } from '@rhtml/di';
import { Module } from '@rhtml/di/module';

class User {
  id = 1;
}
class UserService {
  @Inject(User)
  user: User;
}

@Injectable()
class InjectableService {
  constructor(@Inject(User) private user: User) {}
}

@Module({
  providers: [UserService, InjectableService]
})
class UserModule {}

@Module({
  imports: [UserModule]
})
class AppModule {}
console.log(has(AppModule)); // False
set(AppModule);
const userService = get(UserService);
expect(userService.user.id).toBe(1);
Advanced example using Lazy providers
import '@abraham/reflection';

import { Inject, Injectable, InjectionToken, remove, set } from '@rhtml/di';
import {
  Bootstrap,
  Component,
  Module,
  ModuleWithProviders
} from '@rhtml/di/module';

type Token1 = number;
type Token2 = string;

const Token1 = new InjectionToken<Token1>();
const Token2 = new InjectionToken<Token2>();

const now = Date.now();

@Injectable()
export class UserService66 {
  constructor() {
    console.log('[UserService66]');
  }

  getOmg() {
    return 'ARE BE OMG';
  }
}

@Injectable()
export class UserService {
  // @Inject(Token1) public token: number;
  constructor(@Inject(Token1) public token: number) {
    console.log('[UserService]', token);
  }
}

@Injectable()
export class UserService2 {
  constructor(public userService: UserService) {
    console.log('[UserService2]');
  }
}

@Injectable()
export class UserService3 {
  // @Inject(Token1) public token: number;
  constructor(@Inject(Token1) public token: Token1) {
    console.log('[UserService3]', token);
  }
}

@Injectable({ providers: [set(UserService66)] })
export class UserService4 {
  constructor(data: UserService66) {
    console.log('[UserService4]', data.getOmg());
  }

  getPesh() {
    return 6000;
  }
}

@Component()
class AppComponent {
  constructor(
    public userService2: UserService2,
    @Inject(Token2) public token: Token2
  ) {
    console.log('[AppComponent]', userService2.userService.token, token);
  }

  OnInit() {
    console.log('INITIALIZEEEDDDDD ');
  }

  OnDestroy() {
    console.log('ON DESTROY ');
  }
}

set(UserService4);

@Module({
  providers: [
    UserService2,
    {
      provide: Token1,
      deps: [UserService4],
      useFactory: (data: UserService4) =>
        new Promise<number>(resolve =>
          setTimeout(() => resolve(data.getPesh()), 1000)
        )
    }
  ],
  bootstrap: [AppComponent]
})
export class MainModule {
  static forRoot(): ModuleWithProviders {
    return {
      module: MainModule,
      providers: [
        {
          provide: Token2,
          useFactory: async () => {
            console.log('aa');
            return '1234';
          }
        }
      ]
    };
  }
}

Bootstrap(MainModule).then(() => {
  console.log('Started', `after ${Date.now() - now}`);
  remove(AppComponent);
});
0.0.131

1 month ago

0.0.132

1 month ago

0.0.129

2 months ago

0.0.130

2 months ago

0.0.128

2 months ago

0.0.127

2 months ago

0.0.126

3 months ago

0.0.125

5 months ago

0.0.120

1 year ago

0.0.124

1 year ago

0.0.123

1 year ago

0.0.122

1 year ago

0.0.121

1 year ago

0.0.119

1 year ago

0.0.118

1 year ago

0.0.117

2 years ago

0.0.116

2 years ago

0.0.115

2 years ago

0.0.114

2 years ago

0.0.113

2 years ago

0.0.112

2 years ago

0.0.111

2 years ago

0.0.87

2 years ago

0.0.88

2 years ago

0.0.89

2 years ago

0.0.110

2 years ago

0.0.106

2 years ago

0.0.95

2 years ago

0.0.105

2 years ago

0.0.96

2 years ago

0.0.104

2 years ago

0.0.97

2 years ago

0.0.103

2 years ago

0.0.98

2 years ago

0.0.99

2 years ago

0.0.109

2 years ago

0.0.108

2 years ago

0.0.107

2 years ago

0.0.90

2 years ago

0.0.102

2 years ago

0.0.91

2 years ago

0.0.101

2 years ago

0.0.92

2 years ago

0.0.100

2 years ago

0.0.93

2 years ago

0.0.94

2 years ago

0.0.85

3 years ago

0.0.86

3 years ago

0.0.84

3 years ago

0.0.83

3 years ago

0.0.81

3 years ago

0.0.82

3 years ago

0.0.80

3 years ago

0.0.76

3 years ago

0.0.77

3 years ago

0.0.78

3 years ago

0.0.79

3 years ago

0.0.75

3 years ago

0.0.73

3 years ago

0.0.74

3 years ago

0.0.72

3 years ago

0.0.70

3 years ago

0.0.71

3 years ago

0.0.69

3 years ago

0.0.63

3 years ago

0.0.64

3 years ago

0.0.65

3 years ago

0.0.66

3 years ago

0.0.67

3 years ago

0.0.68

3 years ago

0.0.62

4 years ago

0.0.60

4 years ago

0.0.61

4 years ago

0.0.59

4 years ago

0.0.58

4 years ago

0.0.56

4 years ago

0.0.57

4 years ago

0.0.48

4 years ago

0.0.49

4 years ago

0.0.47

4 years ago

0.0.46

4 years ago

0.0.45

4 years ago

0.0.40

4 years ago

0.0.41

4 years ago

0.0.42

4 years ago

0.0.43

4 years ago

0.0.44

4 years ago

0.0.37

4 years ago

0.0.38

4 years ago

0.0.39

4 years ago

0.0.34

4 years ago

0.0.35

4 years ago

0.0.36

4 years ago

0.0.30

4 years ago

0.0.31

4 years ago

0.0.32

4 years ago

0.0.33

4 years ago

0.0.27

4 years ago

0.0.28

4 years ago

0.0.29

4 years ago

0.0.25

4 years ago