onebeyond / systemic

📦 A minimal dependency injection framework.
https://onebeyond.github.io/systemic
MIT License
56 stars 7 forks source link

Optional dependencies #57

Closed teunmooij closed 2 years ago

teunmooij commented 2 years ago

I'd like to be able to set an optional dependency on a component.

Use case: A library defining a subsystem that can be included in multiple services that might or might not have a certain component. The susbsytem in the library can contain a componentan that has optional dependency on a component in the service. If it exists it will be injected.

Example

/// library
const System = require('systemic');
const { defaultMiddleware, app, server } = require('systemic-express');

const expressSystem = System({ name: 'express' })
  .add('app', app())
  .dependsOn('config', 'logger')
  .add('middleware', defaultMiddleware())
  .dependsOn('logger', 'app', 'routes')
  .add('server', server())
  .dependsOn('config', 'app', 'middleware');

module.export = { expressSystem };

/// service using the library
const System = require('systemic');
const { expressSystem } = require('my-express-system');
const { routes } = require('...');

const system = System({ name: 'main' })
  .include(expressSystem())
  .add('routes', routes()).dependsOn('app')

In this exmplate the routes will be added before the middleware, but if the system doesn't contain routes, an error is thrown when starting the system because of the missing dependency. This could be solved by making the routes dependency optional.

I'll include a PR with an implementation of this proposed change.

cressie176 commented 2 years ago

Hi @teunmooij,

Thanks for the issue and PR. I'd like to make sure I understand the goal of this feature before accepting. It seems like the idea is provide generic system patterns, or strategies. For example you could have a generic "web-application" system, which expected a configuration, a web server, and database components. However, to support web applications that do not require a database because all data is managed by a RESTful service, you would like the ability to make the database component optional.

Is this the sort of think you are trying to solve?

teunmooij commented 2 years ago

Hi @cressie176,

Yes, that's the basic idea. Actually the example I gave in the issue description is not just a random example. That's my actual usecase. I'd like to create an express sub-system with some default configuration, middleware and admin-routes. Some of my services in which I'd like to use this subsystem have additional routes, but some other don't. In the ones that do, i want to register some middleware AFTER my routes get registered.

cressie176 commented 2 years ago

Hi @teunmooij,

That makes sense. Thank you for your PR.

teunmooij commented 2 years ago

Thanks for reviewing

cressie176 commented 2 years ago

Published as systemic@v4.1.0