Se o senhor ainda não ouviu falar do Nodal ainda, ou o senhor já tem, mas
não sabe por onde começar, este tutorial é para o senhor! Certifique-se de que o senhor
acompanhar o Nodal no GitHub para acompanhar
atualizações do projeto.


O Nodal é uma plataforma e estrutura de servidor Node.js que permite que o senhor desenvolva
serviços de API com facilidade. Com produtos cada vez mais multiplataforma
(Web, dispositivos móveis, IoT), precisamos começar a pensar em nossa arquitetura de backend
usando uma abordagem orientada a serviços para começar, e não como uma reflexão posterior.


O objetivo do Nodal é construir uma enciclopédia em torno do Node.js que permita que qualquer
desenvolvedor – novato ou veterano, back-end ou front-end – participe e comece
a criar aplicativos da Web sem esforço.


O Nodal tem suporte integrado ao PostgreSQL, faz uso frequente da sintaxe moderna do ES6 e
e incentiva padrões de design de software bastante rígidos. Isso permite que o Nodal
tome uma série de decisões para que o usuário possa criar seus aplicativos
e implantados rapidamente, com mais confiança. Comece a escrever o código que alimenta
seu produto mais rapidamente e deixe a Nodal fazer o trabalho pesado.


Embora a principal competência da Nodal não esteja sendo usada como um servidor Web monolítico tradicional
servidor Web, ele pode ainda ser usado para essa finalidade. Isso está fora do escopo deste
mas, pesquisando a documentação, o senhor poderá descobrir como
fazer com que o Nodal faça o que o senhor quiser – servir um site de marca estática,
suporte a modelos, etc.


Nosso primeiro projeto nodal


Embora muito do Nodal lhe seja familiar se você já tiver trabalhado com uma estrutura MVC
como o Django ou o Ruby on Rails, começaremos com a configuração básica de um
API Server básico configurado e gerar alguns modelos. É bom começar com
um projeto de amostra, então vamos criar um clone do Twitter chamado Instatweet.


Para referência, o senhor pode encontrar uma versão completa do projeto usado para este
tutorial em keithwhor/instatweet-api
no GitHub.


Configurando a Nodal


Para instalar o Nodal e fazê-lo funcionar com um banco de dados, precisaremos fazer
o seguinte:


  1. Instalar o Node.js 4.x ou superior
  2. Instalar o PostgreSQL
  3. Instalar o Nodal


Instalação do Node.js


Para ter certeza de que está executando uma versão recente do Node.js, basta acessar
Nodejs.org e baixe a versão 4.x mais recente ou
superior. O Nodal foi desenvolvido explicitamente para a versão 4.x, portanto, é o que é
recomendado no momento.


Instalação do PostgreSQL


Se estiver usando o Mac OS X, recomendo enfaticamente usar Postgres.app
para colocar o PostgreSQL em funcionamento em sua máquina. Certifique-se de que o senhor
configure seu $PATH para
obter acesso às ferramentas de linha de comando. Depois que o Postgres.app estiver instalado e o senhor tiver
seguido as instruções para configurar a CLI, verifique se há um superusuário postgres
superusuário chamado postgres (sem senha) com:



$ createuser postgres -s


Para uma instalação do Windows, o senhor pode verificar o site do PostgreSQL.


Instalação do Nodal


O senhor está quase pronto para começar a configurar servidores de API em um piscar de olhos. 🙂


Para instalar o Nodal, basta abrir a linha de comando do Terminal e digitar:



$ npm install nodal -g


Isso instalará as ferramentas de linha de comando do Nodal e a versão atual do
núcleo do Nodal. O senhor está pronto para começar!


Criando seu projeto


A configuração do projeto é fácil. Vá para o diretório no qual o senhor deseja criar sua pasta de projeto
pasta do projeto e digite:



$ nodal new


O senhor verá um prompt…



Welcome to Nodal! v0.7.x



? Nome (my-nodal-project)

O senhor pode dar o nome que quiser, mas eu vou usar instatweet-api para
este tutorial. Também será solicitado que o senhor digite seu nome. O Nodal irá
criar o diretório do projeto para o senhor e copiar todos os pacotes necessários
(node_modules) de sua instalação global do nodal.


