Git Product home page Git Product logo

typedi's Introduction

    /)            /                 
   // _   _  (   /_  _,  , , _ _ _  
  //_/ (_(/_/_)_/ /_(_)_(_/_/ / / /_
 /)                  /|             
(/                  (/              

Is Unicode still cool? Anyway, I'm freshgum. I'd say "Nice to meet you", but I don't know who you are (and it's cringe).

Tip

I'm migrating quite a few projects over to my Codeberg account.

GitHub's telling me to put what I'm working on in here, so...

The best way to get in touch with me is via e-mail: freshgum hyphen bubbles at proton (no space) mail dot com

typedi's People

Contributors

2betop avatar asvetliakov avatar attilaorosz avatar bbakhrom avatar binki avatar bruno-brant avatar bsitruk avatar codemilli avatar dependabot[bot] avatar digitalkaoz avatar freshgum-bubbles avatar github-actions[bot] avatar gjdass avatar happyzombies avatar klassm avatar nightink avatar nonameprovided avatar orimdominic avatar pepakriz avatar petermetz avatar pleerock avatar sobolevn avatar suchcodemuchwow avatar timwolla avatar tonivj5 avatar zibanpirate avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

typedi's Issues

Per-version changelogs

Now we're approaching 1.0, it would be nice to have changelogs for each push to stable.
These could be generated from commit names, or done manually (or a combination of both!).

Development Mode Ideas

Potentially, a development mode could be introduced into TypeDI++.
This would assist with the introspection of individual containers, as well as a few other features.

As a baseline for whether it's worth implementing this in the first place, I'll create a list here and
add scenarios to it wherein the usage of development mode could be advantageous.

  • warning when a service is changed after services depending upon that service have already been constructed
  • [ ]

Provide a way to get fresh transient services without HostContainer

Currently, the only way to get fresh instances of a transient service are by using HostContainer.
It feels nasty to recommend using what is essentially an escape hatch instead of a more sensible API.

import { Service, HostContainer } from '@typed-inject/inject';
import { TimerService } from './timer.service';

@Service([
    HostContainer()
])
export class PageService {
    constructor (private container: ContainerInstance) { }

    async renderPage () {
        const timer = this.container.get(TimerService);
        timer.setName('page-render');
        timer.start();
        // Perform page rendering logic...
        timer.end();
    }
}

ESLint Switch-On

The ESLint configuration was a bit pedantic for my liking, so I turned it off.
I'd like to turn ESLint back on, perhaps with less telling-offs, sometime in future.

Dependencies aren't currently type-checked

Currently, the parameters of a class aren't type-checked against its dependencies.

Consider the following:

@Service([AnotherService])
export class MyService {
  constructor (private randomValue: number) { }
}

It's a clear error, but it still compiles.
This is because currently, TypeDI does not read the constructor's arguments.
Instead, the arguments are typed as any[].

I believe I've found a workaround for this; a PR can be expected soon.

Release on NPM

At some point, this should be released on NPM so I can actually use it.

Add a (better) way to notify services of container disposal

Currently, containers are just dropped from the service with no warning:

public reset(options: { strategy: 'resetValue' | 'resetServices' } = { strategy: 'resetValue' }): this {
this.throwIfDisposed();
switch (options.strategy) {
case 'resetValue':
this.metadataMap.forEach(service => this.disposeServiceInstance(service));
break;
case 'resetServices':
this.metadataMap.forEach(service => this.disposeServiceInstance(service));
this.metadataMap.clear();
this.multiServiceIds.clear();
break;
default:
throw new Error('Received invalid reset strategy.');
}
return this;
}

This seems quite strange. Services would surely want some form of notification
as to when their container is disposed of.

While a seemingly simple concept, the notion of how individual services are meant
to respond to such a notification is ambiguous. For instance, in the case of a database
service, is it meant to close down its database connection(s) when the container is disposed?
Furthermore, in such a case, should we provide a way for the caller of .dispose or .reset to
know when all such asynchronous events have been concluded?

One further challenge is how you would provide an API for such a notification.
It would be awkward to make services conform to a standard interface for notification,
and any runtime type-checking of notification handler methods could incur runtime errors.

This somewhat ties into typestack/typedi#230:

allow containers to dispose of themselves, destroying all locally registered service

Proposed APIs

Addition of @DisposeService decorator

@Service([])
export class DatabaseService {
  @DisposeService
  async dispose(): Promise<void> { }
}

@Service([DatabaseService])
export class RootService {
  constructor (private database: DatabaseService) { }

  @DisposeService([DatabaseService])
  async dispose (): Promise<void> { }
}

The decorator allows a list of dependencies to be passed.
The dependencies are guaranteed not to be disposed before
the returned dispose promise is settled.

For example, in the case of RootService, it may want to
perform further operations on the database (flushing caches, etc.)
before the database is disposed of (which would close the connection).
In this case, it can declare that it requires DatabaseService to dispose of
the application correctly. As such, it can return a Promise that, until settled,
will have an undisposed reference to DatabaseService available.

Use HostContainer

This is already a no-go, but for posterity...

Using this API would mean that tests would have to pass in a container instance for potentially nothing.
Also, we'd have to expose an addDisposeListener or the likes onto the class, which feels awkward.


Definitely needs further investigation.

Version 1 (Stable) Roadmap

I'd like to get this library stable some time soon.

There are a few "nice to haves" that'd be, well, nice to have, before that happens.
Think of this as a quasi-block but, if enough time passes, these features won't make
it into this roadmap window.

typestack/typedi compatibility layer proposal

Compatibility layer with typestack/typedi

#158 essentially proposes a compatibility layer which allows the usage of ++ in places where typestack's implementation is expected.

I definitely think this is worth exploring; it's not a use-case I originally considered,
but I do think it would expand the horizons of where ++ could be used.

A wise investment would be creating a list of incompatibilities with source.
Let's do that here.

  • xxx

General compatibility with typestack

Compatibility with typestack has been a bit of a bug bear of mine.
I've been meaning to make it easier to migrate to this one.
I can only imagine the work required to have to migrate at-once; this could definitely be made easier.

Will this work with Typegraphql?

Will this work with Typegraphql and Bun? I will try it tonight and see how far I get. I am also new to DI so not sure about the library or technology as their isn't much documentation on it here.

So yes, big question will this work with Typegraphql?! Thanks for all the awesome work.

Update

It didn't work unfortunately, would love for it to though!

I tried to pass the default {Container} to the graphql builder both Apollo and Graphql Yoga builders and it errors as they expect get() and Typedi does match their interface.

Theres a quick win if you can support Apollo and Graphql yoga you'd have quite a few users of this library as many use Typegraphql in production and are searching for DI libraries that are still being maintained.

Here's a thread on it:

https://www.reddit.com/r/typescript/comments/fo1equ/typedi_cheat_sheet/

Typedi++ would need a small wrapper to match the graphql builder interfaces which would be big win for us as we could easily just switch to using Type++ :))

