Giter Site home page Giter Site logo

Comments (6)

Sayan751 avatar Sayan751 commented on June 16, 2024 1

@Vheissu Thanks for the clarification and providing the example use cases. For handling configuration options, there might be an easier way of dealing with configuration options. The following example is inspired by the options pattern in .netcore.

The idea is that there is one configuration source (can be more, though) and there is a configuration manager. This looks like below:

// this is loosely the schema of the configuration source, say config.json
interface ConfigurationOptions {
  features: string[]; // turn this into an array of literal type if that is what you needed
}

export const IConfigurationManager = DI.createInterface<IConfigurationManager>('IConfigurationManager', x => x.singleton(ConfigurationManager));
export type IConfigurationManager = ConfigurationManager;

export class ConfigurationManager<TConfig extends ConfigurationOptions = ConfigurationOptions> {
  private _systemConfigs: TConfig | undefined = undefined;
  
  public setConfiguration(systemConfigs: TConfig): void {
    systemConfigs.features = systemConfigs.features ?? [];
    this._systemConfigs = systemConfigs;
  }

  public isFeatureEnabled(featureName: string): boolean {
    return features.includes(featureName); // cache the result if you want
  }
}

Then you can simply inject the IConfigurationManager in your class and check if a certain feature flag is enabled or not. IN that way, you don't need to override any container registrations from tests, and you can rather provide the ConfigurationManager#setConfiguration with a different set of configuration options. Starting from this and creating a TC like with-feature="flagone" might be a trivial step.

<!-- the element-one will only be rendered if the flagone feature is on.
<element-one with-feature="flagone"></element-one>

Implementing the IContainer#deregister for this purpose seems like an overkill TBH. On a different note, this might be a good opportunity to implement something like the options pattern in .netcore for Au2, to offer something standard to manage application configuration options. 😉

from aurelia.

Sayan751 avatar Sayan751 commented on June 16, 2024

Thanks @Vheissu for drafting the detailed RFC!
I have question regarding the enhancement 1 and 3. From the examples provided, the difference is not clear to me. Can you elaborate on that?

My personal opinion is that we opt for the 2nd alternative. Replacing a registered component in a DI, should be a conscious decision due to its potentially disruptive/destructive nature. Hence, I think that it should not be made extra user-friendly.

On a different note, I got a bit stuck by this:

The need to override dependencies arises primarily in tests, where it might be desirable to stub/mock dependencies.

So far, the existing DI infrastructure worked pretty well for me to supply those overrides from the tests. Would you mind sharing some example code to demonstrate where exactly the existing infra lacks?

from aurelia.

Vheissu avatar Vheissu commented on June 16, 2024

@Sayan751 That was my bad on the example. I missed the deregister method. Enhancement 3 proposes implementing a deregister method and supporting a configurable override: true flag.

Enhancement 2 is where I am naturally leading, too. It would be the least destructive change to DI. And it would be intentional what deregister does, especially if someone uses it and wonders why dependencies are not present.

There is a workaround currently where you can use getAll or all and I added in a last resolver which will get the last dependency if there are multiple registered under the same key. However, this arose from a use-case that goes something like this:

Say you have feature flags as enums:

export enum FeatureFlags {
  flagOne = 'valueone',
  flagTwo = 'valuetwo',
  flagThree = 'valuethree',
}

You then register those feature flags inside of some bootstrap code:

container.register(Registration.instance(FeatureFlags.flagOne, false));

You can inject that feature flag in your code:

static inject = [FeatureFlags.flagOne]

Inside your test you want to override the value:

bootstrap(() => {
    container.register(Registration.instance(FeatureFlags.flagOne, true));
});

This will add the value, not override the original feature flag value. Because it's the same container (bootstrap logic stuff is happening outside of the test and abstracted away because there's some globally repeated test stuff).

from aurelia.

bigopon avatar bigopon commented on June 16, 2024

Something like a flag/feature manager sounds like an excellence built in 💯 , we can have it in the addons package, or core is also fine too.

For the ability to undo a resolver, I quite agree that it is an overkill for this scenario, though there' cases where we need it in the framework ourselves, for example, hot reload where we also need to remove the old resource resolver to register the new one. That said, we don't have to do it now if we want to implement the suggestion from @Sayan751 .

from aurelia.

Sayan751 avatar Sayan751 commented on June 16, 2024

My vote is to add the options pattern to the kernel package. As it is expected to be a low level infra, although it will be a public API. The advantage will be that inside the core package we can use that to better transport the configuration options in different parts of the core components.

from aurelia.

bigopon avatar bigopon commented on June 16, 2024

Resolved by #1981

from aurelia.

Related Issues (20)

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.