Skip to content
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

[Feaure Request] implement a way to register a callback to be called when class is instantiated #5

Open
blikblum opened this issue Apr 12, 2024 · 7 comments

Comments

@blikblum
Copy link

Bottlejs has a concept of decorator https://github.com/young-steveo/bottlejs?tab=readme-ov-file#decorators that is a function that runs when class / service is instantiated

Currently i use to register event handlers when a class declares one or more

@zheksoon
Copy link
Owner

Thanks for the request, totally makes sense :)

@zheksoon
Copy link
Owner

Done, see https://github.com/zheksoon/dioma?tab=readme-ov-file#injection-hooks section of README

@blikblum
Copy link
Author

Many thanks.

Can you show me how can i get the instance and or the class using container, descriptor, args parameters?

@zheksoon
Copy link
Owner

Sure! The descriptor is the object that was used in .register method. Example from README:

wild.register({ token: animalToken, class: Dog, scope: Scopes.Transient() });

So you can use descriptor.class, descriptor.token, descriptor.scope from it, if specified when registering the class.
As the beforeCreate is called before the class instance is available, there is no way to get it. Maybe to add another hook like afterCreate, what do you think?

@blikblum
Copy link
Author

Maybe to add another hook like afterCreate, what do you think?

Yes. To cover the use case i cited and covered by bottlejs#decorator.

If i understand correct, beforeInject is called every time is injected right? (just for understanding)

Some notes:

  • I cannot see a use case for beforeCreate since AFAIK is not possible to change how instance is created unless modifying descriptor which is something i would not recommend thinking of API design
  • Initially i think in a way to register the hook in the container instance being called for all classes registered in it (like in bottlejs). But is something that can be easily overcome by creating a helper function in "userland" that registers a class using a predefined hook. So i would not pursue any change here

@blikblum
Copy link
Author

Here's my concrete user case:

Declare the class to be injected

// @service register a class in the DI container
// @taskHandler register the method in the a property of class constructor to be used as event handlers
@service('schedulesStore', ['appStore'])
class SchedulesStore extends SchedulesQuery {
  constructor(appStore) {
    super()
    bindRefParams(appStore, this, {
      customerId: 'currentCustomer',
    })
    this.observe()
  }

  @taskHandler('save-schedule')
  saveSchedule({model, attrs, dirtyAttrs}) {
    if(model.isNew()) {
      return this.create(attrs)
    }

    return model.save(dirtyAttrs, { patch: true })
  }
}

export { SchedulesStore }

start listening to the events

// in the start of app
// bindClassTasks checks if there are handlers registered in constructor and configure the event listeners
registry.decorator((instance) => {
  bindClassTasks(instance)
  return instance
})

@zheksoon
Copy link
Owner

Ah, ok, I see. Will think about the implementation. But PRs are welcome! :)

@zheksoon zheksoon reopened this Apr 16, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants