npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

doguinho

v0.0.12

Published

IoC and DI for Vue.js 2 with InversifyJS inspired by NestJS

Downloads

23

Readme

doguinho

IoC and DI for Vue with InversifyJS inspired by NestJS

Node.js Package

Requirements

Features

  • vuex-module-decorators support using lazy injection via @LazyInject.
  • Services are accessible through Vue components.
  • Can inject a VuexStore if you want type-safety.

Installation

$ npm install doguinho reflect-metadata inversify --save

TypeScript Configuration

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

Getting started

Creating application

First, create an Doguinho instance.

import { createDoguinho } from "doguinho";

const doguinho = createDoguinho(options);

You can pass several options during creation such as router and store if you want to define them in advance, and Doguinho will use them as the basis for defining things, if you do not provide, Doguinho will create its own.

Add it to your Vue application

import Vue from "vue";
const vm = new Vue({ doguinho });

Note: you must create Doguinho before building your application.

Modules

Modules are closed injection environments and should be used to better organize your application.

To define a new module simply add the decorator @Module on it.

import { Module } from "doguinho";

@Module()
export default class MyModule {}

Initialization handler

In case you need to do something when the module starts, there are initialization handlers beforeInit and init for you to work on.

import { Module, ModuleContext } from "doguinho";

@Module({
    onInit(context: ModuleContext): void { /* ... */ }
})
export default class MyModule {}

You can use the current context to perform manual injection, or anything else.

import { Module, ModuleContext } from "doguinho";

@Module({
    beforeInit(context: ModuleContext): void {
        context.inject(Anything);
    }
})
export default class MyModule {}

Use keys to inject constant, dynamic, or function values.

const HelloWorldKey = "hero";

@Module({
    beforeInit(context: ModuleContext): void {
        context.injectConst("Hello world", HelloWorldKey);
    }
})
export default class MyModule {}

Get values injected into the post-init handler.

const InitKey = "hero";

@Module({
    beforeInit(context: ModuleContext): void {
        context.injectConstant(`Module "${context.module.name}" initialized!`, InitKey);
    }, 
    init(context: ModuleContext): void {
        console.log(context.get(InitKey));
        // prints: Module "auth" initialized
    }
})
export default class AuthModule {}

Providers

Providers passed through modules are automatically injected in the context of that module.

Only classes annotated with @Injectable can be providers.

import { Module, Injectable } from "doguinho";

@Injectable()
export class SomeRandomService {}

@Module({
    providers: [SomeRandomService]
})
export default class MyModule {}

Recommended project directory structure

A recommended project structure using modules is the feature module which consists of a directory (with its own module) for each feature. Something like this:

Source directory (/src)

├─ app/
│  │  ├─ module-A/
│  │  │  ├─ A.module.ts
│  │  ├─ module-B/
│  │  │  ├─ B.module.ts
│  │  app.module
│  │  App.vue
│  ├─ main.ts

Injection

Inject any type of instantiable class in the context of the module.
Anything injected becomes singleton in the module context.

When necessary, InversifyJS will instantiate the object and keep it available for other services.

@Injectable 
export class DogService {}
doguinho.inject(DogService);

Inject other services available in the module into your service constructor.

@Injectable 
export class CatsService {

  constructor(@Inject() private readonly dogsService: DogsService) {}

}
doguinho.inject(DogsService, CatsService);

It is often not possible for InversifyJS to instantiate the object being injected, for example: Vue components or Vuex stores.

Considering that there is no specific order of startup and that we do not know what will or will not be available or when, we created the lazy injection.

Lazy Injection

Make a note of a property so that it becomes a getter which, when requested, will get the result late.

export class Somewhere {

  @Inject() private readonly dogsService!: DogsService
  
}

Note: providers are searched for in their own module and then in the global context if they are not found.

Using with vuex-module-decorators

@Module
export default class DogsStore extends VuexModule {

  @Inject() private readonly dogsService!: DogsService;
  
  @Action
  public async createDog(name: string): Promise<Dog> {
      // do something with DogsService
  }

}

You can inject the store so that it will be available anywhere in the scope of that module.

doguinho.inject(DogStore);

Using with vue-class-component

@Component
export default class SomeComponent extends Vue {

  @Inject() private readonly dogsStore!: DogsStore;
  
  /* ... do something wih DogsStore */

}