Unable to create plugin
I'm currently using admin plugin with phone plugin , i need a way to setup custom endpoints that enables admins to create users with a phoneNumber without otp and a role , i know it is going to be possible with custom plugin and i can directly tap into the db instance of better auth , but unfortunately , when i try to setup , there is a issue that i am encountering
2 Replies
<-- GET /auth/custom/test
# SERVER_ERROR:  TypeError: handler(...).catch is not a function
    at internalHandler (/Users/anasmohammed361/vs/webzenith/mutual-space/mutual-funds-web/node_modules/.pnpm/better-call@1.0.16/node_modules/better-call/src/endpoint.ts:340:58)
    at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
    at async api.<computed> (/Users/anasmohammed361/vs/webzenith/mutual-space/mutual-funds-web/node_modules/.pnpm/better-auth@1.3.7_react-dom@19.1.0_react@19.1.0__react@19.1.0_zod@4.0.5/node_modules/better-auth/dist/shared/better-auth.C-iQKHit.cjs:6211:22)
    at async processRequest (/Users/anasmohammed361/vs/webzenith/mutual-space/mutual-funds-web/node_modules/.pnpm/better-call@1.0.16/node_modules/better-call/src/router.ts:193:22)
    at async handler (/Users/anasmohammed361/vs/webzenith/mutual-space/mutual-funds-web/node_modules/.pnpm/better-call@1.0.16/node_modules/better-call/src/router.ts:214:16)
    at async dispatch (/Users/anasmohammed361/vs/webzenith/mutual-space/mutual-funds-web/node_modules/.pnpm/hono@4.8.5/node_modules/hono/dist/cjs/compose.js:44:17)
    at async dispatch (/Users/anasmohammed361/vs/webzenith/mutual-space/mutual-funds-web/node_modules/.pnpm/hono@4.8.5/node_modules/hono/dist/cjs/compose.js:44:17)
    at async cors2 (/Users/anasmohammed361/vs/webzenith/mutual-space/mutual-funds-web/node_modules/.pnpm/hono@4.8.5/node_modules/hono/dist/cjs/middleware/cors/index.js:106:5)
    at async dispatch (/Users/anasmohammed361/vs/webzenith/mutual-space/mutual-funds-web/node_modules/.pnpm/hono@4.8.5/node_modules/hono/dist/cjs/compose.js:44:17)
    at async logger2 (/Users/anasmohammed361/vs/webzenith/mutual-space/mutual-funds-web/node_modules/.pnpm/hono@4.8.5/node_modules/hono/dist/cjs/middleware/logger/index.js:66:5)
--> GET /auth/custom/test 500 17ms
<-- GET /auth/custom/test
# SERVER_ERROR:  TypeError: handler(...).catch is not a function
    at internalHandler (/Users/anasmohammed361/vs/webzenith/mutual-space/mutual-funds-web/node_modules/.pnpm/better-call@1.0.16/node_modules/better-call/src/endpoint.ts:340:58)
    at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
    at async api.<computed> (/Users/anasmohammed361/vs/webzenith/mutual-space/mutual-funds-web/node_modules/.pnpm/better-auth@1.3.7_react-dom@19.1.0_react@19.1.0__react@19.1.0_zod@4.0.5/node_modules/better-auth/dist/shared/better-auth.C-iQKHit.cjs:6211:22)
    at async processRequest (/Users/anasmohammed361/vs/webzenith/mutual-space/mutual-funds-web/node_modules/.pnpm/better-call@1.0.16/node_modules/better-call/src/router.ts:193:22)
    at async handler (/Users/anasmohammed361/vs/webzenith/mutual-space/mutual-funds-web/node_modules/.pnpm/better-call@1.0.16/node_modules/better-call/src/router.ts:214:16)
    at async dispatch (/Users/anasmohammed361/vs/webzenith/mutual-space/mutual-funds-web/node_modules/.pnpm/hono@4.8.5/node_modules/hono/dist/cjs/compose.js:44:17)
    at async dispatch (/Users/anasmohammed361/vs/webzenith/mutual-space/mutual-funds-web/node_modules/.pnpm/hono@4.8.5/node_modules/hono/dist/cjs/compose.js:44:17)
    at async cors2 (/Users/anasmohammed361/vs/webzenith/mutual-space/mutual-funds-web/node_modules/.pnpm/hono@4.8.5/node_modules/hono/dist/cjs/middleware/cors/index.js:106:5)
    at async dispatch (/Users/anasmohammed361/vs/webzenith/mutual-space/mutual-funds-web/node_modules/.pnpm/hono@4.8.5/node_modules/hono/dist/cjs/compose.js:44:17)
    at async logger2 (/Users/anasmohammed361/vs/webzenith/mutual-space/mutual-funds-web/node_modules/.pnpm/hono@4.8.5/node_modules/hono/dist/cjs/middleware/logger/index.js:66:5)
--> GET /auth/custom/test 500 17ms
import type { BetterAuthPlugin } from "better-auth";
import { createAuthEndpoint } from "better-auth/api";
 
export const adminCreateUserWithRole = ()=>{
    return {
        id: "custom-plugin",
        endpoints:{
            createUserWithRole:createAuthEndpoint("/custom/test", {
                method: "GET", 
            },(ctx)=>{
                // const {context} = ctx;
                //  console.log(context.session?.user);
                
                return ctx.json({
                    message: "Logged"
                })
            })
        }
    } satisfies BetterAuthPlugin
}
import type { BetterAuthPlugin } from "better-auth";
import { createAuthEndpoint } from "better-auth/api";
 
export const adminCreateUserWithRole = ()=>{
    return {
        id: "custom-plugin",
        endpoints:{
            createUserWithRole:createAuthEndpoint("/custom/test", {
                method: "GET", 
            },(ctx)=>{
                // const {context} = ctx;
                //  console.log(context.session?.user);
                
                return ctx.json({
                    message: "Logged"
                })
            })
        }
    } satisfies BetterAuthPlugin
}
import { betterAuth } from "better-auth";
// Database Adapter
import { drizzleAdapter } from "better-auth/adapters/drizzle";
import * as schema from "@repo/drizzle/schema"
import { db } from "@repo/drizzle/index";
// Plugins
import { openAPI, phoneNumber, admin as adminPlugin } from "better-auth/plugins"
// Authorization
import { admin, advisor, user, ac } from "./permission"
import { adminCreateUserWithRole } from "./plugins/admin-create-user-with-role";
const auth = betterAuth({
    appName: "Mutual Funds",
    basePath: "/auth",
    user:{
        additionalFields:{
            advisorType:{
                type:'string',
                required:false,
                input:false,
            }
        }
    },
    database: drizzleAdapter(db, {
        provider: 'pg',
        schema
    }),
    plugins: [openAPI({
        disableDefaultReference: false,
    }), 
    phoneNumber({
        sendOTP(data, request) {
            console.log(data)
            // TODO: Implement OTP sending
        },
        signUpOnVerification: {
            getTempEmail(phoneNumber) {
                return `temp-${phoneNumber}@temp.internal`
            },
            getTempName(phoneNumber) {
                return `Temp ${phoneNumber}`
            },
        },
    }),
    adminPlugin({
        ac,
        roles: {
            admin,
            advisor,
            user
        },
        adminRoles: ["admin"],
        defaultRole: "user",
    }),
    adminCreateUserWithRole(),
    ],
});
type Auth = typeof auth;
export { auth, type Auth }
import { betterAuth } from "better-auth";
// Database Adapter
import { drizzleAdapter } from "better-auth/adapters/drizzle";
import * as schema from "@repo/drizzle/schema"
import { db } from "@repo/drizzle/index";
// Plugins
import { openAPI, phoneNumber, admin as adminPlugin } from "better-auth/plugins"
// Authorization
import { admin, advisor, user, ac } from "./permission"
import { adminCreateUserWithRole } from "./plugins/admin-create-user-with-role";
const auth = betterAuth({
    appName: "Mutual Funds",
    basePath: "/auth",
    user:{
        additionalFields:{
            advisorType:{
                type:'string',
                required:false,
                input:false,
            }
        }
    },
    database: drizzleAdapter(db, {
        provider: 'pg',
        schema
    }),
    plugins: [openAPI({
        disableDefaultReference: false,
    }), 
    phoneNumber({
        sendOTP(data, request) {
            console.log(data)
            // TODO: Implement OTP sending
        },
        signUpOnVerification: {
            getTempEmail(phoneNumber) {
                return `temp-${phoneNumber}@temp.internal`
            },
            getTempName(phoneNumber) {
                return `Temp ${phoneNumber}`
            },
        },
    }),
    adminPlugin({
        ac,
        roles: {
            admin,
            advisor,
            user
        },
        adminRoles: ["admin"],
        defaultRole: "user",
    }),
    adminCreateUserWithRole(),
    ],
});
type Auth = typeof auth;
export { auth, type Auth }
Solution
This did work once i made the function async