Giter Site home page Giter Site logo

di's Introduction

@squirly/di

CircleCI semantic-release standard-readme compliant Commitizen friendly

A slim, fully typed, asynchronous dependency injection library for achieving IoC.

TODO: Fill out this long description.

Table of Contents

Install

npm install @squirly/di

Usage

Container

import {Binding, Container, Injectable} from '@squirly/di';

const AuthenticationKey = Binding<string>('AuthenticationKey');
interface Fetcher {
  fetch: () => Promise<{data: string}>;
}
const Fetcher = Binding<Fetcher>('Fetcher');

@Injectable
class Client {
  static Tag = Binding.Tag<Client>('Client');
  static Inject = Injectable.Resolution(Fetcher);

  constructor(private readonly fetcher: Fetcher) {}

  getData(): Promise<string> {
    return this.fetcher
      .fetch()
      .then(result => `Received result: '${result.data}'`);
  }
}

async function fetcherFactory(c: Container<string>): Promise<Fetcher> {
  const key = await c.resolve(AuthenticationKey);

  return {
    fetch: () =>
      Promise.resolve({
        data: `Called with AuthenticationKey "${key}"`,
      }),
  };
}

const container = Container.create()
  .bindConstant(AuthenticationKey, 'my-secret-key')
  .bindSingletonFactory(Fetcher, fetcherFactory)
  .bindService(Client, Client);

const clientResult = container.resolve(Client).then(client => client.getData());

// Logs 'Received result: Called with AuthenticationKey "my-secret-key"';
clientResult.then(console.log);

Module

Using the definitions above, a Module can be created.

import {Module} from '@squirly/di';

const module = Module.create(
  Container.create()
    .bindConstant(AuthenticationKey, 'my-secret-key')
    .bindSingletonFactory(Fetcher, fetcherFactory),
).export(Fetcher);

const moduleContainer = Container.create()
  .importModule(module)
  .bindService(Client, Client);

moduleContainer.resolve(Client).then(client => {
  client.getData(); // returns "Calling API with 'yek-terces-ym'"
});

// $ExpectError
const resolution = moduleContainer.resolve(AuthenticationKey);
// Type 'string' is not assignable to 'Fetcher | Client'

// Logs "MissingDependencyError('Could not find dependency bound to AuthenticationKey.')"
clientResult.catch(console.log);

Maintainers

Tyler Jones ~ @squirly

Contribute

PRs accepted. Commits must follow the Angular Commit Message Conventions.

If editing the README, please conform to the standard-readme specification.

License

MIT © 2018 Tyler David Jones

di's People

Contributors

dependabot-support avatar dependabot[bot] avatar ksaryan avatar squirly avatar

Stargazers

 avatar

Watchers

 avatar  avatar  avatar

Forkers

ksaryan

di's Issues

Create shortcut for registering Service bindings

When registering services, it is sometimes the case that the passed binding and constructor are an identical reference:

import {Binding, Container} from '@squirly/di';

class MyService {
  static Tag = Binding.Tag<MyService>('MyService');
}

Container.create().bindService(MyService, MyService);

It would be ideal to simplify this registration to

Container.create().bindService(MyService);

This will require creating overloads for the bindService method.

Dependabot can't resolve your JavaScript dependency files

Dependabot can't resolve your JavaScript dependency files.

As a result, Dependabot couldn't update your dependencies.

The error Dependabot encountered was:

Error while updating /package-lock.json:
No matching version found for @types/[email protected]

If you think the above is an error on Dependabot's side please don't hesitate to get in touch - we'll do whatever we can to fix it.

You can mention @dependabot in the comments below to contact the Dependabot team.

Dependabot can't resolve your JavaScript dependency files

Dependabot can't resolve your JavaScript dependency files.

As a result, Dependabot couldn't update your dependencies.

The error Dependabot encountered was:

Error while updating /package-lock.json:
No matching version found for jest-resolve-dependencies@^23.6.0

If you think the above is an error on Dependabot's side please don't hesitate to get in touch - we'll do whatever we can to fix it.

You can mention @dependabot in the comments below to contact the Dependabot team.

Better Container type safety

Currently Container is genericised on a union of the types that the Container can resolve, this is the same generic that is provided to the Binding. If it is instead genericised on the Binding, or the internal unique symbol of the binding, Container construction can have an additional layer of you typesafety.

This same principle can be applied to Module construction.

This may cause a breaking change. Though the in code surface area is limited, because it only affects Module and Container creation.

Dependabot can't resolve your JavaScript dependency files

Dependabot can't resolve your JavaScript dependency files.

As a result, Dependabot couldn't update your dependencies.

The error Dependabot encountered was:

Error while updating /package-lock.json:
No matching version found for [email protected]

If you think the above is an error on Dependabot's side please don't hesitate to get in touch - we'll do whatever we can to fix it.

You can mention @dependabot in the comments below to contact the Dependabot team.

Document `Container.Decorator`

Simple example:

export const bindDependencies = Container.Decorator<
  // the dependencies made available ("exported")
  ExportedDependency,
  // The dependencies required for the dependencies being added
  RequiredDependency1 | RequiredDependency2,
> = container => container
    // dependencies added here do not have to be "exported"
    .bindService(PrivateDependency, PrivateDependency)
    .bindService(ExportedDependency, ExportedDependency);

Create module container

When creating large projects it is beneficial to group dependencies into groups, called modules.

To limit a dependant to a subset of a container's API, modules can only allow access to some subset of registered bindings.

This change requires a implementation of the Container API that allows to create a container that does not expose it's inner registered dependencies, only a configured subset.
Additionally, the container API needs an additional method that allows inheriting dependencies from another container, it is possible this is only available in the module version of the Container API.

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.