Giter Site home page Giter Site logo

athennaio / ioc Goto Github PK

View Code? Open in Web Editor NEW
8.0 8.0 0.0 1.87 MB

๐Ÿ“ฆ Global Ioc helper for Athenna ecosystem. Built on top of awilix.

Home Page: https://athenna.io

License: MIT License

TypeScript 100.00%
athenna awilix esm ioc-container nodejs service-container service-provider typescript

ioc's Introduction

AthennaIO ๐Ÿฆด

The Athenna scaffold project used by 'athenna new project' command to create your project.

GitHub followers GitHub stars

Buy Me A Coffee

GitHub language count Repository size License Commitizen

Links

For project documentation click here. If something is not clear in the documentation please open an issue in the documentation repository

Contributing

If you want to contribute to this project, first read the CONTRIBUTING.MD file. It will be a pleasure to receive your help.


With ๐Ÿ’œ by Athenna community

ioc's People

Contributors

jlenon7 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

ioc's Issues

[Bug]: Package @athenna/common being used as dependency

Version

1.3.2

Steps to reproduce

Create a new Athenna project with athenna new... command.
Install a different version of @athenna/common package. Example: npm install @athenna/[email protected]
Now inside of node_modules/@athenna/common we will have the version 1.0.0 of @athenna/common. But inside node_modules/@athenna/ioc we will have the version 1.0.2 of @athenna/common.

Expected behavior

I expect that when I install the version 1.0.0 of @athenna/common that @athenna/config package uses the same version.

Actual behavior

Two versions of @athenna/common are installed, one specific for @athenna/ioc and the other for the project. This means that I can't choose which version of the package I want to use globally in the project.

Additional context

No response

Environment

System:
    OS: Linux 5.14 Ubuntu 20.04.5 LTS (Focal Fossa)
    CPU: (8) x64 11th Gen Intel(R) Core(TM) i5-1145G7 @ 2.60GHz
    Memory: 6.19 GB / 15.03 GB
    Container: Yes
    Shell: 5.8 - /usr/bin/zsh
  Binaries:
    Node: 16.18.0 - ~/.nvm/versions/node/v16.18.0/bin/node
    npm: 8.19.2 - ~/.nvm/versions/node/v16.18.0/bin/npm

[Bug]: Error when lifetime is TRANSIENT

Version

1.3.1

Steps to reproduce

Register a dependency with TRANSIENT lifetime and try to mock it using __mock method.

Expected behavior

I expect that TRANSIENT lifetime dependencies could be mocked.

Actual behavior

An error is thrown because transient method does not exist in Ioc class.

Additional context

Implementation to fix these scenarios in Facade.__mock method:

const dictionary = {
  SCOPED: 'scoped', // This method should be implemented in Ioc class.
  TRANSIENT: 'bind',
  SINGLETON: 'singleton'
}

const registration = Facade.container.list()[this.alias]
const lifetime = dictionary[registration.lifetime] ? dictionary[registration.lifetime] : 'bind'

Facade.depsMocksRestoreMap.set(`${this.alias}::${method}`, this.Provider.prototype[method])

this.Provider.prototype[method] = returnValue

Facade.container[lifetime](this.alias, this.Provider, true)

Environment

System:
    OS: Linux 5.14 Ubuntu 20.04.5 LTS (Focal Fossa)
    CPU: (8) x64 11th Gen Intel(R) Core(TM) i5-1145G7 @ 2.60GHz
    Memory: 6.19 GB / 15.03 GB
    Container: Yes
    Shell: 5.8 - /usr/bin/zsh
  Binaries:
    Node: 16.18.0 - ~/.nvm/versions/node/v16.18.0/bin/node
    npm: 8.19.2 - ~/.nvm/versions/node/v16.18.0/bin/npm

[Feature]: Update version to 3.0.0

๐Ÿš€ Feature Proposal

The version of this package needs to be updated to 3.0.0.

Motivation

We are going to start versioning the Athenna packages using Semver. All packages of Athenna will be updated to version 3.0.0 to start following Semver rules.

Example

No response

[Bug]: Impossible to mock dependencies in test hooks

Version

4.2.0

Steps to reproduce

In test hooks like @BeforeAll(), re-register a dependency using the ioc:

@BeforeAll()
public async beforeAll() {
  ioc.instance('App/Services/AppService', {})
}

The above code doesn't change the appService injected in the controller because the @Inject() annotation is executed when appController is imported to be registered in the service container.

Expected behavior

I expect to be able to re-register dependencies of any type and in an any time.

Actual behavior

Re-registering dependencies in runtime is not possible.

Additional context

This means that we need to refactor @Inject() annotation to use a proxy like Facade to respect when the service is not registered yet, and also to be able to re-register service providers in runtime.

This means that @Service() annotation should also not really register the dependency, but only prepare it to be registered by CoreProvider that will import all the services registered in the .athennarc.json file.

Goal

None service provider could be "resolved" from the service container until the first user interaction with the application starts from the client.

In other words, Athenna cannot call use() and safeUse() methods when bootstrapping the application, only by closures.

Environment

