-
-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Inject providers into strategies/configurable classes #303
Comments
There are 2 distinct categories to address here:
Therefore the approach to allowing provider injection for each class of object will be different. For strategies, we simply do it as in the original proposal - implement a common interface with init and destroy methods. ConfigurableOperationDefs (CODs) slightly trickier. Since they are already classes, we would have to add an export const myPromotionAction= new PromotionOrderAction({
code: 'my-complex-promotion',
args: {},
init(moduleRef) {
// what do we do with "connection"? Hoist it to the global scope as a closure?
// cannot assign it to "this", as we would with a Strategy.
const connection = moduleRef.get(getConnectionToken() as any, { strict: false });
},
execute(order, args) {
// do some calculation based on a DB lookup using "connection"
},
description: [/* ... */],
}); I think the general pattern above makes sense. It would be good to define a common interface which all of the config objects which are passed to the COD constructors would implement, with the init & destroy methods. |
When working on a extension I noticed the issue of
doesn't seem to be solved yet? What for now seems to be working is the following (in case of a payment provider): interface ConnectedPaymentMethodConfigOptions<
T extends PaymentMethodArgs = PaymentMethodArgs
> extends PaymentMethodConfigOptions<T> {
connection: Connection | null;
}
class ConnectedPaymentMethodHandler<
T extends PaymentMethodArgs = PaymentMethodArgs
> extends PaymentMethodHandler<T> {
constructor(config: ConnectedPaymentMethodConfigOptions<T>) {
super(config);
}
}
export const InvoicePaymentIntegration = new ConnectedPaymentMethodHandler({
....
connection: null,
init: function (injector) {
this.connection = injector.getConnection();
},
destroy: function () {
this.connection = null;
},
createPayment: async function (
this: ConnectedPaymentMethodHandler,
order,
args,
metadata
): Promise<CreatePaymentResult | CreatePaymentErrorResult> {
//@ts-ignore
const connection: Connection = this["options"].connection;
if (!connection) {
throw new Error(
"This shouldn't happen"
);
//use connection
}
},
}); Now this obviously isn't pretty and a global variable might be more appropriate since only one instance is created. But it made me think of a possible solution. Using Then one could use the |
Hi, sounds interesting. Could you illustrate the idea further with an example of the implementation so I can understand it better? |
Of course! |
Something like this: Tyratox@75c80b9 (Yes lifecycle.e2e-spec.ts might not be the best file for a test but as there was already an injection test in there it seemed like the easiest option for an example) |
For this implementation to work it is important not to use arrow functions as these use the
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions |
Is your feature request related to a problem? Please describe.
A number of aspects of Vendure can be customised, e.g:
These allow much flexibility to support various processes and business needs. However, they all lack a way to inject providers (services), which limits their usefulness.
We have ad-hoc work-arounds for this limitation, e.g. in the
PromotionCondition
interface we provide thecheck()
method with aPromotionUtils
object. This is not ideal though because other custom promo conditions may need other "utils" and we can't just keep inflating this object with all possible utility functions.Describe the solution you'd like
A better solution would be to allow the injection of providers using Nest's own DI system. The recently-created
JobQueueStrategy
interface allows this via aninit()
method which receives the App'sModuleRef
, which lets you inject any provider from the whole app:vendure/packages/core/src/plugin/default-job-queue-plugin/sql-job-queue-strategy.ts
Lines 25 to 31 in 2fbf37a
We could therefore define a new interface, e.g:
All configurable classes would implement this interface.
Describe alternatives you've considered
Another approach would be to use the Nest DI system more directly by injecting providers into the class constructor. However, this implies quite a different architecture for the way we handle the VendureConfig, since those strategies would not all need to be registered as providers in a Nest module, and it would also prevent the current pattern of configuring the strategy by instantiation.
The text was updated successfully, but these errors were encountered: