Currently, I am utilizing ElysiaJS to establish an API. The code can be found in the following open-source repository here.
In my setup, there are three essential files: auth.routes.ts
, auth.handlers.ts
, and auth.dto.ts
. The routes file contains the path, validation object, and handler function. The validation object is exported from the auth.dto.ts
(data transfer object), while the handler function, which encompasses all logic and queries, is exported from the auth.handler.ts
.
auth.routes.ts
const authRoutes = new Elysia({ prefix: '/auth' })
/** Injecting Database Connection */
.use(databaseConfig)
/** Register User with Email and Password */
.post('/register', registerWithEmailAndPassword, registerWithEmailAndPasswordDTO)
export { authRoutes }
The databaseConfig
serves as an Elysia Plugin containing the database connection code.
auth.dto.ts
import { t } from "elysia"
export const registerWithEmailAndPasswordDTO = {
body: t.Object({
email: t.String({ format: 'email' }),
password: t.String({ minLength: 6 }),
})
}
auth.handlers.ts
/** Importing Schema */
import { type Context } from "elysia"
import Schema from "../../schema"
import { hashPassword } from "../../utils/auth.utils"
/** Destructuring Schema */
const { users } = Schema
export const registerWithEmailAndPassword = async (context: Context): Promise<string> => {
const { set, body: { email, password }, db } = context
// more code here
}
If the handler function resides within the 'auth.routes.ts' file, all relevant types are injected by Elysia, resulting in everything functioning as expected. However, when the handler function is placed in a separate file, adding the Context to the argument type does not effectively add types for the body parameters injected by the validator object nor the database config object added as a plugin.
Is there a way to correctly infer these types in the handler function present in a distinct file?
Edit
To tackle this issue, constructing the type manually worked seamlessly. Here's the code snippet:
import { dbType } from "../../config/database.config"
type RegisterType = Context & {
body: {
email: string
password: string
},
db: () => dbType
}
The RegisterType
will then be utilized in the handler function like so:
export const registerWithEmailAndPassword = async (context: RegisterType)
.
database.config.ts
// create the connection
const connection = connect({
host: process.env.DB_HOST,
username: process.env.DB_USERNAME,
password: process.env.DB_PASSWORD
})
const db = drizzle(connection, { schema, logger })
const databaseConfig = new Elysia({ name: "databaseConfig" })
.decorate('db', () => db)
export type dbType = typeof db
export default databaseConfig
Edit 2
Despite following all steps outlined in the Dependency Injection documentation, the issue still persists.