Interface support

Is your question related to a contrib/ feature?

No

Question

it's will be injection supported using the interface instead of classes in some version, or is it already possible?

Confusion regarding arguments passed to service factory tuples

Describe the bug
factory function with arguments,It's not the engine.
To Reproduce

import {Container, Service} from '@freshgum/typedi';

@Service([])
class Engine {
    public type = 'V8';

    public get name() : string {
        return 'bmw';
    }
}

@Service([Engine])
class CarFactory {
    createCar(engine: Engine) {
        console.log(engine);    // ContainerInstance not Engine
        engine.type = 'V6';
        return new Car(engine);
    }
}

@Service({ factory: [CarFactory, 'createCar'] }, [Engine])
class Car {
    constructor(public engine: Engine) {

    }
}

const car = Container.get(Car);
console.log(car.engine.type);
console.log(car.engine.name);  // undefined
  • OS: MacOS
  • Browser Chrome
  • Version ^0.7.1

Regression in unreleased 0.6.0's Container dispose functinality

Describe the bug

In 0.6.0, the ContainerInstance.dispose method now correctly awaits the disposing of said container.
Unfortunately, this seems to have introduced regressions in the test suite, which are still being investigated.

0.6.0 has not yet been released, so there's a window to fix these unexpected regressions before they go live.

Container Plug-Ins

Dagger has a concept called Service Provider Interface, which allows consumers to hook into the module loading process.

Some use-cases of this include:

  1. Generating a report of the overall service tree
  2. Adding warnings for services which should be scoped to a container (instead of being global)
  3. Throwing errors when the DI container or any of its services are used incorrectly

I believe this would be a valuable addition to the project,
although I'm not entirely sure how it would be implemented.
Dagger's concept of loading modules differs entirely from that of TypeDI and,
therefore, the implementation of this in TypeDI will most likely be very different.