Iniciando seu servidor


Inicialize seu servidor com:



$ nodal s


O senhor verá algo como:



[Nodal.Daemon] Startup: Initializing
Initializer Ready
[Nodal.Daemon] Startup: Spawning HTTP Workers
[Nodal.27454] Startup: Starting HTTP Worker
[Nodal.27455] Startup: Starting HTTP Worker
[Nodal.27455] Ready: HTTP Worker listening on port 3000
[Nodal.27454] Ready: HTTP Worker listening on port 3000


Na verdade, o senhor verá um novo [Nodal.XXXX] processo gerado para cada um dos
núcleos do seu processador. Portanto, se o senhor vir 16 mensagens aqui (2 para cada núcleo),
não se preocupe com isso. Isso é apenas o Daemon fazendo seu trabalho. 🙂


O Nodal faz um bom trabalho ao se reiniciar quando há alterações nos arquivos, portanto, deixe o servidor
servidor em execução e abrir outra janela do Terminal e navegar de volta para o diretório do projeto
instatweet-api.


Criando seu primeiro modelo


Criar um modelo é simples. Abra seu terminal e digite:



$ nodal g:model Tweet user_id:int body:string


O senhor verá algo como:



Create: ./app/models/tweet.js
Create: ./db/migrations/2016022003113671__create_tweet.js


Um arquivo de modelo e uma migração foram criados automaticamente para o senhor.


O arquivo Model contém informações sobre o objeto Tweet em seu projeto,
que contém um campo inteiro chamado user_id e um corpo que é uma string.


O arquivo Migration é um conjunto de comandos para criar uma tabela no banco de dados Postgres
para armazenar dados do Tweet, com os campos como colunas na tabela.


Criando seu primeiro Controller


Agora que temos um modelo, queremos um controlador para esse modelo. Podemos usar
a linha de comando novamente para facilitar esse processo:



$ nodal g:controller v1 --for:Tweet


O v1 nos indica um namespace e o --for:Tweet nos informa que o Controller
é um controlador Create-Read-Update-Destroy (CRUD) para um recurso Model
(fará algumas coisas para nós). Observe que algo como:



$ nodal g:controller v1/Tweet


também é aceitável, mas criará um modelo de controlador vazio sem os comandos
CRUD, portanto, o senhor precisará escrever todas as funções por conta própria.


A partir desse comando, o senhor deve ver:



Create: ./app/controllers/v1/tweets_controller.js
Modify: ./app/router.js


As ferramentas de linha de comando do Nodal modificaram automaticamente suas rotas e criaram
seus controladores para o senhor. O roteador adicionou automaticamente determinados caminhos padrão
caminhos e métodos HTTP, como GET e POST, para servir a API para tweets –
listando, criando, atualizando, excluindo tweets, etc.


Executando migrações


Agora que o senhor tem um Tweet Model e uma migração, antes de começarmos a fazer a interface
com nosso Tweet Model, queremos ter certeza de que o banco de dados está pronto para lidar com ele;
Crie o banco de dados especificado em config/db.json com:



$ nodal db:create


Agora, prepare-o para as migrações e, em seguida, execute essas migrações com:



$ nodal db:prepare
$ nodal db:migrate


Interface com nossos tweets


Certifique-se de que seu servidor esteja sendo executado novamente no localhost com nodal s.


Abrir http://localhost:3000/v1/tweets em seu navegador. Essa é a rota que
foi criada automaticamente ao criar o modelo Tweet. Observe que nós
pluralizamos automaticamente o modelo Tweet para que a rota seja “tweets”;
O senhor deve ver:



{
  "meta": {
    "total": 0,
    "count": 0,
    "offset": 0,
    "error": null
  },
  "data": []
}


Para criar um tweet, basta enviar uma solicitação POST para o mesmo endpoint com
dados JSON ou dados codificados por url. O senhor pode usar curl para isso. (Verifique também o
Plug-in Postman para Chrome, uma ferramenta visual que é ótima para acessar dados de e para APIs).



