{"id":3943,"date":"2017-09-01T07:00:21","date_gmt":"2017-09-01T14:00:21","guid":{"rendered":"https:\/\/www.couchbase.com\/blog\/?p=3943"},"modified":"2025-06-13T20:15:10","modified_gmt":"2025-06-14T03:15:10","slug":"midwest-js-project-source-full-stack-node-development-available","status":"publish","type":"post","link":"https:\/\/www.couchbase.com\/blog\/pt\/midwest-js-project-source-full-stack-node-development-available\/","title":{"rendered":"Fonte do Projeto JS do Centro-Oeste em Desenvolvimento de Node Full Stack, dispon\u00edvel"},"content":{"rendered":"<p>Em agosto, eu havia participado do <a href=\"https:\/\/midwestjs.com\/\" target=\"_blank\" rel=\"noopener\">Midwest JS<\/a> localizado em Minneapolis, Minnesota. Como voc\u00ea deve saber, sou um grande f\u00e3 do desenvolvimento de aplicativos de pilha completa com a pilha JavaScript. Foi exatamente sobre isso que me apresentei na confer\u00eancia.<\/p>\n<p>Minha sess\u00e3o teve uma boa participa\u00e7\u00e3o e muitos desenvolvedores aprenderam a usar o Node.js com o Couchbase para desenvolver uma API RESTful e o Angular como a camada voltada para o cliente.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-3953 size-full\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2017\/08\/midwestjs-couchbase.jpg\" alt=\"Couchbase at Midwest JS\" width=\"768\" height=\"558\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/08\/midwestjs-couchbase.jpg 768w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/08\/midwestjs-couchbase-300x218.jpg 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/08\/midwestjs-couchbase-20x15.jpg 20w\" sizes=\"auto, (max-width: 768px) 100vw, 768px\" \/><\/p>\n<p>Conforme prometido, vou revisitar o material que abordei durante a apresenta\u00e7\u00e3o para que os conceitos e o c\u00f3digo possam ser reproduzidos e ampliados.<\/p>\n<p><!--more--><\/p>\n<p>Daqui para frente, a suposi\u00e7\u00e3o \u00e9 que voc\u00ea tem <a href=\"https:\/\/www.couchbase.com\/blog\/pt\/\" target=\"_blank\" rel=\"noopener\">Servidor Couchbase<\/a>, <a href=\"https:\/\/nodejs.org\" target=\"_blank\" rel=\"noopener\">Node.js<\/a>e o <a href=\"https:\/\/ionicframework.com\/\" target=\"_blank\" rel=\"noopener\">Estrutura i\u00f4nica<\/a> CLI instalado e configurado. O Couchbase ser\u00e1 o banco de dados NoSQL, o Node.js alimentar\u00e1 nosso back-end e a estrutura Ionic nos fornecer\u00e1 um front-end da Web alimentado pelo Angular.<\/p>\n<p>O projeto criado na Midwest JS permitia armazenar informa\u00e7\u00f5es sobre consoles de videogame e jogos de videogame para v\u00e1rios consoles. Isso demonstrou o uso de CRUD, bem como as rela\u00e7\u00f5es entre documentos NoSQL e como o Couchbase facilita isso.<\/p>\n<h2>Cria\u00e7\u00e3o do back-end Node.js com Couchbase NoSQL<\/h2>\n<p>Antes de iniciarmos o desenvolvimento, precisamos criar um novo projeto Node.js. Na linha de comando, execute o seguinte:<\/p>\n<pre class=\"lang:default decode:true\">npm init -y\r\nnpm install couchbase express body-parser uuid cors --save<\/pre>\n<p>O comando acima criar\u00e1 um projeto\u00a0<strong>package.json<\/strong> e instalar as depend\u00eancias do nosso projeto. O arquivo <code>cors<\/code> nos permitir\u00e1 usar o Node e o Angular localmente em duas portas diferentes sem receber erros de compartilhamento de recursos entre origens. O pacote <code>uuid<\/code> nos permitir\u00e1 gerar cadeias de caracteres exclusivas para uso como chaves de documentos. O pacote <code>analisador de corpo<\/code> nos permitir\u00e1 enviar dados JSON em solicita\u00e7\u00f5es HTTP. Usaremos o Express e o Couchbase, o que explica os outros dois pacotes.<\/p>\n<p>Criar um\u00a0<strong>app.js<\/strong> em seu projeto. Ele conter\u00e1 todo o c\u00f3digo-fonte do nosso aplicativo Node.js. Como padr\u00e3o, ele deve se parecer com o seguinte:<\/p>\n<pre class=\"lang:default decode:true\">var Couchbase = require(\"couchbase\");\r\nvar Express = require(\"express\");\r\nvar BodyParser = require(\"body-parser\");\r\nvar UUID = require(\"uuid\");\r\nvar Cors = require(\"cors\");\r\n\r\nvar app = Express();\r\nvar N1qlQuery = Couchbase.N1qlQuery;\r\n\r\napp.use(BodyParser.json());\r\napp.use(BodyParser.urlencoded({ extended: true }));\r\napp.use(Cors());\r\n\r\nvar cluster = new Couchbase.Cluster(\"couchbase:\/\/localhost\");\r\nvar bucket = cluster.openBucket(\"default\", \"\");\r\n\r\napp.get(\"\/consoles\", (request, response) =&gt; {});\r\napp.post(\"\/console\", (request, response) =&gt; {});\r\napp.post(\"\/game\", (request, response) =&gt; {});\r\napp.get(\"\/games\", (request, response) =&gt; {});\r\napp.get(\"\/game\/:id\", (request, response) =&gt; {});\r\n\r\nvar server = app.listen(3000, () =&gt; {\r\n    console.log(\"Listening on port \" + server.address().port + \"...\");\r\n});<\/pre>\n<p>Observe que importamos cada uma das depend\u00eancias baixadas, inicializamos e configuramos o Express e nos conectamos a um Bucket em nosso cluster do Couchbase.<\/p>\n<p>Teremos cinco endpoints de API RESTful diferentes para esse aplicativo.<\/p>\n<p>A primeira coisa l\u00f3gica a fazer seria criar um console de videogame para podermos adicionar jogos a ele. D\u00ea uma olhada no c\u00f3digo do endpoint a seguir:<\/p>\n<pre class=\"lang:default decode:true\">app.post(\"\/console\", (request, response) =&gt; {\r\n    if(!request.body.title) {\r\n        return response.status(401).send({ \"message\": \"A `title` is required.\" });\r\n    }\r\n    var id = UUID.v4();\r\n    request.body.type = \"console\";\r\n    bucket.insert(id, request.body, (error, result) =&gt; {\r\n        if(error) {\r\n            return response.status(500).send(error);\r\n        }\r\n        response.send(result);\r\n    });\r\n});<\/pre>\n<p>Na l\u00f3gica acima, estamos validando que a <code>t\u00edtulo<\/code> existe em nossa solicita\u00e7\u00e3o. Se existir, geraremos um novo ID, atribuiremos um <code>tipo<\/code> para os dados em nossa solicita\u00e7\u00e3o e os insere no Couchbase. A resposta de sucesso ou falha da inser\u00e7\u00e3o ser\u00e1 retornada ao cliente, que eventualmente ser\u00e1 um aplicativo Angular.<\/p>\n<p>Para consultar os consoles de videogame, precisaremos consultar com base no <code>tipo<\/code> propriedade. Por esse motivo, teremos que usar uma consulta N1QL em vez de uma pesquisa por id.<\/p>\n<pre class=\"lang:default decode:true\">app.get(\"\/consoles\", (request, response) =&gt; {\r\n    var statement = \"SELECT `\" + bucket._name + \"`.*, META().id FROM `\" + bucket._name + \"` WHERE type = 'console'\";\r\n    var query = N1qlQuery.fromString(statement);\r\n    query.consistency(N1qlQuery.Consistency.REQUEST_PLUS);\r\n    bucket.query(query, (error, result) =&gt; {\r\n        if(error) {\r\n            return response.status(500).send(error);\r\n        }\r\n        response.send(result);\r\n    });\r\n});<\/pre>\n<p>A consulta N1QL nada mais \u00e9 do que um simples <code>SELECIONAR<\/code> que voc\u00ea encontraria no SQL. Depois de executar a consulta, retornamos a resposta para o cliente.<\/p>\n<p>Isso nos leva aos videogames reais. As coisas ficam um pouco mais complexas, mas n\u00e3o mais dif\u00edceis.<\/p>\n<pre class=\"lang:default decode:true\">app.post(\"\/game\", (request, response) =&gt; {\r\n    if(!request.body.title) {\r\n        return response.status(401).send({ \"message\": \"A `title` is required.\" });\r\n    } else if(!request.body.cid) {\r\n        return response.status(401).send({ \"message\": \"A `cid` is required.\" });\r\n    }\r\n    var id = UUID.v4();\r\n    request.body.type = \"game\";\r\n    bucket.insert(id, request.body, (error, result) =&gt; {\r\n        if(error) {\r\n            return response.status(500).send(error);\r\n        }\r\n        response.send(result);\r\n    });\r\n});<\/pre>\n<p>Na l\u00f3gica do endpoint acima, planejamos inserir um novo videogame no banco de dados. Isso n\u00e3o \u00e9 diferente do que vimos ao inserir um novo console de videogame no banco de dados. Estamos definindo um <code>tipo<\/code> mas tamb\u00e9m estamos nos certificando de que uma propriedade <code>cid<\/code> existe. O <code>cid<\/code> ser\u00e1 um ID de console que nos permitir\u00e1 estabelecer uma rela\u00e7\u00e3o com nossos dados.<\/p>\n<p>Quando voc\u00ea tem relacionamentos, voc\u00ea tem <code>JUNTAR<\/code> opera\u00e7\u00f5es.<\/p>\n<pre class=\"lang:default decode:true\">app.get(\"\/games\", (request, response) =&gt; {\r\n    var statement = \"SELECT game.title AS game_title, console.title AS console_title FROM `\" + bucket._name + \"` AS game JOIN `\" + bucket._name + \"` AS console ON KEYS game.cid WHERE game.type = 'game'\";\r\n    var query = N1qlQuery.fromString(statement);\r\n    query.consistency(N1qlQuery.Consistency.REQUEST_PLUS);\r\n    bucket.query(query, (error, result) =&gt; {\r\n        if(error) {\r\n            return response.status(500).send(error);\r\n        }\r\n        response.send(result);\r\n    });\r\n});<\/pre>\n<p>No endpoint acima, estamos fazendo outra consulta N1QL, mas desta vez temos um <code>JUNTAR<\/code> opera\u00e7\u00e3o. N\u00e3o \u00e9 \u00fatil retornar um <code>cid<\/code> ao consultar jogos de v\u00eddeo, portanto <code>JUNTAR<\/code> e substitua essas informa\u00e7\u00f5es pelo t\u00edtulo do console do outro documento.<\/p>\n<p>Da mesma forma, temos uma consulta semelhante quando tentamos encontrar um videogame espec\u00edfico:<\/p>\n<pre class=\"lang:default decode:true\">app.get(\"\/game\/:id\", (request, response) =&gt; {\r\n    if(!request.params.id) {\r\n        return response.status(401).send({ \"message\": \"An `id` is required.\" });\r\n    }\r\n    var statement = \"SELECT game.title AS game_title, console.title AS console_title FROM `\" + bucket._name + \"` AS game JOIN `\" + bucket._name + \"` AS console ON KEYS game.cid WHERE game.type = 'game' AND META(game).id = $id\";\r\n    var query = N1qlQuery.fromString(statement);\r\n    bucket.query(query, { \"id\": request.params.id }, (error, result) =&gt; {\r\n        if(error) {\r\n            return response.status(500).send(error);\r\n        }\r\n        response.send(result);\r\n    });\r\n});<\/pre>\n<p>A alternativa ao uso do N1QL e do <code>JUNTAR<\/code> seria fazer duas pesquisas com base no ID. N\u00e3o h\u00e1 nada de errado com essa pr\u00e1tica, mas, na minha opini\u00e3o, \u00e9 mais f\u00e1cil deixar que o banco de dados cuide de um <code>JUNTAR<\/code> em vez de tentar <code>JUNTAR<\/code> por meio da camada de aplicativos.<\/p>\n<p>Isso nos leva ao front-end do cliente.<\/p>\n<h2>Cria\u00e7\u00e3o da estrutura Ionic com front-end angular<\/h2>\n<p>Como mencionado anteriormente, desta vez estamos usando o Ionic Framework, que usa uma variante do Angular. Escolhi esse framework porque estava com pregui\u00e7a de criar um frontend atraente com o Bootstrap ou o Foundation.<\/p>\n<p>Com a CLI do Ionic Framework dispon\u00edvel, execute o seguinte:<\/p>\n<pre class=\"lang:default decode:true\">ionic start pwa sidemenu<\/pre>\n<p>O comando acima criar\u00e1 um projeto chamado <strong>pwa<\/strong> usando a estrutura Ionic <code>sidemenu<\/code> modelo.<\/p>\n<p>O modelo b\u00e1sico \u00e9 \u00fatil, mas n\u00e3o tem tudo o que precisamos. Precisamos adicionar algumas p\u00e1ginas ao aplicativo.<\/p>\n<p>Usando os geradores do Ionic Framework, ou manualmente, crie um <strong>consoles<\/strong>, <strong>jogos<\/strong>e <strong>jogo<\/strong> p\u00e1gina. Cada uma dessas p\u00e1ginas deve ter um arquivo HTML, SCSS e TypeScript e cada diret\u00f3rio de p\u00e1gina deve estar no diret\u00f3rio <strong>p\u00e1ginas<\/strong> diret\u00f3rio.<\/p>\n<p>Abra o arquivo\u00a0<strong>app\/app.component.ts<\/strong> e fa\u00e7a com que ele se pare\u00e7a com o seguinte:<\/p>\n<pre class=\"lang:default decode:true\">import { Component, ViewChild } from '@angular\/core';\r\nimport { Nav, Platform } from 'ionic-angular';\r\nimport { StatusBar } from '@ionic-native\/status-bar';\r\nimport { SplashScreen } from '@ionic-native\/splash-screen';\r\n\r\nimport { GamesPage } from '..\/pages\/games\/games';\r\nimport { ConsolesPage } from '..\/pages\/consoles\/consoles';\r\n\r\n@Component({\r\n  templateUrl: 'app.html'\r\n})\r\nexport class MyApp {\r\n  @ViewChild(Nav) nav: Nav;\r\n\r\n  rootPage: any = GamesPage;\r\n\r\n  pages: Array&lt;{title: string, component: any}&gt;;\r\n\r\n  constructor(public platform: Platform, public statusBar: StatusBar, public splashScreen: SplashScreen) {\r\n    this.initializeApp();\r\n\r\n    \/\/ used for an example of ngFor and navigation\r\n    this.pages = [\r\n      { title: 'Games', component: GamesPage },\r\n      { title: 'Consoles', component: ConsolesPage }\r\n    ];\r\n\r\n  }\r\n\r\n  initializeApp() {\r\n    this.platform.ready().then(() =&gt; {\r\n      \/\/ Okay, so the platform is ready and our plugins are available.\r\n      \/\/ Here you can do any higher level native things you might need.\r\n      this.statusBar.styleDefault();\r\n      this.splashScreen.hide();\r\n    });\r\n  }\r\n\r\n  openPage(page) {\r\n    \/\/ Reset the content nav to have just this page\r\n    \/\/ we wouldn't want the back button to show in this scenario\r\n    this.nav.setRoot(page.component);\r\n  }\r\n}<\/pre>\n<p>Observe que importamos\u00a0<code>P\u00e1gina de jogos<\/code> e <code>ConsolesP\u00e1gina<\/code>, atualizou o <code>p\u00e1ginas<\/code> e definir a p\u00e1gina raiz padr\u00e3o como <code>P\u00e1gina de jogos<\/code>. Ao fazer isso, configuramos a navega\u00e7\u00e3o e a p\u00e1gina padr\u00e3o quando o aplicativo \u00e9 iniciado.<\/p>\n<p>Para concluir a configura\u00e7\u00e3o, tamb\u00e9m precisamos alterar o arquivo\u00a0<strong>app\/app.module.ts<\/strong> arquivo. Fa\u00e7a com que ele se pare\u00e7a com o seguinte:<\/p>\n<pre class=\"lang:default decode:true\">import { BrowserModule } from '@angular\/platform-browser';\r\nimport { ErrorHandler, NgModule } from '@angular\/core';\r\nimport { IonicApp, IonicErrorHandler, IonicModule } from 'ionic-angular';\r\nimport { HttpModule } from \"@angular\/http\";\r\n\r\nimport { MyApp } from '.\/app.component';\r\nimport { GamesPage } from '..\/pages\/games\/games';\r\nimport { GamePage } from '..\/pages\/game\/game';\r\nimport { ConsolesPage } from '..\/pages\/consoles\/consoles';\r\n\r\nimport { StatusBar } from '@ionic-native\/status-bar';\r\nimport { SplashScreen } from '@ionic-native\/splash-screen';\r\n\r\n@NgModule({\r\n  declarations: [\r\n    MyApp,\r\n    GamesPage,\r\n    GamePage,\r\n    ConsolesPage\r\n  ],\r\n  imports: [\r\n    BrowserModule,\r\n    HttpModule,\r\n    IonicModule.forRoot(MyApp),\r\n  ],\r\n  bootstrap: [IonicApp],\r\n  entryComponents: [\r\n    MyApp,\r\n    GamesPage,\r\n    GamePage,\r\n    ConsolesPage\r\n  ],\r\n  providers: [\r\n    StatusBar,\r\n    SplashScreen,\r\n    {provide: ErrorHandler, useClass: IonicErrorHandler}\r\n  ]\r\n})\r\nexport class AppModule {}<\/pre>\n<p>Observe que importamos cada uma de nossas novas p\u00e1ginas e as adicionamos \u00e0 pasta <code>declara\u00e7\u00f5es<\/code> e <code>entryComponents<\/code> matrizes do <code>@NgModule<\/code> bloco.<\/p>\n<p>Agora podemos nos concentrar no desenvolvimento do aplicativo e conect\u00e1-lo \u00e0 nossa API.<\/p>\n<p>Abra o arquivo\u00a0<strong>src\/pages\/games\/games.ts<\/strong> e fazer com que ele se pare\u00e7a com o seguinte. Vamos detalhar o que est\u00e1 acontecendo a seguir.<\/p>\n<pre class=\"lang:default decode:true\">import { Component } from '@angular\/core';\r\nimport { NavController, ModalController } from 'ionic-angular';\r\nimport { Http, Headers, RequestOptions } from \"@angular\/http\";\r\nimport \"rxjs\/Rx\";\r\nimport { GamePage } from \"..\/game\/game\";\r\n\r\n@Component({\r\n    selector: 'page-games',\r\n    templateUrl: 'games.html'\r\n})\r\nexport class GamesPage {\r\n\r\n    public games: Array&lt;any&gt;;\r\n\r\n    public constructor(public navCtrl: NavController, private http: Http, private modalCtrl: ModalController) {\r\n        this.games = [];\r\n    }\r\n\r\n    public ionViewDidEnter() {\r\n        this.http.get(\"https:\/\/localhost:3000\/games\")\r\n            .map(result =&gt; result.json())\r\n            .subscribe(result =&gt; {\r\n                this.games = result;\r\n            });\r\n    }\r\n\r\n    public create() {\r\n        let gameModal = this.modalCtrl.create(GamePage);\r\n        gameModal.onDidDismiss(data =&gt; {\r\n            let headers = new Headers({ \"Content-Type\": \"application\/json\" });\r\n            let options = new RequestOptions({ headers: headers });\r\n            this.http.post(\"https:\/\/localhost:3000\/game\", JSON.stringify(data), options)\r\n                .subscribe(result =&gt; {\r\n                    this.games.push({ \"game_title\": data.title, \"console_title\": \"\"});\r\n                });\r\n        });\r\n        gameModal.present();\r\n    }\r\n\r\n}<\/pre>\n<p>Dentro do <code>P\u00e1gina de jogos<\/code> temos uma vari\u00e1vel p\u00fablica chamada <code>jogos<\/code>. Por ser p\u00fablico, ele ser\u00e1 acess\u00edvel via HTML. Ele conter\u00e1 todos os jogos retornados do aplicativo Node.js.<\/p>\n<p>Quando a p\u00e1gina \u00e9 carregada, queremos consultar nosso endpoint. Nunca \u00e9 uma boa ideia fazer isso na se\u00e7\u00e3o <code>construtor<\/code> portanto, em vez disso, usamos o m\u00e9todo <code>ionViewDidEnter<\/code> m\u00e9todo. Depois de emitir a solicita\u00e7\u00e3o, o resultado \u00e9 transformado em JSON e, em seguida, carregado em nossa vari\u00e1vel p\u00fablica.<\/p>\n<p>Se quisermos criar um novo jogo em nosso banco de dados, as coisas ser\u00e3o um pouco diferentes. Vamos exibir uma caixa de di\u00e1logo modal e coletar informa\u00e7\u00f5es.<\/p>\n<pre class=\"lang:default decode:true\">public create() {\r\n    let gameModal = this.modalCtrl.create(GamePage);\r\n    gameModal.onDidDismiss(data =&gt; {\r\n        let headers = new Headers({ \"Content-Type\": \"application\/json\" });\r\n        let options = new RequestOptions({ headers: headers });\r\n        this.http.post(\"https:\/\/localhost:3000\/game\", JSON.stringify(data), options)\r\n            .subscribe(result =&gt; {\r\n                this.games.push({ \"game_title\": data.title, \"console_title\": \"\"});\r\n            });\r\n    });\r\n    gameModal.present();\r\n}<\/pre>\n<p>O <code>criar<\/code> exibir\u00e1 nosso m\u00e9todo <code>P\u00e1gina do jogo<\/code> que estar\u00e1 no formato modal. Todos os dados inseridos no formul\u00e1rio no modal ser\u00e3o retornados ao <code>P\u00e1gina de jogos<\/code> e enviado por meio de uma solicita\u00e7\u00e3o HTTP para a API.<\/p>\n<p>Antes de darmos uma olhada em\u00a0<code>P\u00e1gina do jogo<\/code>Vamos dar uma olhada no HTML que alimenta o <code>P\u00e1gina de jogos<\/code>.<\/p>\n<pre class=\"lang:default decode:true\">&lt;ion-header&gt;\r\n    &lt;ion-navbar&gt;\r\n        &lt;button ion-button menuToggle&gt;\r\n            &lt;ion-icon name=\"menu\"&gt;&lt;\/ion-icon&gt;\r\n        &lt;\/button&gt;\r\n        &lt;ion-title&gt;Games&lt;\/ion-title&gt;\r\n        &lt;ion-buttons end&gt;\r\n            &lt;button ion-button icon-only (click)=\"create()\"&gt;\r\n                &lt;ion-icon name=\"add\"&gt;&lt;\/ion-icon&gt;\r\n            &lt;\/button&gt;\r\n        &lt;\/ion-buttons&gt;\r\n    &lt;\/ion-navbar&gt;\r\n&lt;\/ion-header&gt;\r\n\r\n&lt;ion-content padding&gt;\r\n    &lt;ion-list&gt;\r\n        &lt;button ion-item *ngFor=\"let game of games\"&gt;\r\n            {{game.game_title}}\r\n<span class=\"item-note\">{{game.console_title}}<\/span>\r\n&lt;\/button&gt; &lt;\/ion-list&gt; &lt;\/ion-content&gt;<\/pre>\n<p>No HTML acima, estamos percorrendo nosso arquivo p\u00fablico <code>jogos<\/code> matriz. Cada objeto da matriz \u00e9 renderizado na tela dentro de uma lista. O Angular faz todo o trabalho pesado para n\u00f3s.<\/p>\n<p>Abra o arquivo\u00a0<strong>src\/pages\/game\/game.ts<\/strong> e inclua o seguinte:<\/p>\n<pre class=\"lang:default decode:true\">import { Component } from '@angular\/core';\r\nimport { IonicPage, NavController, NavParams, ViewController } from 'ionic-angular';\r\nimport { Http, Headers, RequestOptions } from \"@angular\/http\";\r\nimport \"rxjs\/Rx\";\r\n\r\n@IonicPage()\r\n@Component({\r\n    selector: 'page-game',\r\n    templateUrl: 'game.html',\r\n})\r\nexport class GamePage {\r\n\r\n    public consoles: Array&lt;any&gt;;\r\n    public input: any;\r\n\r\n    constructor(public navCtrl: NavController, public navParams: NavParams, public viewCtrl: ViewController, private http: Http) {\r\n        this.consoles = [];\r\n        this.input = {\r\n            \"cid\": \"\",\r\n            \"title\": \"\"\r\n        }\r\n    }\r\n\r\n    ionViewDidEnter() {\r\n        this.http.get(\"https:\/\/localhost:3000\/consoles\")\r\n            .map(result =&gt; result.json())\r\n            .subscribe(result =&gt; {\r\n                for(let i = 0; i &lt; result.length; i++) {\r\n                    this.consoles.push(result[i]);\r\n                }\r\n            });\r\n    }\r\n\r\n    public save() {\r\n        this.viewCtrl.dismiss(this.input);\r\n    }\r\n\r\n}<\/pre>\n<p>Essa l\u00f3gica modal \u00e9 semelhante ao que j\u00e1 vimos. Haver\u00e1 um formul\u00e1rio vinculado a HTML e TypeScript. Quando o <code>ionViewDidEnter<\/code> acionadores, consultamos as informa\u00e7\u00f5es do console. Essas informa\u00e7\u00f5es do console ser\u00e3o eventualmente usadas para uma lista de op\u00e7\u00f5es que o usu\u00e1rio pode selecionar.<\/p>\n<p>Quando o usu\u00e1rio seleciona o <code>salvar<\/code> os dados vinculados no formul\u00e1rio p\u00fablico s\u00e3o passados para o m\u00e9todo <code>P\u00e1gina de jogos<\/code> p\u00e1gina.<\/p>\n<p>O HTML que alimenta esse modal, encontrado em\u00a0<strong>src\/pages\/game\/game.html<\/strong> se parece com isso:<\/p>\n<pre class=\"lang:default decode:true\">&lt;ion-header&gt;\r\n    &lt;ion-navbar&gt;\r\n    &lt;ion-title&gt;New Game&lt;\/ion-title&gt;\r\n    &lt;\/ion-navbar&gt;\r\n&lt;\/ion-header&gt;\r\n\r\n&lt;ion-content padding&gt;\r\n    &lt;ion-list&gt;\r\n        &lt;ion-item&gt;\r\n            &lt;ion-label stacked&gt;Title&lt;\/ion-label&gt;\r\n            &lt;ion-input type=\"text\" [(ngModel)]=\"input.title\"&gt;&lt;\/ion-input&gt;\r\n        &lt;\/ion-item&gt;\r\n        &lt;ion-item&gt;\r\n            &lt;ion-label&gt;Console&lt;\/ion-label&gt;\r\n            &lt;ion-select [(ngModel)]=\"input.cid\"&gt;\r\n                &lt;ion-option *ngFor=\"let console of consoles\" value=\"{{ console.id }}\"&gt;{{ console.title }}&lt;\/ion-option&gt;\r\n            &lt;\/ion-select&gt;\r\n        &lt;\/ion-item&gt;\r\n        &lt;ion-item&gt;\r\n            &lt;button ion-button full (click)=\"save()\"&gt;Save&lt;\/button&gt;\r\n        &lt;\/ion-item&gt;\r\n    &lt;\/ion-list&gt;\r\n&lt;\/ion-content&gt;<\/pre>\n<p>Temos uma lista simples que comp\u00f5e nosso formul\u00e1rio. Os elementos do formul\u00e1rio s\u00e3o vinculados \u00e0 nossa vari\u00e1vel TypeScript e as informa\u00e7\u00f5es do console s\u00e3o percorridas para preencher um arquivo HTML <code>selecionar<\/code> elemento.<\/p>\n<p>Isso nos leva \u00e0 p\u00e1gina final do front-end do Angular.<\/p>\n<p>Abra o arquivo\u00a0<strong>src\/pages\/consoles\/consoles.ts<\/strong> e inclua o seguinte:<\/p>\n<pre class=\"lang:default decode:true\">import { Component } from '@angular\/core';\r\nimport { NavController, NavParams, AlertController } from 'ionic-angular';\r\nimport { Http, Headers, RequestOptions } from \"@angular\/http\";\r\nimport \"rxjs\/Rx\";\r\n\r\n@Component({\r\n  selector: 'page-consoles',\r\n  templateUrl: 'consoles.html'\r\n})\r\nexport class ConsolesPage {\r\n\r\n    public consoles: Array&lt;any&gt;;\r\n\r\n    public constructor(public navCtrl: NavController, private http: Http, private alertCtrl: AlertController) {\r\n        this.consoles = [];\r\n    }\r\n\r\n    public ionViewDidEnter() {\r\n        this.http.get(\"https:\/\/localhost:3000\/consoles\")\r\n            .map(result =&gt; result.json())\r\n            .subscribe(result =&gt; {\r\n                this.consoles = result;\r\n            });\r\n    }\r\n\r\n    public create() {\r\n        let alert = this.alertCtrl.create({\r\n            title: 'Add Console',\r\n            inputs: [\r\n                {\r\n                    name: 'title',\r\n                    placeholder: 'Title'\r\n                },\r\n                {\r\n                    name: 'year',\r\n                    placeholder: 'Year'\r\n                }\r\n            ],\r\n            buttons: [\r\n                {\r\n                    text: 'Cancel',\r\n                    role: 'cancel',\r\n                    handler: data =&gt; {\r\n                        console.log('Cancel clicked');\r\n                    }\r\n                },\r\n                {\r\n                    text: 'Save',\r\n                    handler: data =&gt; {\r\n                        let headers = new Headers({ \"Content-Type\": \"application\/json\" });\r\n                        let options = new RequestOptions({ headers: headers });\r\n                        this.http.post(\"https:\/\/localhost:3000\/console\", JSON.stringify(data), options)\r\n                            .subscribe(result =&gt; {\r\n                                this.consoles.push(data);\r\n                            }, error =&gt; {});\r\n                    }\r\n                }\r\n            ]\r\n        });\r\n        alert.present();\r\n    }\r\n\r\n}<\/pre>\n<p>Embora n\u00e3o seja muito diferente do que j\u00e1 vimos, temos um novo recurso. Estamos usando uma caixa de di\u00e1logo pop-up para coletar informa\u00e7\u00f5es sobre o novo console de videogame.<\/p>\n<p>Quando o pop-up \u00e9 descartado, o seguinte \u00e9 executado:<\/p>\n<pre class=\"lang:default decode:true\">handler: data =&gt; {\r\n    let headers = new Headers({ \"Content-Type\": \"application\/json\" });\r\n    let options = new RequestOptions({ headers: headers });\r\n    this.http.post(\"https:\/\/localhost:3000\/console\", JSON.stringify(data), options)\r\n        .subscribe(result =&gt; {\r\n            this.consoles.push(data);\r\n        }, error =&gt; {});\r\n}<\/pre>\n<p>Isso pegar\u00e1 as informa\u00e7\u00f5es encontradas no formul\u00e1rio e as enviar\u00e1 via HTTP para a nossa API, que, por sua vez, salvar\u00e1 as informa\u00e7\u00f5es do console no banco de dados.<\/p>\n<p>Incr\u00edvel, n\u00e3o \u00e9?<\/p>\n<p>O HTML encontrado na pasta\u00a0<strong>src\/pages\/consoles\/consoles.html<\/strong> \u00e9 parecido com o seguinte:<\/p>\n<pre class=\"lang:default decode:true\">&lt;ion-header&gt;\r\n    &lt;ion-navbar&gt;\r\n        &lt;button ion-button menutoggle&gt;\r\n            &lt;ion-icon name=&quot;menu&quot;&gt;&lt;\/ion-icon&gt;\r\n        &lt;\/button&gt;\r\n        &lt;ion-title&gt;Consoles&lt;\/ion-title&gt;\r\n        &lt;ion-buttons end&gt;\r\n            &lt;button ion-button icon-only (click)=&quot;create()&quot;&gt;\r\n                &lt;ion-icon name=&quot;add&quot;&gt;&lt;\/ion-icon&gt;\r\n            &lt;\/button&gt;\r\n        &lt;\/ion-buttons&gt;\r\n    &lt;\/ion-navbar&gt;\r\n&lt;\/ion-header&gt;\r\n\r\n&lt;ion-content&gt;\r\n    &lt;ion-list&gt;\r\n        &lt;button ion-item *ngfor=&quot;let console of consoles&quot;&gt;\r\n            {{ console.title }}\r\n            &lt;span class=&quot;item-note&quot; item-right&gt;\r\n                {{ console.year }}\r\n            &lt;\/span&gt;\r\n        &lt;\/button&gt;\r\n    &lt;\/ion-list&gt;\r\n&lt;\/ion-content&gt;<\/pre>\n<p>Novamente, ele \u00e9 quase id\u00eantico aos outros arquivos HTML que vimos.<\/p>\n<h2>Conclus\u00e3o<\/h2>\n<p>Voc\u00ea acabou de receber uma recapitula\u00e7\u00e3o de tudo o que foi abordado no Midwest JS 2017. Vimos como criar uma API do Node.js que se comunica com o Couchbase, nosso banco de dados NoSQL, al\u00e9m de criar um frontend usando o Angular e o Ionic Framework. Esses s\u00e3o apenas alguns componentes de um aplicativo de pilha completa.<\/p>\n<p>Para obter mais informa\u00e7\u00f5es sobre <a href=\"https:\/\/www.couchbase.com\/blog\/pt\/build-a-rest-api-with-node-js-express-and-couchbase\/\">usando Node.js<\/a> com o Couchbase, confira o <a href=\"https:\/\/www.couchbase.com\/blog\/pt\/developers\/\" target=\"_blank\" rel=\"noopener\">Portal do desenvolvedor do Couchbase<\/a>. Se voc\u00ea quiser que eu volte ao Midwest JS, avise-me nos coment\u00e1rios.<\/p>","protected":false},"excerpt":{"rendered":"<p>Back in August I had participated in Midwest JS located in\u00a0Minneapolis,\u00a0Minnesota. As you may know, I&#8217;m a huge fan of developing full stack applications with the JavaScript stack. This is exactly what I had presented on at the conference. My [&hellip;]<\/p>","protected":false},"author":63,"featured_media":13873,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[1814,1815,1816,9327,1822,1812],"tags":[1704,1588,1534,1543],"ppma_author":[9032],"class_list":["post-3943","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-application-design","category-best-practices-and-tutorials","category-couchbase-server","category-javascript","category-node-js","category-n1ql-query","tag-angular","tag-full-stack","tag-ionic-framework","tag-javascript"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v26.5 (Yoast SEO v26.5) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Midwest JS Project Source on Full Stack Node Development, Available<\/title>\n<meta name=\"description\" content=\"The full stack Node.js, Angular, and Couchbase NoSQL project source from Midwest JS is now available, with full write-up guide to success.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.couchbase.com\/blog\/pt\/midwest-js-project-source-full-stack-node-development-available\/\" \/>\n<meta property=\"og:locale\" content=\"pt_BR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Midwest JS Project Source on Full Stack Node Development, Available\" \/>\n<meta property=\"og:description\" content=\"The full stack Node.js, Angular, and Couchbase NoSQL project source from Midwest JS is now available, with full write-up guide to success.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.couchbase.com\/blog\/pt\/midwest-js-project-source-full-stack-node-development-available\/\" \/>\n<meta property=\"og:site_name\" content=\"The Couchbase Blog\" \/>\n<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/thepolyglotdeveloper\" \/>\n<meta property=\"article:published_time\" content=\"2017-09-01T14:00:21+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-06-14T03:15:10+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/08\/midwestjs-couchbase.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"768\" \/>\n\t<meta property=\"og:image:height\" content=\"558\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Nic Raboy, Developer Advocate, Couchbase\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@nraboy\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Nic Raboy, Developer Advocate, Couchbase\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"7 minutos\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/midwest-js-project-source-full-stack-node-development-available\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/midwest-js-project-source-full-stack-node-development-available\/\"},\"author\":{\"name\":\"Nic Raboy, Developer Advocate, Couchbase\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/bb545ebe83bb2d12f91095811d0a72e1\"},\"headline\":\"Midwest JS Project Source on Full Stack Node Development, Available\",\"datePublished\":\"2017-09-01T14:00:21+00:00\",\"dateModified\":\"2025-06-14T03:15:10+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/midwest-js-project-source-full-stack-node-development-available\/\"},\"wordCount\":1489,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/midwest-js-project-source-full-stack-node-development-available\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"keywords\":[\"Angular\",\"full stack\",\"ionic framework\",\"javascript\"],\"articleSection\":[\"Application Design\",\"Best Practices and Tutorials\",\"Couchbase Server\",\"JavaScript\",\"Node.js\",\"SQL++ \/ N1QL Query\"],\"inLanguage\":\"pt-BR\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/midwest-js-project-source-full-stack-node-development-available\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/midwest-js-project-source-full-stack-node-development-available\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/midwest-js-project-source-full-stack-node-development-available\/\",\"name\":\"Midwest JS Project Source on Full Stack Node Development, Available\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/midwest-js-project-source-full-stack-node-development-available\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/midwest-js-project-source-full-stack-node-development-available\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"datePublished\":\"2017-09-01T14:00:21+00:00\",\"dateModified\":\"2025-06-14T03:15:10+00:00\",\"description\":\"The full stack Node.js, Angular, and Couchbase NoSQL project source from Midwest JS is now available, with full write-up guide to success.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/midwest-js-project-source-full-stack-node-development-available\/#breadcrumb\"},\"inLanguage\":\"pt-BR\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/midwest-js-project-source-full-stack-node-development-available\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"pt-BR\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/midwest-js-project-source-full-stack-node-development-available\/#primaryimage\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"width\":1800,\"height\":630},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/midwest-js-project-source-full-stack-node-development-available\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.couchbase.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Midwest JS Project Source on Full Stack Node Development, Available\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\",\"url\":\"https:\/\/www.couchbase.com\/blog\/\",\"name\":\"The Couchbase Blog\",\"description\":\"Couchbase, the NoSQL Database\",\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.couchbase.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"pt-BR\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\",\"name\":\"The Couchbase Blog\",\"url\":\"https:\/\/www.couchbase.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"pt-BR\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png\",\"width\":218,\"height\":34,\"caption\":\"The Couchbase Blog\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/bb545ebe83bb2d12f91095811d0a72e1\",\"name\":\"Nic Raboy, Developer Advocate, Couchbase\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"pt-BR\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/8863514d8bed0cf6080f23db40e00354\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/bedeb68368d4681aca4c74fe5f697f0c423b80d498ec50fd915ba018b72c101f?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/bedeb68368d4681aca4c74fe5f697f0c423b80d498ec50fd915ba018b72c101f?s=96&d=mm&r=g\",\"caption\":\"Nic Raboy, Developer Advocate, Couchbase\"},\"description\":\"Nic Raboy is an advocate of modern web and mobile development technologies. He has experience in Java, JavaScript, Golang and a variety of frameworks such as Angular, NativeScript, and Apache Cordova. Nic writes about his development experiences related to making web and mobile development easier to understand.\",\"sameAs\":[\"https:\/\/www.thepolyglotdeveloper.com\",\"https:\/\/www.facebook.com\/thepolyglotdeveloper\",\"https:\/\/x.com\/nraboy\"],\"url\":\"https:\/\/www.couchbase.com\/blog\/pt\/author\/nic-raboy-2\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Fonte do Projeto JS do Centro-Oeste em Desenvolvimento de Node Full Stack, dispon\u00edvel","description":"A fonte do projeto Node.js, Angular e Couchbase NoSQL de pilha completa da Midwest JS j\u00e1 est\u00e1 dispon\u00edvel, com um guia completo para o sucesso.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.couchbase.com\/blog\/pt\/midwest-js-project-source-full-stack-node-development-available\/","og_locale":"pt_BR","og_type":"article","og_title":"Midwest JS Project Source on Full Stack Node Development, Available","og_description":"The full stack Node.js, Angular, and Couchbase NoSQL project source from Midwest JS is now available, with full write-up guide to success.","og_url":"https:\/\/www.couchbase.com\/blog\/pt\/midwest-js-project-source-full-stack-node-development-available\/","og_site_name":"The Couchbase Blog","article_author":"https:\/\/www.facebook.com\/thepolyglotdeveloper","article_published_time":"2017-09-01T14:00:21+00:00","article_modified_time":"2025-06-14T03:15:10+00:00","og_image":[{"width":768,"height":558,"url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/08\/midwestjs-couchbase.jpg","type":"image\/jpeg"}],"author":"Nic Raboy, Developer Advocate, Couchbase","twitter_card":"summary_large_image","twitter_creator":"@nraboy","twitter_misc":{"Written by":"Nic Raboy, Developer Advocate, Couchbase","Est. reading time":"7 minutos"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.couchbase.com\/blog\/midwest-js-project-source-full-stack-node-development-available\/#article","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/midwest-js-project-source-full-stack-node-development-available\/"},"author":{"name":"Nic Raboy, Developer Advocate, Couchbase","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/bb545ebe83bb2d12f91095811d0a72e1"},"headline":"Midwest JS Project Source on Full Stack Node Development, Available","datePublished":"2017-09-01T14:00:21+00:00","dateModified":"2025-06-14T03:15:10+00:00","mainEntityOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/midwest-js-project-source-full-stack-node-development-available\/"},"wordCount":1489,"commentCount":0,"publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/midwest-js-project-source-full-stack-node-development-available\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","keywords":["Angular","full stack","ionic framework","javascript"],"articleSection":["Application Design","Best Practices and Tutorials","Couchbase Server","JavaScript","Node.js","SQL++ \/ N1QL Query"],"inLanguage":"pt-BR","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.couchbase.com\/blog\/midwest-js-project-source-full-stack-node-development-available\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.couchbase.com\/blog\/midwest-js-project-source-full-stack-node-development-available\/","url":"https:\/\/www.couchbase.com\/blog\/midwest-js-project-source-full-stack-node-development-available\/","name":"Fonte do Projeto JS do Centro-Oeste em Desenvolvimento de Node Full Stack, dispon\u00edvel","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/midwest-js-project-source-full-stack-node-development-available\/#primaryimage"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/midwest-js-project-source-full-stack-node-development-available\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","datePublished":"2017-09-01T14:00:21+00:00","dateModified":"2025-06-14T03:15:10+00:00","description":"A fonte do projeto Node.js, Angular e Couchbase NoSQL de pilha completa da Midwest JS j\u00e1 est\u00e1 dispon\u00edvel, com um guia completo para o sucesso.","breadcrumb":{"@id":"https:\/\/www.couchbase.com\/blog\/midwest-js-project-source-full-stack-node-development-available\/#breadcrumb"},"inLanguage":"pt-BR","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.couchbase.com\/blog\/midwest-js-project-source-full-stack-node-development-available\/"]}]},{"@type":"ImageObject","inLanguage":"pt-BR","@id":"https:\/\/www.couchbase.com\/blog\/midwest-js-project-source-full-stack-node-development-available\/#primaryimage","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","width":1800,"height":630},{"@type":"BreadcrumbList","@id":"https:\/\/www.couchbase.com\/blog\/midwest-js-project-source-full-stack-node-development-available\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.couchbase.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Midwest JS Project Source on Full Stack Node Development, Available"}]},{"@type":"WebSite","@id":"https:\/\/www.couchbase.com\/blog\/#website","url":"https:\/\/www.couchbase.com\/blog\/","name":"Blog do Couchbase","description":"Couchbase, o banco de dados NoSQL","publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.couchbase.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"pt-BR"},{"@type":"Organization","@id":"https:\/\/www.couchbase.com\/blog\/#organization","name":"Blog do Couchbase","url":"https:\/\/www.couchbase.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"pt-BR","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","width":218,"height":34,"caption":"The Couchbase Blog"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/bb545ebe83bb2d12f91095811d0a72e1","name":"Nic Raboy, defensor dos desenvolvedores, Couchbase","image":{"@type":"ImageObject","inLanguage":"pt-BR","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/8863514d8bed0cf6080f23db40e00354","url":"https:\/\/secure.gravatar.com\/avatar\/bedeb68368d4681aca4c74fe5f697f0c423b80d498ec50fd915ba018b72c101f?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/bedeb68368d4681aca4c74fe5f697f0c423b80d498ec50fd915ba018b72c101f?s=96&d=mm&r=g","caption":"Nic Raboy, Developer Advocate, Couchbase"},"description":"Nic Raboy \u00e9 um defensor das modernas tecnologias de desenvolvimento m\u00f3vel e da Web. Ele tem experi\u00eancia em Java, JavaScript, Golang e uma variedade de estruturas, como Angular, NativeScript e Apache Cordova. Nic escreve sobre suas experi\u00eancias de desenvolvimento relacionadas a tornar o desenvolvimento m\u00f3vel e da Web mais f\u00e1cil de entender.","sameAs":["https:\/\/www.thepolyglotdeveloper.com","https:\/\/www.facebook.com\/thepolyglotdeveloper","https:\/\/x.com\/nraboy"],"url":"https:\/\/www.couchbase.com\/blog\/pt\/author\/nic-raboy-2\/"}]}},"authors":[{"term_id":9032,"user_id":63,"is_guest":0,"slug":"nic-raboy-2","display_name":"Nic Raboy, Developer Advocate, Couchbase","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/bedeb68368d4681aca4c74fe5f697f0c423b80d498ec50fd915ba018b72c101f?s=96&d=mm&r=g","author_category":"","last_name":"Raboy","first_name":"Nic","job_title":"","user_url":"https:\/\/www.thepolyglotdeveloper.com","description":"Nic Raboy \u00e9 um defensor das modernas tecnologias de desenvolvimento m\u00f3vel e da Web. Ele tem experi\u00eancia em Java, JavaScript, Golang e uma variedade de estruturas, como Angular, NativeScript e Apache Cordova. Nic escreve sobre suas experi\u00eancias de desenvolvimento relacionadas a tornar o desenvolvimento m\u00f3vel e da Web mais f\u00e1cil de entender."}],"_links":{"self":[{"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/posts\/3943","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/users\/63"}],"replies":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/comments?post=3943"}],"version-history":[{"count":0,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/posts\/3943\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/media\/13873"}],"wp:attachment":[{"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/media?parent=3943"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/categories?post=3943"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/tags?post=3943"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/ppma_author?post=3943"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}