Another point of note is that, currently, there's no other way to hook into the default container.

As of now, you could hack this together with the following:

export class HookedContainerInstance extends ContainerInstance {
  get (x, y) { /* ... */ }
}

const hookedDefaultContainer = new HookedContainerInstance('default');
await ContainerRegistry.removeContainer(ContainerInstance.defaultContainer);
ContainerRegistry.registerContainer(hookedDefaultContainer);

However, this is very error-prone. None of the services have been copied over,
meaning providers declared via @Service and with reference to the default
container will no longer be resolvable.
Furthermore, it relies on awaiting the removal of the container.
This may introduce race conditions and result in undefined behaviour.


This is food for thought; this is a great feature and something I'd like to implement.

Clean up GitHub Actions jobs

Currently the GitHub Actions CI workflow is... pretty ugly.
We copy-paste the Node+PNPM installer pretty much everywhere.

To attempt to fix this, I tried to make a reusable workflow which didn't go so well.

I'd really appreciate help from someone who actually knows how to use GitHub Actions.

- name: Set up Node
uses: actions/setup-node@v2
with:
node-version: 'lts/*'
registry-url: https://registry.npmjs.org
- uses: pnpm/action-setup@v2
name: Install pnpm
id: pnpm-install
with:
version: 8.6.1
- name: Set PNPM Cache Directory
id: pnpm-cache
shell: bash
run: |
echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT
- uses: actions/cache@v3
name: Restore PNPM Package Cache
with:
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-store-

A way to subscribe to container creation

It might be helpful if a way to subscribe to the creation of a certain container was implemented.
This is similar to CustomElementsRegistry.whenDefined.

Needs investigation as to whether this feature has any merit and is feasible.

For instance:

Container.whenDefined('task-1', container => console.log(container.get('CONFIG')));

Implementation Challenges

  • Should the listener immediately be called when the container is created, or when its received all services?
  • If 2, how do we know when the services have all been added?

API Reference not present at typedi.js.org

Hi! I switched to this fork from upstream and I'm finding some of the APIs confusing, but that's beside the point. I went to the docs, and every doc link worked except for the API Reference. /api-reference returns a 404, in fact. Maybe it's related to this build error I get when i build the API reference using the typedoc command? I've run out of things to check on my end so I don't know whether it's an issue with this repo or not.

 ~/c/u/typedi  on develop  pnpm install && pnpm run docs:api-reference
Lockfile is up to date, resolution step is skipped
Packages: +772
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Progress: resolved 0, reused 716, downloaded 0, added 772, done

> @freshgum/[email protected] prepare /home/blue/code/utils/typedi
> husky install

husky - Git hooks installed
Done in 8s

> @freshgum/[email protected] docs:api-reference /home/blue/code/utils/typedi
> rimraf website/build/api-reference && typedoc

[info] Loaded plugin @mxssfd/typedoc-theme
[warning] The entrypoint glob ./src/index.ts did not match any files.
[error] Unable to find any entry points. See previous warnings.
 ELIFECYCLE  Command failed with exit code 3.

 ~/c/u/typedi  on develop   