$ curl --data "user_id=1&body=Testing" http://localhost:3000/v1/tweets


Sua resposta deve ser mais ou menos assim:



{
  "meta": {
    "total": 1,
    "count": 1,
    "offset": 0,
    "error": null
  },
  "data": [
    {
      "id": 1,
      "user_id": 1,
      "body": "Testing",
      "created_at": "2016-02-20T03:21:30.879Z",
      "updated_at": "2016-02-20T03:21:30.882Z"
    }
  ]
}


Atualize a página de seu navegador em http://localhost:3000/v1/tweets e o senhor
deverá ver o tweet lá.


Criação de um modelo de usuário


Ótimo! Agora temos Tweets, mas queremos alguns usuários. Para lidar com a criptografia de senha
(para que o senhor não precise escrevê-la por conta própria), o Nodal vem com um
modelo de usuário pré-criado que o senhor pode gerar:



$ nodal g:model --user


Esse modelo de usuário será gerado com username, email e password
automaticamente, juntamente com os campos bcrypt para criptografia de senhas.


Gere um Controller para seus modelos de usuário com:



$ nodal g:controller v1 --for:User


Migre seu banco de dados com:



$ nodal db:migrate


Execute seu servidor com nodal se envie a seguinte solicitação POST para criar
um usuário:



$ curl --data "username=test_user&email=test@test.com&password=password" http://localhost:3000/v1/users


O senhor receberá uma resposta como:



{
  "meta": {
    "total": 1,
    "count": 1,
    "offset": 0,
    "error": null
  },
  "data": [
    {
      "id": 1,
      "email": "test@test.com",
      "password": "$2a$10$/pXLNrp9afneJtImvNTBO.79CIsd8N39fko4sF3CaXZyoaxpctQZS",
      "username": "test_user",
      "created_at": "2016-02-20T03:27:58.152Z",
      "updated_at": "2016-02-20T03:27:58.255Z"
    }
  ]
}


Maravilhoso! Temos usuários, e eles têm senhas criptografadas.


Ocultação de campos sensíveis e validações de modelos


Visite http://localhost:3000/v1/users em seu navegador para ver uma lista de todos os
o senhor poderá notar um problema. A API retorna a senha criptografada. Isso
não é algo que queremos. Para corrigir isso, abriremos o app/models/user.js:


Encontre as linhas:



User.validates('email', 'must be valid', v => v && (v + '').match(/.+@.+\.\w+/i));
User.validates('password', 'must be at least 5 characters in length', v => v && v.length >= 5);


Abaixo deles, adicione:



User.hides('password');


Abrir http://localhost:3000/v1/users em seu navegador e pronto! A senha desapareceu.


O senhor pode estar se perguntando o que o User.validates(...) são sobre as chamadas. Bem,
vamos tentar um novo curl com uma senha…



$ curl --data "username=test_user&email=test@test.com" http://localhost:3000/v1/users


Incrível! Nossas validações funcionam como esperado. O senhor pode tentar usar
com elas por conta própria.



{
  "meta": {
    "total": 0,
    "count": 0,
    "offset": 0,
    "error": {
      "message": "Validation error",
      "details": {
        "password": [
          "must be at least 5 characters in length"
        ]
      }
    }
  },
  "data": []
}


Como associar usuários a tweets em respostas de API


O senhor notará que em nosso primeiro Tweet especificamos um user_id. Podemos
certificar-se de que associamos usuários a Tweets em nossa resposta da API fazendo o seguinte.


Primeiro, abra o app/models/tweet.js:



module.exports = (function() {

  'use strict';

  const Nodal = require('nodal');

  class Tweet extends Nodal.Model {}

  Tweet.setDatabase(Nodal.require('db/main.js'));
  Tweet.setSchema(Nodal.my.Schema.models.Tweet);

  return Tweet;

})();


Antes de return Tweet, adicione as linhas:



const User = Nodal.require('app/models/user.js');
Tweet.joinsTo(User, {multiple: true});


Agora, abra o app/controllers/v1/tweets_controllers.js e encontre index():