System:
    OS: macOS 13.5.2
    CPU: (8) arm64 Apple M1 Pro
    Memory: 77.44 MB / 16.00 GB
    Shell: 5.9 - /opt/homebrew/bin/zsh
  Binaries:
    Node: 18.14.2 - ~/.nvm/versions/node/v18.14.2/bin/node
    npm: 9.5.0 - ~/.nvm/versions/node/v18.14.2/bin/npm

[Bug]: Facades being generated with wrong type

Version

1.3.0

Steps to reproduce

Run the node artisan make:facade Facade command.

Expected behavior

I expect that my facade has the typeof Facade and the instance type of my dependency.

Actual behavior

The facade has the instance type of Facade and the instance type of my dependency.

Additional context

No response

Environment

System:
    OS: Linux 5.14 Ubuntu 20.04.5 LTS (Focal Fossa)
    CPU: (8) x64 11th Gen Intel(R) Core(TM) i5-1145G7 @ 2.60GHz
    Memory: 6.19 GB / 15.03 GB
    Container: Yes
    Shell: 5.8 - /usr/bin/zsh
  Binaries:
    Node: 16.18.0 - ~/.nvm/versions/node/v16.18.0/bin/node
    npm: 8.19.2 - ~/.nvm/versions/node/v16.18.0/bin/npm

[Bug]: If dependency cannot be found inside the map, __restore should return void

Version

1.3.1

Steps to reproduce

Call Facade.__restore('not-found') in a method that is not mocked.

Expected behavior

I expect that the __restore method returns void and do not throw errors.

Actual behavior

The __restore method will set the method prototype as undefined in the provider.

Additional context

No response

Environment

System:
    OS: Linux 5.14 Ubuntu 20.04.5 LTS (Focal Fossa)
    CPU: (8) x64 11th Gen Intel(R) Core(TM) i5-1145G7 @ 2.60GHz
    Memory: 6.19 GB / 15.03 GB
    Container: Yes
    Shell: 5.8 - /usr/bin/zsh
  Binaries:
    Node: 16.18.0 - ~/.nvm/versions/node/v16.18.0/bin/node
    npm: 8.19.2 - ~/.nvm/versions/node/v16.18.0/bin/npm

[Feature]: Implement the mock method for Facades

๐Ÿš€ Feature Proposal

The mock method will be responsible for mocking a single method of the Facade.

Here is an example of how this could be done inside __callStatic method of FacadeProxyHandler class:

  __callStatic(facade, key) {
    const provider = facade.getFacadeRoot(this.#facadeAccessor)

    if (key === 'mock') {
      return (method, returnValue) => {
        provider[method] = returnValue

        const providerNameCamel = String.toCamelCase(provider.constructor.name)
        const registration = facade.container.list()[providerNameCamel]
        const lifetime = registration.lifetime ? registration.lifetime.toLowerCase() : 'bind'

        facade.container[lifetime](this.#facadeAccessor, provider, true)
      }
    }

    /**
     * Access methods from the Facade class instead of
     * the provider.
     */
    if (facade[key] && !provider[key]) {
      return facade[key]
    }

    const apply = (method, _this, args) => method.bind(provider)(...args)

    if (provider[key] === undefined) {
      return undefined
    }

    if (!Is.Function(provider[key])) {
      return provider[key]
    }

    return new Proxy(provider[key], { apply })
  }

A better approach would be to create a new class that would be instantiated by the FacadeProxyHandler that would extend a lot of methods for the Facades.

Also, it's not mandatory, but mock method should save the old provider state, this way we could implement a method called release(method) that would be responsible to remove the mocked value from the provider.

Motivation

Let the developer to easy mock the facade methods in tests.

Example

MyFacade.mock('hello', () => 'mocked!')
MyFacade.hello() // 'mocked!'

MyFacade.release('hello')
MyFacade.hello() // 'world!'

[Bug]: The package @athenna/test needs to be dynamically imported

Version

4.4.1

Steps to reproduce

  1. Install production dependencies only in any Athenna application.
  2. Try to run the application
  3. Error happens

Expected behavior

I expect that my Facades does not depend on @athenna/test package to be able to work.

Actual behavior

The @athenna/test package needs to be installed as production dependency to run an Athenna application.

Additional context

A good way to fix this is to use Module.safeImport() method and save the value in a constant. The value will only be used when calling mock related methods of Facades (this kind of methods are used for testing purposes only, so we are assuming that the user will not use them in production).

Environment

System:
    OS: macOS 13.5.2
    CPU: (8) arm64 Apple M1 Pro
    Memory: 77.44 MB / 16.00 GB
    Shell: 5.9 - /opt/homebrew/bin/zsh
  Binaries:
    Node: 18.14.2 - ~/.nvm/versions/node/v18.14.2/bin/node
    npm: 9.5.0 - ~/.nvm/versions/node/v18.14.2/bin/npm

[Feature]: Implement the __restoreAll method in Facades

๐Ÿš€ Feature Proposal

This method will help to easily restore all the mocked methods of the Facade.

Motivation

Help developer gain time. With __restoreAll he does not need to keep calling __restore method:

Facade.__restore('methodx')
Facade.__restore('methody')

Example

Facade.__restoreAll()

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.