Giter Site home page Giter Site logo

ckgrafico / inversify-props Goto Github PK

View Code? Open in Web Editor NEW
85.0 3.0 9.0 6.94 MB

Wrapper of Inversify to inject your dependencies in the components, made with TypeScript and compatible with Vue, React and other component libraries.

License: MIT License

TypeScript 96.11% JavaScript 3.89%
injection dependency-injection component vue react polymer lit-element

inversify-props's Introduction

Inversify Props

This package is a wrapper of Inversify to simplify how inject your dependencies with property decorators in the components, made with TypeScript and compatible with Vue, React and other component libraries.

Do you use Hooks? You can try the experimental package inversify-hooks

GitHub last commit GitHub license GitHub forks GitHub contributors GitHub issues

logo

Installation

$ npm install inversify-props reflect-metadata --save

The inversify-props type definitions are included in the inversify-props npm package.

How to use

import 'reflect-metadata'; // Import only once
import { container, inject } from 'inversify-props';

container.addSingleton<IService1>(Service1);
container.addSingleton<IService2>(Service2);
container.addSingleton(Service3);

export default class extends Component {
  @inject() service1: IService1;
  @inject() _service2: IService2;
  @inject() Service3: IService3;
}

⚠️ If you use a minifier or a obfuscator, you need to configure it to preserve the class and function names in the build output. See this paragraph for more info.

How to use this library outside of a component

import 'reflect-metadata'; // Import only once
import { cid, container, inject } from 'inversify-props';

container.addSingleton<IService1>(Service1, 'MyService1');

// You can inject in other services as a Prop
export class MyOtherService {
  @inject() private service1: IService1;
}

// Also in the constructor as a param
export class MyOtherService {
  constructor(@inject() private exampleService: IExampleService) {}
}

// Or in any function as a variable
export function myHelper() {
  const service1 = container.get<IService1>(cid.IService1);
}

// camelCase, PascalCase and _ are allowed
export class MyOtherService {
  @inject() private service1: IService1;
  @inject() private _service1: IService1;
  @inject() private Service1: IService1;
  @inject() private _Service1: IService1;
}

You can also use any ID that you prefer if you don't want to use auto generated ids

import 'reflect-metadata'; // Import only once
import { container, inject } from 'inversify-props';

container.addSingleton<IService1>(Service1, 'MyService1');

export default class extends Component {
  @inject('MyService1') service1: IService1;
}

This library provides a container to make your experience easier, but you can create your own container.

import 'reflect-metadata'; // Import only once
import { Container, inject, setContainer } from 'inversify-props';

setContainer(new Container());
container.addSingleton<IService1>(Service1, 'MyService1');

export default class extends Component {
  @inject('MyService1') service1: IService1;
}

⚠️ Important! inversify-props requires TypeScript >= 2.0 and the experimentalDecorators, emitDecoratorMetadata, types and lib compilation options in your tsconfig.json file.

{
  "compilerOptions": {
    "target": "es5",
    "lib": ["es6"],
    "types": ["reflect-metadata"],
    "module": "commonjs",
    "moduleResolution": "node",
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true
  }
}

Why we made this package

The idea is to add a simple wrapper that helps us to inject dependencies in components using property decorators, we have also extend a little inversify adding some methods that make our experience injecting dependencies easier.

You probably don't need this if:

  • You have experience using inversify and you don't need to simplify the process.
  • You want to use all the power of inversify, we are only injecting dependencies like services, helpers, utils...
  • You don't want to inject your dependencies as properties.

How to register a dependency

Inversify needs an id to register our dependencies, this wrapper is going to do this for you 'magically' but if you want to uglify the code, keep reading the docs 🤓.

First of all create a class and an interface with the public methods of your class.

// iservice1.ts
export interface IService1 {
  method1(): string;
}

// service.ts
export class Service1 implements IService1 {
  method1(): string {
    return 'method 1';
  }
}

Now is time to register the service in the container, we usually do that in app.container.ts or app.ts.

container.addSingleton<IService1>(Service1);

How to test

There are some helper functions to test, the recommended way to test is beforeEach test:

  1. Reset the Container
  2. Register again all the dependencies of the container (this is your job)
  3. Mock all the necessary dependencies for the test
beforeEach(() => {
  resetContainer();
  containerBuilder();
  mockSingleton<IHttpService>(cid.IHttpService, HttpServiceMock);
});

Other ways to register a class

As inversify accepts, we have configured three types of registration.

  • Singleton: The dependency will be created only once, one dependency - one object.
  • Transient: The dependency will be created each time is injected, one dependency - one object per injection.
  • Request: Special case of singleton, more info in official docs.

How to use in your components

Once your dependencies are registered in the container, is simple as create a property with the name and the interface.

export default class extends Component {
  @inject() service1: IService1;
}

Note: Part of the magic is that the name of the property has to be the name of the interface, this is how we don't need to add the id.

Some examples

How to configure Uglify or Terser

If you want to use Uglify or Terser to obfuscate the code, you will need to add this options to preserve the names of the classes (we need them to generate the ids magically 😉).

new UglifyJSPlugin({
  uglifyOptions: {
    keep_classnames: true,
    keep_fnames: true
  }
});
new TerserPlugin({
  terserOptions: {
    keep_classnames: true,
    keep_fnames: true
  }
});

Note: Vue-cli uses TerserPlugin under the hood.
You can configure the Terser plugin inside your vue.config.js file in configureWebpack node via the optimization.minimizer property.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.