index() {

  Tweet.query()
    .where(this.params.query)
    .end((err, models) => {

      this.respond(err || models);

  });
}


Altere isso para:



index() {

  Tweet.query()
    .where(this.params.query)
    .join('user')
    .end((err, models) => {
      this.respond(err || models, ['id', 'body', 'created_at', 'user']);
    });
}


Atualizar http://localhost:3000/v1/tweets em seu navegador e o senhor verá:



{
  "meta": {
    "total": 1,
    "count": 1,
    "offset": 0,
    "error": null
  },
  "data": [
    {
      "id": 1,
      "body": "Testing",
      "created_at": "2016-02-20T03:21:30.879Z",
      "user": {
        "id": 1,
        "email": "test@test.com",
        "username": "test_user",
        "created_at": "2016-02-20T03:27:58.152Z",
        "updated_at": "2016-02-20T03:27:58.255Z"
      }
    }
  ]
}


O senhor deve ter notado que passamos um segundo parâmetro para o this.respond(...). Esse
é conhecido como o parâmetro Interface do modelo e informa ao controlador quais
campos do modelo devem ser realmente exibidos na resposta da API. Por padrão, o
Controller exibirá todos os campos, com exceção daqueles que o senhor marcou como
sensíveis/ocultos (acima). Ele exibirá nãono entanto, não exibem nenhum modelo de junção
unidos. O senhor precisará especificá-los manualmente (como fizemos aqui, com
'user'). Se o senhor quiser restringir quais campos do User model mostram,
faça o seguinte:



this.respond(err || models, ['id', 'body', 'created_at', {user: ['username']}]);


Como associar tweets a usuários


A associação de tweets a usuários é um processo semelhante. Adicionaremos ao app/models/user.js:



const Tweet = Nodal.require('app/models/tweet.js');
User.joinedBy(Tweet, {multiple: true});


Nota: Certifique-se de que o joinsTo deve sempre ser especificado no
criança (qualquer que seja a tabela/modelo que tenha a parent_id ), e
joinedBy é sempre especificado no campo pai table. Essas convenções são
importantes.


Da mesma forma, em app/controllers/v1/user_controller.js altere seu index()
para:



index() {

  User.query()
    .where(this.params.query)
    .join('tweets')
    .end((err, models) => {

      this.respond(
          err || models,
          [
            'id',
            'username',
            'email',
            'tweets'
          ]
        );
    });
}


e o senhor verá a resposta:



{
  "meta": {
    "total": 1,
    "count": 1,
    "offset": 0,
    "error": null
  },
  "data": [
    {
      "id": 1,
      "username": "test_user",
      "email": "test@test.com",
      "tweets": [
        {
          "id": 1,
          "user_id": 1,
          "body": "Testing",
          "created_at": "2016-02-20T03:21:30.879Z",
          "updated_at": "2016-02-20T03:21:30.882Z"
        }
      ]
    }
  ]
}


Semeando seu banco de dados


Tudo bem, isso é legal, mas vamos gerar alguns dados de teste!


Abrir config/seed.json:



{
  "development": {},

  "test": {},

  "production": {}

}


Modifique isso para:



{

  "development": {
    "User": [
      {
        "username": "Rihanna",
        "email": "rihanna@r.com",
        "password": "password"
      },
      {
        "username": "The Weeknd",
        "email": "weeknd@w.com",
        "password": "password"
      },
      {
        "username": "Drake",
        "email": "drake@d.com",
        "password": "password"
      }
    ],
    "Tweet": [
      {
        "userid": 1,
        "body": "Hello, world"
      },
      {
        "userid": 2,
        "body": "hello, world!"
      },
      {
        "user_id": 3,
        "body": "You used to call me on my cell phone, world"
      }
    ]
  },

"test": {},

"production": {}

}


Agora vamos executar:



$ nodal db:bootstrap


E visite http://localhost:3000/v1/tweets (certifique-se de que o servidor esteja funcionando):



