Coder Social home page Coder Social logo

routegenerator's Introduction

Route generator

Projeto destinado a criar um gerador de rotas segundo um padrão onde as rotas sejam geradas automaticamente à partir dos controllers disponíveis.

Antes de mais nada, precisamos entender como funciona a definição de rotas. Nesse exemplo utilizaremos o restify-route em conjunto com o restify, que é um framework Node focado em APIs REST.

var restify = require('restify')
var router = require('restify-route')

var server = restify.createServer()

router
	.use(server)
	.set('/users', 'get', function(req, res, next){
		res.send({
			'usuarios' : 'Lista de usuários',
			'version' : '1.0.2'
		})
		return next()
	})
	.set('/users/:id', 'get', function(req, res, next){
    const id = req.params.id
		res.send({
			'user' : id
		})
		return next()
	})

Na definição de rotas acima podemos perceber os seguintes elementos:

  • router: restify-route
  • path: /, /:id
  • method: get
  • callback: function(req, res, next)

Antes de seguirmos em frente, vamos refatorar o código acima usando ES6

var restify = require('restify')
var router = require('restify-route')

var server = restify.createServer()

router
	.use(server)
	.set('/', 'get', (req, res, next) => {
		res.send({
			'api' : 'api-rest',
			'version' : '1.0.2'
		})
		return next()
	})
	.set('/:id', 'get', (req, res, next) =>{
    const id = req.params.id
		res.send({
			'user' : id
		})
		return next()
	})

Agora vamos imaginar que nosso projeto segue a seguinte estrutura de pastas.

|-- src/
|   |-- index.js
|   |-- controller/
|   |   |-- UserController.js

Vamos refatorar o nosso código para utilizar o UserController e simplificar a definição das nossas rotas.

//index.js
router
	.use(server)
	.set('/users', 'get', (req, res, next) => {
		var Users = require('./controller/UserController').listar

		Users(req.params, (code, data) => {
			res.send(code, data)
		})
		return next()
	})
	.set('/users/:id', 'get', (req, res, next) => {
		var Users = require('./controller/UserController').obter

		Users(req.params, (code, data) => {
			res.send(code, data)
		})
		return next()
	})

Note que a definição das duas rotas é basicamente a mesma, mudando apenas o método utilizado do controller.

Abaixo o conteúdo do nosso UserController

//UserController.js
var listUsers = (data, callback) => {
    return callback(200, { 'usuarios' : 'Lista de usuarios'})
}

var getUsers = (data, callback) => {

    return callback(200,  data )
}

module.exports = {
    listar : listUsers,
    obter : getUsers
}

Nessa estrutura podemos ter uma infinidade de rotas a serem definidas para um único controller.

Antes de pensar em automatizar definição das rotas, precisamos estabelecer um padrão para definição dessas rotas dentro dos controllers. Para isso vamos refatorar nosso UserController da seguinte forma.

const listUsers = (data, callback) => callback(200, { 'usuarios' : 'Lista de usuarios'})

const getUsers = (data, callback) => callback(200,  data )

module.exports = [
    {
        path : '/users',
        method : 'get',
        action : listUsers
    },
    {
        path : '/users/:id',
        method : 'get',
        action : getUsers
    }
]

Note que agora o nosso module.exports do UserController define suas rotas possíveis e todas as informações necessárias para executa-las.

Agora podemos pensar em automatizar a criação dessas rotas, utilizando o módulo fs, nativo do Node.

const fs = require('fs')

A partir do uso desse módulo, podemos fazer a leitura do conteúdo da pasta controller e identificar quais os controllers disponíveis. Algo como:

fs.readdir(__dirname + '/controller', (err, files) => {
  //Arquivos presentes na pasta controller
})

Agora que já conseguimos obter o conteúdo da pasta controller, precisamos identificar as rotas presentes em cada arquivo. Para isso vamos executar um map nos arquivos da função readdir do fs.

fs.readdir(__dirname + '/controller', (err, files) => {
  files.map((file) => {
    //Lógica para cada arquivo.
  })
})

Agora que já conseguimos obter os arquivos, e executar uma lógica a cada um deles, podemos definir as rotas.

fs.readdir(__dirname + '/controller', (err, files) => 
  files.map((file) => {
    //Primeiro adicionamos o módulo
	  let module = require("./controller/" + file)
    //Esse módulo tem uma série de módulos internos que definimos para cada rota
    module.map((route, index) => {
      //Definimos todas as rotas definidas no nosso UserController
      router.set(route.path, route.method, (req, res, next) => {
          //Agora executamos a ação relativa à rota
          module[index].action(req.params, (code, data) => 
            res.send(code, data)
          )
      })
    })
  })
)

Agora podemos remover a definição manual de rotas do nosso index.js, deixando ele assim.

const restify = require('restify')
const router = require('restify-route')
const fs = require('fs')

const server = restify.createServer()

router
	.use(server)

fs.readdir(__dirname + '/controller', (err, files) => {
  files.map((file) => {
    //Primeiro adicionamos o módulo
	  var module = require("./controller/" + file)
    //Esse módulo tem uma série de módulos internos que definimos para cada rota
    module.map((route, index) => {
      //Definimos todas as rotas definidas no nosso UserController
      router.set(route.path, route.method, (req, res, next) => {
          //Agora executamos a ação relativa à rota
          module[index].action(req.params, (code, data) => {
            res.send(code, data)
          })
      })
    })
  })
})

server.listen(process.argv[2], () => {
  console.log('%s listening at %s', server.name, server.url);
})

Para tornar nosso código reaproveitável, podemos criar um módulo para fazer esse carregamento.

const fs = require('fs')
module.exports = (path, router) => 
  fs.readdir(path, (err, files) => {
      files.map((file) => {
          var module = require(path + file)
          module.map((route, index) => {
          router.set(route.path, route.method, (req, res, next) => {
              module[index].action(req.params, (code, data) => {
                  res.send(code, data)
              })
          })
          })
      })
  )
}

Agora basta executarmos o módulo injetando o nosso router.

var restify = require('restify')
var router = require('restify-route')
var loader = require('./lib/loader.js')

var server = restify.createServer()

router
	.use(server)

loader(__dirname + '/controller/', router)

server.listen(process.argv[2], () => {
  console.log('%s listening at %s', server.name, server.url);
})

Esse estudo foi desenvolvido com base no material AgnosticRoutes desenvolvido pelo suissa.

routegenerator's People

Contributors

dawtaylor avatar suissa avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.