PNPM version: 8.7.0
Node version v18.17.0
typedi version: latest commit as of 10/03/23 10:26 EDT
(also tried with Bun package manager / runtime 1.0.3, didn't work either)

If there's a better way to read the API docs or compile them myself, please do let me know!

  • blue

EDIT: sorry for not clarifying, but i did try and fix all of the issues, like first changing the entrypoint, then setting the typedoc tsconfig to use the tsconfig.spec, however none of them ultimately solved the problems and it still threw dozens of compile errors relating to JSX usage and various unresolveable modules.

Asynchronous Services: A Better Solution

In one of my applications, I have quite a few services which require explicit bootstrapping
before they can be safely used. In the case of that specific application, my solution boiled
down to a bootstrap (): Promise<void> method on services that needed to perform an
asynchronous action before it was usable.

As a result, a lot of services ended up like:

@Service([DatabaseService, WebServerService])
export class RootService {
  constructor (protected database: DatabaseService, protected webServer: WebServerService) {}

  async bootstrap () {
    await this.database.bootstrap();
    await this.webServer.bootstrap();
  }
}

There might be a way to solve this in DI.
While it looks like there was a proposal to add asynchronous services in TypeDI, it never emerged.
Additionally, it introduced a substantial amount of complexity into the API.

Another problem with that proposal was forcing all asynchronous services to be "ready"
before any other services could run. This, of course, has the side effect of slowing down the app.
Any important synchronous tasks can't be performed until everything is ready.
This would, of course, quickly bog the application down when a number of async services are introduced.

As a result, I'd like to create a different API that would handle this differently.
Namely, some of the design proposals for this API include:

  • Being able to import asynchronous services without "initialising" them.
  • Not having to wait for every asynchronous service to load before the app can start.
  • Being able to control the order of execution for asynchronous services.

Definitely food for thought.

Built-ins can be set in containers

Built-ins such as Number and String can currently be set
to values in the Container. This is a problem, as the API
never resolves built-ins to container values.

Therefore, we should prevent this by checking if a value
passed to Container.set is a built-in before we add it.

Unable to build node.js typescript project using the library: Missing exported members

Describe the bug
Project does not build, due to typedi build errors:

> [email protected] build
> tsc -p tsconfig.json                   

node_modules/@freshgum/typedi/build/esm5/container-instance.class.d.mts:4:58 - error TS2724: '"./interfaces/service-options.interface.mjs"' has no exported member named 'ServiceOptionsWithoutTypeOrDependencies'. Did you mean 'ServiceOptionsWithoutDependencies'?
                                                                                                                                                                                                                                                                     
4 import { ServiceOptions, ServiceOptionsWithDependencies, ServiceOptionsWithoutTypeOrDependencies } from './interfaces/service-options.interface.mjs';                                                                                                              
                                                           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                                                                                                                                                                   

node_modules/@freshgum/typedi/build/esm5/container-instance.class.d.mts:12:10 - error TS2305: Module '"./types/service-identifier-location.type.mjs"' has no exported member 'ServiceIdentifierLocation'.

12 import { ServiceIdentifierLocation } from './types/service-identifier-location.type.mjs';
            ~~~~~~~~~~~~~~~~~~~~~~~~~

node_modules/@freshgum/typedi/build/esm5/functions/lazy.function.d.mts:2:10 - error TS2305: Module '"../types/infer-service-type.type.mjs"' has no exported member 'InferServiceType'.

2 import { InferServiceType } from '../types/infer-service-type.type.mjs';
           ~~~~~~~~~~~~~~~~

node_modules/@freshgum/typedi/build/esm5/index.d.mts:21:10 - error TS2305: Module '"./types/service-identifier-location.type.mjs"' has no exported member 'ServiceIdentifierLocation'.

21 export { ServiceIdentifierLocation } from './types/service-identifier-location.type.mjs';
            ~~~~~~~~~~~~~~~~~~~~~~~~~

node_modules/@freshgum/typedi/build/esm5/interfaces/tree-visitor.interface.d.mts:4:10 - error TS2305: Module '"../types/service-identifier-location.type.mjs"' has no exported member 'ServiceIdentifierLocation'.

4 import { ServiceIdentifierLocation } from '../types/service-identifier-location.type.mjs';
           ~~~~~~~~~~~~~~~~~~~~~~~~~

node_modules/@freshgum/typedi/build/esm5/types/type-wrapper.type.d.mts:3:10 - error TS2305: Module '"./infer-service-type.type.mjs"' has no exported member 'InferServiceType'.

3 import { InferServiceType } from './infer-service-type.type.mjs';
           ~~~~~~~~~~~~~~~~


Found 6 errors in 5 files.

Errors  Files
     2  node_modules/@freshgum/typedi/build/esm5/container-instance.class.d.mts:4
     1  node_modules/@freshgum/typedi/build/esm5/functions/lazy.function.d.mts:2
     1  node_modules/@freshgum/typedi/build/esm5/index.d.mts:21
     1  node_modules/@freshgum/typedi/build/esm5/interfaces/tree-visitor.interface.d.mts:4
     1  node_modules/@freshgum/typedi/build/esm5/types/type-wrapper.type.d.mts:3

To Reproduce

Use preconfigured project:

  1. Clone https://github.com/JonathanIlk/typedi-build-issue
  2. npm run build

DIY:

  1. Download typescript node.js boilerplate project (https://github.com/jsynowiec/node-typescript-boilerplate)
  2. Add @freshgum/typedi as dependency to package.json
  3. Add experimentalDecorators to tsconfig.json
  4. Add class with @service Decorator to main.ts
  5. npm run build

Expected behavior
Project builds correctly.

Desktop (please complete the following information):

  • OS: Windows
  • Typescript: 5.1

Additional context
The missing types appear to be missing from the interface files. However they seem to be available in the source code in the github.
Maybe they went missing when deploying the package to npm?

Create a way for services to get the container

After removing code that passes in the container as a constructor parameter, there's no way for services to actually get and interact with the container.
While the Service Locator pattern is generally discouraged, an escape hatch should be provided for code which still requires it.

This could be achieved by the addition of a function which returns an ID, similar to how the resolution constraints API was implemented.

A check for said ID would then be added to ContainerInstance.get, wherein it would immediately return itself. A new Token and a .set call seems harder to implement, especially with container inheritance (what if they specifically requested a local identifier?)

Ideas

@Service([
  HostContainer()
])
export class MyService {
  constructor (private container: ContainerInstance) { }
}

Notes: If implemented like above, this will work with SkipSelf() to allow the consumer to neatly resolve the parent container. (It should also work with other constraints, though Self() and Many() would obviously be pointless.)

Question: Doubled references when injecting

Is your question related to a contrib/ feature?

No

Question

We're currently using typedi and were looking at esbuild but were stuck due to reflect-metadata not being supported. A friend recommended this library as an alternative and I couldn't help but notice in the example that dependencies need to be referenced twice:

typedi (original - also similar to how it looks in Angular):

@Service()
class RootService {
  constructor(private logger: LogService) {}
}

this library:

@Service([LogService])
class RootService {
  constructor(private logger: LogService) {}
}

The fact that you have to declare all services twice (once in the array of the @Service([]) decorator and again in the constructor) is a bit off putting to me cause it's going to add a lot of boilerplate and it'll require quite a bit of effort to migrate. I know that once I migrate, people are going to forget to maintain both the array + constructor and end up with weird errors and constantly be asking why stuff doesn't work.

Is this a technical limitation of Stage 3 decorators or more of a design decision? One thing that Angular 16 added recently was the ability to inject without the constructor like so:

@Service()
class RootService {
  private logger = inject(LogService);
}

This is nice cause you don't need to match constructor args when extending classes etc.

Types marked with @internal are excluded from typings, but still imported

Latest contains the following in container-instance:

import { ServiceOptions, ServiceOptionsWithDependencies, ServiceOptionsWithoutTypeOrDependencies } from './interfaces/service-options.interface.mjs';

...but ServiceOptionsWithoutTypeOrDependencies is marked as @internal in the TSDoc.
This seems more like a TypeScript bug, tbh.

Create Documentation

The main goal of this project is to create a better TypeDI. Also, one that I and others can use in projects.
Without documentation, that's quite hard to do.

This is definitely a goal for 1.0.

.js.org subdomain

It would be nice to have a domain ready for when docs hit stable.
js.org might be a good contendor,
as they provide subdomains of .js.org to organisations managing NPM packages etc.

Alternatively, we could stick with the standard github.io subdomain.

Container not registering classes defined in external directories

Hi, im having trouble trying to get the dependency injection to work if my files are in different directories

Im using the following structure for my project

usecases/
infrastructure/
entities/
web/

where web is a next js app
infrastructure is where I defined the following classes

import { Service } from '@freshgum/typedi';
import IAuthService from "../../../usecases/common/interfaces/authService";
import type IGateway from "../interfaces/gateway";
import ApiGateway from '../gateways/gateway';


@Service({ scope: "transient" }, [ApiGateway])
export default class AuthService implements IAuthService {
    private readonly gateway : IGateway;

    /**
     *
     */
    constructor(gateway : IGateway) {
        this.gateway = gateway;
    }
}
import IGateway from "../interfaces/gateway";
import { Service } from "@freshgum/typedi";

@Service({ scope: "singleton" }, [])
export default class ApiGateway implements IGateway {
    ...
}

EDIT: I try to use this command inside a page of my next's project

if I try to use Container.get(AuthService);

I get the following error

ServiceNotFoundError: Service with "MaybeConstructable<AuthService>" identifier was not found in the container. Register it before usage via "Container.set" or the "@Service()" decorator.

its the same error if I try to register it manually

let identifier : ServiceIdentifier = AuthService;
if (!Container.has(identifier)) {
    identifier = Container.set(AuthService);
}
const service = Container.get(AuthService);

these are my dependencies in package.json file in /web

"dependencies": {
    "18": "^0.0.0",
    "@freshgum/typedi": "^0.6.0",
    "@headlessui/react": "^1.7.17",
    "@heroicons/react": "^2.0.18",
    "@tremor/react": "^3.6.6",
    "@types/react": "18.2.20",
    "@types/react-dom": "18.2.7",
    "@types/react-router-dom": "^5.3.3",
    "axios": "^1.5.1",
    "next": "13.5.6",
    "next-auth": "^4.23.1",
    "react": "18.2.0",
    "react-dom": "18.2.0",
    "react-hook-form": "^7.48.2",
    "react-router-dom": "^6.17.0",
    "reflect-metadata": "^0.1.13",
    "sharp": "^0.32.6",
    "zod": "^3.22.4"
  },
  "devDependencies": {
    "@types/node": "^20",
    "autoprefixer": "^10",
    "eslint": "^8",
    "eslint-config-next": "13.5.4",
    "postcss": "^8",
    "tailwindcss": "^3",
    "ts-loader": "^9.5.0",
    "typescript": "^5"
  }

and this is the next.config.js file

/** @type {import('next').NextConfig} */
const nextConfig = {
    images: {
        domains: ['avatars.githubusercontent.com', 'avatar.vercel.sh']
      },
    experimental: {
      serverActions: true,
      externalDir: true,
    },
    output: 'standalone',
}

module.exports = nextConfig

it works fine if dependencies are inside a directory, as I managed to write a test file in the infrastructure folder to try injecting them (although it only works with classes defined inside the infrastructure folder)

any advise on how can I make it work using multiple directories? thanks.

Support typescript stage 3 decorator ?

I'm going to use stage 3 decorator in my typescript project with inversify, but can't not use stage 2 and stage 3 decorator at the same time.Any plan to support stage 3 decorator?

Explicit Resource Management

Currently, the API is rather unsafe, in that a service could be disposed as another service is using it.
We could combat this using an explicit resource management framework, wherein services are attained
via references, and those references can be released later. This provides guarantees to the calling code
that a service won't dispose itself while it's in-use.

We could accomplish the above using a sort of garbage collector, with a simplified implementation of
the reference counting algorithm, which is a fairly universal concept.

The advantage of this algorithm is that it gives us more information as to how the caller is using the provided
symbol, so we can make more informed decisions later.

The current APIs should not be affected by this change. In the case of a reference counter, Calls to get
should not be reference-counted to ensure backwards compatibility. Additionally, we should ensure that the
usual behaviour of disposing services (after a .get call) is still satisfied.

Find a basic implementation of this below:

const reference = Container.refer(MyService);
const myService = reference.current;

// This won't do anything, as a reference to MyService is currently held:
Container.remove(MyService);

await myService.runAsyncCode();
reference.release();

// The identifier is now removed.

A way to use this in services could be:

@Service([
  Refer(MyService)
])
class AnotherService {
  constructor (private myServiceRef: Refer<MyService>) { }
}

Questions

  • In the case of Container.remove, it would probably be best to immediately remove the identifier from the map, to ensure compatibility with code that would expect the older behaviour.
  • One aspect of interest is calling reset when a reference is held: when that reference is released, should the identifier be immediately discarded? I personally think this would be wise.

Misuse of resolution constraints is not checked

Currently, the following is allowed:

import { Service, Container, HostContainer, SkipSelf() } from '@typed-inject/injector';

const myContainer = Container.ofChild(Symbol());
const childContainer = Container.ofChild(Symbol());

@Service({ container: childContainer }, [
  [HostContainer(), SkipSelf() | SkipSelf()]
])
const LogService {
  constructor (private container: ContainerInstance) {
    // Due to the doubled usage of SkipSelf(),
    // the consumer may expect it to traverse up *twice*.
    // In that case, the result would be the default container.
    // However, this isn't the case, so the following is true:
    assert(container === myContainer);
  }
}

childContainer.get(LogService);

I feel like this should be documented somewhere.

Update to 0.5.1

I believe version 0.4.0 introduced a regression, which broke code importing
the package -- the TypeScript server was unable to resolve the types for the
imports.

A recent update has been released, 0.5.1, which remedies this problem.
Apologies for the downtime; I'm not entirely familiar with the new exports
system, and I didn't test the package -- I will endeavour to do this in future.

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.