Max
Max

Reputation: 1220

DatabaseController in NodeJS MySQL with Typescript

I am developing a restAPI with nodejs, express and mysql. Now I have a app.js which is the starting point of the App.

Within app.js I initialize the UserController:

const router: express.Router = express.Router();
new UserController(router);

The UserController looks like this:

import { Request, Response, Router } from 'express';
import UserModel from '../model/user';

class UserController {

  constructor(private router: Router) {

    router.get('/users', async (req: Request, resp: Response) => {
      try {
        // const users = get Users with mysql
        // resp.status(200).send(users);
      } catch (error) {
        resp.send({
          msg: 'Not found',
          status: 404
        });
      }
    });

  }

}

export default UserController;

Now I would like to have a DatabaseController which handels everything around the Database like providing a Connection, closing it and so on:

class DatabaseController {

  constructor() {

  }

}

export default DatabaseController;

How can I achieve that I open the connection in the DatabaseController and let the UserController simply access it? Is that even possible without initializing the DatabaseController and giving the UserController a parameter "dbConnection"?

Upvotes: 1

Views: 5073

Answers (1)

Cisco
Cisco

Reputation: 23052

Yes it's possible. I'm not entirely familiar with typescript so some psuedo code below. Untested.

Somewhere in another file, configure your database connection and the service:

import { MyConnection } from 'my-db-package';

class DatabaseService {
  private connection: MyConnection

  constructor(db: MyConnection) {
    this.connection = db;
  }

  // Return the promise if any.
  // Don't want to handle the error here.
  // Let your controller handle the error
  async openConnection() {
    return this.connection.open()
  }

  async closeConnection() {
    return this.connection.close()
  }

  async getAllUsers() {
    return this.connection.query('SELECT * FROM USERS;')
  }

}

export default DatabaseService;

import { Database } from 'my-db-driver'
import { DatabaseService } from 'my-db-service'

// Don't actually connect here
// Just create the object so it's ready for connection.
const connection = new Database({
  // config
})

// Wire up the internal db connection
// Remember this is a singleton.
export default new DatabaseService(connection)

Next wire up your controller with the new database service:

import { Request, Response } from 'express';
import { DatabaseService } from './my-service'

class UserController {
  private dbService: DatabaseService;

  constructor(dbService: DatabaseService) {
    this.dbService = dbService;
  }

  async connect() {
    return this.dbService.openConnection()
  }

  async close() {
    return this.dbService.closeConnection()
  }

  async getAllUsers(req: Request, res: Response) {
    let users

    try {
      users = await this.dbService.getAllUsers();
    } catch (error) {
      // ...
    }

    res.json(users)
  }

}

export default UserController;

Then hook up your routes:

import { express } from 'express'
import { UserController } from 'user-controller'
import { DatabaseService } from 'database-service'

const userController = new UserController(DatabaseService);
const router: express.Router = express.Router();

router.get('/users', userController.getAllUsers)
// ...

export default router

Finally, hook up your routes with the main Express app:

import { express } from 'express'
import { userRoutes } from 'user-routes'

const app = express()

app.use(userRoutes)
// ..

Again, the above code is untested and likely unusable. It is meant to give you an example of one approach. You may find a better way to do it, but that's the gist of it.

Upvotes: 4

Related Questions