{
  "meta": {
    "total": 3,
    "count": 3,
    "offset": 0,
    "error": null
  },
  "data": [
    {
      "id": 1,
      "body": "Hello, world",
      "created_at": "2016-02-20T04:08:38.762Z",
      "user": {
        "id": 1,
        "email": "rihanna@r.com",
        "username": "Rihanna",
        "created_at": "2016-02-20T04:08:38.765Z",
        "updated_at": "2016-02-20T04:08:38.765Z"
      }
    },
    {
      "id": 2,
      "body": "hello, world!",
      "created_at": "2016-02-20T04:08:38.764Z",
      "user": {
        "id": 2,
        "email": "weeknd@w.com",
        "username": "The Weeknd",
        "created_at": "2016-02-20T04:08:38.767Z",
        "updated_at": "2016-02-20T04:08:38.767Z"
      }
    },
    {
      "id": 3,
      "body": "You used to call me on my cell phone, world",
      "created_at": "2016-02-20T04:08:38.764Z",
      "user": {
        "id": 3,
        "email": "drake@d.com",
        "username": "Drake",
        "created_at": "2016-02-20T04:08:38.767Z",
        "updated_at": "2016-02-20T04:08:38.767Z"
      }
    }
  ]
}


Fantástico! O que fizemos aqui foi definir uma semente de banco de dados especificando uma matriz de
com os quais preencheremos cada tabela no banco de dados. A chave para
cada matriz (como "User") é apenas o nome do modelo. db:bootstrap é um comando
que executa nodal db:prepare, nodal db:migrate e nodal db:seed, nessa
ordem.


Consultando seu endpoint


A última coisa que faremos é começar a solicitar ao nosso endpoint diferentes tipos de
resultados. O senhor deve ter notado um .where(this.params.query) na página do index()
para ambos os nossos controladores. Isso está criando um método filtro por meio de
no qual escolhemos seletivamente quais resultados gostaríamos de obter com base nos parâmetros de consulta HTTP
parâmetros.


Por exemplo, experimente abrir estes arquivos em seu navegador:



http://localhost:3000/v1/tweets?body=Hello,%20world
http://localhost:3000/v1/tweets?body__is=Hello,%20world
http://localhost:3000/v1/tweets?body__not=Hello,%20world
http://localhost:3000/v1/tweets?body__startswith=Hello
http://localhost:3000/v1/tweets?body__istartswith=Hello
http://localhost:3000/v1/tweets?body__endswith=world
http://localhost:3000/v1/tweets?user__username=Drake


Comparadores compatíveis com o adaptador PostgreSQL (obrigatório) __ antes deles) são:



is
not
lt
lte
gt
gte
contains
icontains
startswith
istartswith
endswith
iendswith
like
ilike
is_null
not_null
in
not_in
json
jsoncontains


Observe que o padrão é __ise o senhor pode consultar modelos unidos usando
o nome da união (ou seja, o user) e separando o campo com sublinhados duplos como
bem (__).


Aproveite e continue explorando!


Isso encerra o tutorial por enquanto. Lembre-se de que o senhor pode encontrar uma versão completa de
tudo o que foi descrito aqui em keithwhor/instatweet-api.
Há muito mais que o senhor pode fazer com o Nodal,
incluindo esta demonstração do GraphQL, mas deve
haver material suficiente aqui para o senhor começar.


Confira o site da Nodal
e Iniciar o repositório no GitHub para
manter-se atualizado à medida que o projeto cresce e progride. Convidamos o senhor a participar da
comunidade! Nosso Canal Gitter é um ótimo
lugar para obter respostas rápidas e dicas.


Além disso, o senhor pode acompanhar um conjunto de screencasts
que abordam material muito semelhante com base no Nodal 0.6.


Obrigado pela leitura. 🙂 O senhor pode me seguir no Twitter em @keithwhor.

Keith Horwood

Sobre Keith Horwood

Keith é um desenvolvedor autodidata de Toronto, Canadá, apaixonado por aprender e construir. Ex-líder de engenharia da Storefront, sua aventura mais recente foi a criação do Polybit, um serviço que permite que os desenvolvedores criem e implementem com mais eficiência seus back-ends de aplicativos para que possam se concentrar em seus produtos e clientes.