[GH-ISSUE #4770] Allow databaseHooks + user.deleteUser in plugin #27379

Closed
opened 2026-04-17 18:22:47 -05:00 by GiteaMirror · 8 comments
Owner

Originally created by @benjaminpreiss on GitHub (Sep 19, 2025).
Original GitHub issue: https://github.com/better-auth/better-auth/issues/4770

Is this suited for github?

  • Yes, this is suited for github

I want to setup database hooks and user delete actions through a plugin. E.g. like this:

export const auth = betterAuth({
  database: new Database(dbPath),

  emailAndPassword: { enabled: true },

  user: {
    deleteUser: {
      enabled: true,
      afterDelete: async (user: any) => {
          // action
      },
    },
  },

  databaseHooks: {
    user: {
      create: {
        after: async (user: any) => {
          // action
        }
      },
    },
  },
})

Describe the solution you'd like

It would be great if it'd be possible to configure databaseHooks and user.deleteUser through a plugin.

Describe alternatives you've considered

Manually adding a database hooks (worse DX)

Additional context

No response

Originally created by @benjaminpreiss on GitHub (Sep 19, 2025). Original GitHub issue: https://github.com/better-auth/better-auth/issues/4770 ### Is this suited for github? - [x] Yes, this is suited for github ### Is your feature request related to a problem? Please describe. I want to setup database hooks and user delete actions through a plugin. E.g. like this: ```ts export const auth = betterAuth({ database: new Database(dbPath), emailAndPassword: { enabled: true }, user: { deleteUser: { enabled: true, afterDelete: async (user: any) => { // action }, }, }, databaseHooks: { user: { create: { after: async (user: any) => { // action } }, }, }, }) ``` ### Describe the solution you'd like It would be great if it'd be possible to configure `databaseHooks` and `user.deleteUser` through a plugin. ### Describe alternatives you've considered Manually adding a database hooks (worse DX) ### Additional context _No response_
GiteaMirror added the lockedenhancement labels 2026-04-17 18:22:47 -05:00
Author
Owner

@ping-maxwell commented on GitHub (Sep 19, 2025):

I'm in favour of this and it has been apart of my plans for some time now, but haven't gotten to it yet

Just got to get confirmation from the team that it makes sense before I get to it, also might be some time since we're focused on a lot of other stuff right now.

For more context: In order to do this we would be moving database hook calling logic to the adapter factory which will allow us to accurately call user DB hooks for any action (including delete) automatically. Right now all DB hooks are called from our internal-adapter which is manual and not automatic.

<!-- gh-comment-id:3312526980 --> @ping-maxwell commented on GitHub (Sep 19, 2025): I'm in favour of this and it has been apart of my plans for some time now, but haven't gotten to it yet Just got to get confirmation from the team that it makes sense before I get to it, also might be some time since we're focused on a lot of other stuff right now. For more context: In order to do this we would be moving database hook calling logic to the adapter factory which will allow us to accurately call user DB hooks for any action (including delete) automatically. Right now all DB hooks are called from our internal-adapter which is manual and not automatic.
Author
Owner

@benjaminpreiss commented on GitHub (Sep 19, 2025):

While we are at it - would be really cool if the plugins could have the auth.api object available internally, e.g. through this? Or by offering an onInit: (auth: BetterAuth) => () => void key in the plugin, where one can run stuff on betterAuth instance creation, with the return value from the onInit function being the cleanup?

<!-- gh-comment-id:3312772564 --> @benjaminpreiss commented on GitHub (Sep 19, 2025): While we are at it - would be really cool if the plugins could have the `auth.api` object available internally, e.g. through `this`? Or by offering an `onInit: (auth: BetterAuth) => () => void` key in the plugin, where one can run stuff on betterAuth instance creation, with the return value from the `onInit` function being the cleanup?
Author
Owner

@benjaminpreiss commented on GitHub (Sep 30, 2025):

@Bekacru @ping-maxwell is there a pull request that I can look into with which this was merged? Can't find it in the past releases bullet points...

<!-- gh-comment-id:3350921766 --> @benjaminpreiss commented on GitHub (Sep 30, 2025): @Bekacru @ping-maxwell is there a pull request that I can look into with which this was merged? Can't find it in the past releases bullet points...
Author
Owner

@ping-maxwell commented on GitHub (Sep 30, 2025):

I think this was closed mistakenly.

<!-- gh-comment-id:3352396319 --> @ping-maxwell commented on GitHub (Sep 30, 2025): I think this was closed mistakenly.
Author
Owner

@benjaminpreiss commented on GitHub (Sep 30, 2025):

Database hooks seem to be supported for plugins, if you check the source code. But couldn't find delete user support...

<!-- gh-comment-id:3352421565 --> @benjaminpreiss commented on GitHub (Sep 30, 2025): Database hooks seem to be supported for plugins, if you check the source code. But couldn't find delete user support...
Author
Owner

@benjaminpreiss commented on GitHub (Sep 30, 2025):

... true - doesnt work on 1.4.0-beta.5. And I think it's not in 1.4.0-beta.6 either.

<!-- gh-comment-id:3354034747 --> @benjaminpreiss commented on GitHub (Sep 30, 2025): ... true - doesnt work on `1.4.0-beta.5`. And I think it's not in `1.4.0-beta.6` either.
Author
Owner

@benjaminpreiss commented on GitHub (Oct 1, 2025):

There is something happening with databaseHooks in the plugin initialization: 19f39cb400/packages/better-auth/src/init.ts (L259-L287)

It assigns the value of options.databaseHooks returned from the plugin init function to the hooks property in createInternalAdapter. Is this desired behaviour? This seems a little out of sync to me to the rest of the plugin interface...

E.g. that I need to return the databaseHooks from the plugins init function, but the hooks can be defined directly:

const somePlugin = {
    hooks: {...},
    async init() {
        return {context, options: {databaseHooks: ...}}
    }
}

Is this intended? Also, why are the databaseHooks that are returned from the plugin init function assigned to the hooks property in createInternalAdapter? Is this correct?

Also, I think it is not permitted in the types currently to pass a custom context property, but it should be:

const somePlugin = {
    async init() {
        return {context: {customContextProperty: "hey-there"}}
    }
}

To do's:

  • An update to the docs detailing the init property in the plugin interface, especially the return type.
  • Fix a type error in the plugin init function types (they don't allow for custom return properties)
<!-- gh-comment-id:3355176165 --> @benjaminpreiss commented on GitHub (Oct 1, 2025): There is something happening with databaseHooks in the plugin initialization: https://github.com/benjaminpreiss/better-auth/blob/19f39cb400d1b7afe925528bb58bccb8c3f077c3/packages/better-auth/src/init.ts#L259-L287 It assigns the value of `options.databaseHooks` returned from the plugin init function to the `hooks` property in `createInternalAdapter`. Is this desired behaviour? This seems a little out of sync to me to the rest of the plugin interface... E.g. that I need to return the databaseHooks from the plugins init function, but the hooks can be defined directly: ```ts const somePlugin = { hooks: {...}, async init() { return {context, options: {databaseHooks: ...}} } } ``` Is this intended? Also, why are the databaseHooks that are returned from the plugin init function assigned to the `hooks` property in createInternalAdapter? Is this correct? Also, I think it is not permitted in the types currently to pass a custom context property, but it should be: ``` const somePlugin = { async init() { return {context: {customContextProperty: "hey-there"}} } } ``` To do's: - [ ] An update to the docs detailing the `init` property in the plugin interface, especially the return type. - [ ] Fix a type error in the plugin init function types (they don't allow for custom return properties)
Author
Owner

@benjaminpreiss commented on GitHub (Oct 1, 2025):

Good news: database hooks and delete user is available as a return from the init property in the plugin interface.
This code in my plugin works: d087d7934f/packages/plugins/src/better-auth/plugin.ts (L167-L173)

<!-- gh-comment-id:3356379213 --> @benjaminpreiss commented on GitHub (Oct 1, 2025): Good news: database hooks and delete user is available as a return from the `init` property in the plugin interface. This code in my plugin works: https://github.com/benjaminpreiss/payload-better-auth/blob/d087d7934f190419c07585e9ff08fdf303d4a375/packages/plugins/src/better-auth/plugin.ts#L167-L173
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#27379