Giter Site home page Giter Site logo

mesaugat / express-api-es6-starter Goto Github PK

View Code? Open in Web Editor NEW
291.0 11.0 92.0 3.63 MB

Build APIs with Express.js in no time using ES6/ES7/ESNext goodness.

Home Page: https://express-api-es6-starter.herokuapp.com/api-docs/

License: MIT License

JavaScript 95.65% Dockerfile 4.35%
expressjs nodejs es2015 es2017 rest web babel api

express-api-es6-starter's Introduction

Express API ES6 Starter

Starter application for building APIs with Express.js

Build Status Codecov

Comes with:


Prerequisites

Setup

Clone the repository, install the dependencies and get started right away.

$ git clone --depth=1 [email protected]:mesaugat/express-api-es6-starter.git <application-name>
$ cd <application-name>
$ rm -rf .git
$ yarn   # or npm install

Make a copy of .env.example as .env and update your application details and database credentials. Now, run the migrations and seed the database.

$ yarn migrate
$ yarn seed

Finally, start the application.

$ yarn start:dev (For development)
$ NODE_ENV=production yarn start (For production)

Navigate to http://localhost:8848/api-docs/ to verify installation.

Creating new Migrations and Seeds

These are the commands to create a new migration and corresponding seed file.

$ yarn make:migration <name>
$ yarn make:seeder <name>

Example,

$ yarn make:migration create_tags_table
$ yarn make:seeder 02_insert_tags

Using Docker

Using docker-compose

Use docker-compose to quickly bring up a stack with pre-configured Postgres database container. Data is ephemeral and containers will disappear when stack is removed.

Specific configuration for Docker is in .env.docker

  • 0.0.0.0 as $APP_HOST to expose app on Docker network interface
  • Pre-configured Postgres settings - can be updated to point to another Postgres host

Bring up stack,

$ docker-compose up

Navigate to http://localhost:8848/api-docs/ to verify application is running from docker.

Bring down stack,

$ docker-compose down

Multi-stage docker builds

There are multiple build targets available for different stages. These images can be used to deploy or run jobs in different container based cloud infrastructure like Kubernetes, AWS ECS, Fargate, GCP Cloud Run etc.

  1. Building a production image.

    $ docker build --target=prod -t express-api-es6-starter:prod .
  2. Building an image for development.

    $ docker build --target=dev -t express-api-es6-starter:dev .
  3. Building an image that runs migration and/or rollback.

     # Docker image that runs migration and seeds.
     $ docker build --target=migrate -t express-api-es6-starter:migrate .
    
     # Docker image that rollbacks migrations.
     $ docker build --target=migrate-rollback -t express-api-es6-starter:migrate-rollback .

Once the images have been built - all you need to do is run them providing a .env file. Like this:

$ docker run -v "/path/to/your/.env:/app/.env" mesaugat/express-api-es6-starter:migrate

Using MySQL instead of PostgreSQL

Install the mysql driver first.

$ yarn add mysql

Update these lines in your .env file.

- DB_CLIENT='pg'
+ DB_CLIENT='mysql'

- DB_PORT='5432'
+ DB_PORT='3306'

You can remove the pg driver if you like to.

$ yarn remove pg

That's it, you are ready to roll.

Tests

To run the tests you need to create a separate test database. Don't forget to update your .env file to include the connections for test database.

$ NODE_ENV=test yarn migrate
$ yarn test

Run tests with coverage.

$ yarn test:coverage

Why 8848?

Because the highest point in the world is 8848 metres.

Contributing

For contribution and feature requests, please create an issue first.

License

express-api-es6-starter is under MIT License.

express-api-es6-starter's People

Contributors

cham11ng avatar dependabot[bot] avatar ecliptik avatar kabirbaidhya avatar mesaugat avatar pratishshr avatar pravashupreti avatar squgeim avatar subash-poudel avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

express-api-es6-starter's Issues

Show error message on 500

How can I show that error message on console in my return ?

2017-12-16T11:03:36.598Z - error: Error: ER_NO_SUCH_TABLE: Table 'sigpharmaDB1.tipos_medicamentos' doesn't exist

screenshot from 2017-12-16 09-04-07

2 more fields returning

After a post, the return shows 2 more fields, what is that ? I dont have that fields in my model
{
"data": {
"descricao": "Estamos cadastrando um registro",
"big": "132165484655456",
"updated_at": "2017-12-16T11:11:28.363Z",
"created_at": "2017-12-16T11:11:28.363Z",
"id": 1,
"createdAt": "2017-12-16T08:11:28.000Z",
"updatedAt": "2017-12-16T08:11:28.000Z"

}
}

here is my migration

/**
 * Create tipos_medicamentos table.
 *
 * @param  {object} knex
 * @return {Promise}
 */
export function up(knex) {
  return knex.schema.createTable('tipos_medicamentos', table => {
    table.increments();
    table
      .timestamp('created_at')
      .notNull()
      .defaultTo(knex.raw('now()'));
    table.timestamp('updated_at').notNull();
    table.string('descricao', 255).notNull();
    table.string('big', 255);
  });
}

/**
 * Drop tipos_medicamentos table.
 *
 * @param  {object} knex
 * @return {Promise}
 */
export function down(knex) {
  return knex.schema.dropTable('tipos_medicamentos');
}

Problem when field name contains numbers

I'm trying to insert some data on my table.
That table has a field called MED_PLA17
But BookShelf dont recognize when I try to set this field

const record = {
   medAbc: resource.ID_PRODUTO,
   medCtr: resource.NOME_FABRICANTE,
   medCap: resource.CAP,
   medTarja: resource.ID_TARJA,
   medAbc: resource.ID_PRODUTO,
   labNom: resource.NOME_FABRICANTE,
   medTipmed: resource.DESCRICAO_TIPO_PRODUTO,
   medDes: resource.NOME,
   medApr: resource.DESCRICAO,
   medPrinci: resource.COMPOSICAO,
   medBarra: resource.EAN,
   medLab: resource.ID_FABRICANTE,
   medNegpos: resource.ID_LCCT,
   medPla17: resource.MED_PLA17
   // medPLA175: resource.PF_17_5,
   // medPLA18: resource.PF_18,
   // medPla_12: resource.PF_12,
   // medPla20: resource.PF_20

 };

 console.log(`${JSON.stringify(record)}`);


 return new Resource(record).save().then(resource => resource.refresh());
{"medAbc":"240402","medCtr":"AUROBINDO PHARMA","medCap":"0","medTarja":"TV","labNom":"AUROBINDO PHARMA","medTipmed":"GENERICO","medDes":"AMPICILINA SODICA","medApr":"500mg po sol inj x 50fa emb hosp","medPrinci":"AMPICILINA SODICA","medBarra":"7898361884611","medLab":"435","medNegpos":"+","medPla17":"125.64"}

The error

2018-04-11T19:19:51.279Z - error:  Error: ER_BAD_FIELD_ERROR: Unknown column 'med_pla_17' in 'field list'

Unable to migrate

Getting this error while running
npm run migrate:latest

Error: connect ECONNREFUSED 127.0.0.1:5432
at Object.exports._errnoException (util.js:1036:11)
at exports._exceptionWithHostPort (util.js:1059:20)
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1080:14)

docker => 'client' is missing

When I try to run it from docker I get
api_1 | Error: knex: Required configuration option 'client' is missing.

api_1  | [4/5] Linking dependencies...
api_1  | [5/5] Building fresh packages...
api_1  | success Saved 1 new dependency.
api_1  | info Direct dependencies
api_1  | └─ [email protected]
api_1  | info All dependencies
api_1  | └─ [email protected]
api_1  | Done in 11.15s.
api_1  | yarn run v1.6.0
api_1  | $ nodemon --watch .env --watch src --exec babel-node src --source-maps
api_1  | [nodemon] 1.12.1
api_1  | [nodemon] to restart at any time, enter `rs`
api_1  | [nodemon] watching: /app/.env/**/* /app/src/**/*
api_1  | [nodemon] starting `babel-node src --source-maps`
api_1  | /app/node_modules/knex/lib/client.js:108
api_1  |     throw new Error('knex: Required configuration option \'client\' is missing.');
api_1  |     ^
api_1  |
api_1  | Error: knex: Required configuration option 'client' is missing.
api_1  |     at new Client (/app/node_modules/knex/lib/client.js:108:11)
api_1  |     at Knex (/app/node_modules/knex/lib/index.js:60:34)
api_1  |     at Object.<anonymous> (/app/src/db.js:8:14)
api_1  |     at Module._compile (module.js:652:30)
api_1  |     at loader (/app/node_modules/babel-register/lib/node.js:144:5)
api_1  |     at Object.require.extensions.(anonymous function) [as .js] (/app/node_modules/babel-register/lib/node.js:154:7)
api_1  |     at Module.load (module.js:565:32)
api_1  |     at tryModuleLoad (module.js:505:12)
api_1  |     at Function.Module._load (module.js:497:3)
api_1  |     at Module.require (module.js:596:17)
api_1  |     at require (internal/module.js:11:18)
api_1  |     at Object.<anonymous> (/app/src/index.js:2:1)
api_1  |     at Module._compile (module.js:652:30)
api_1  |     at loader (/app/node_modules/babel-register/lib/node.js:144:5)
api_1  |     at Object.require.extensions.(anonymous function) [as .js] (/app/node_modules/babel-register/lib/node.js:154:7)
api_1  |     at Module.load (module.js:565:32)

Update FIELDS different than Insert FIELDS

Hi,
I'm using 'bookshelf-camelcase' plugin and that is my model class

import bookshelfR from '../../../../db_R';

const TABLE_NAME = 'tipo_medicamento';
class tipoMedicamento extends bookshelfR.Model {
  get idAttribute() {
    return 'codigoTipoMedicamento';
  }
  get tableName() {
    return TABLE_NAME;
  }
}
export default tipoMedicamento;

I can succes insert a new record using that function createResource and passing this as parameters:

Parameters

{
	"codigoTipoMedicamento": null,
	"descricao": "Problemas diversos", 
	"codigoBig": "atualizando registro 8"
}

Function

export function createResource(resource) {

  return new Resource({
    descricao: resource.descricao,
    codigoBig: resource.codigoBig
  })
    .save()
    .then(resource => {
      resource.refresh();
      return resource;
    });
}

But when I try to UPDATE my record, using this parameters and function I get some error about the primarykey field name is incorrect:

Parameters to updateRecord function

{
	"codigoTipoMedicamento": null,
	"descricao": "Problemas diversos", 
	"codigoBig": "atualizando registro 8"
}

Function updateRecord

export function updateResource(codigoTipoMedicamento, resource) {
  const data = {
    descricao: resource.descricao,
    codigoBig: resource.codigoBig
  };

  return new Resource({
    codigoTipoMedicamento
  })
    .save(data)
    .then(resource => resource.refresh());
}

table structure in mysql/mariadb

screenshot from 2018-05-10 04-38-40

The ERROR:


 error:  Error: ER_BAD_FIELD_ERROR: Unknown column 'codigoTipoMedicamento' in 'where clause'
    at Query.Sequence._packetToError (/home/duard/projetoSIG/sigpharmaAPI/node_modules/mysql/lib/protocol/sequences/Sequence.js:52:14)
    at Query.ErrorPacket (/home/duard/projetoSIG/sigpharmaAPI/node_modules/mysql/lib/protocol/sequences/Query.js:77:18)
    at Protocol._parsePacket (/home/duard/projetoSIG/sigpharmaAPI/node_modules/mysql/lib/protocol/Protocol.js:279:23)
    at Parser.write (/home/duard/projetoSIG/sigpharmaAPI/node_modules/mysql/lib/protocol/Parser.js:76:12)
    at Protocol.write (/home/duard/projetoSIG/sigpharmaAPI/node_modules/mysql/lib/protocol/Protocol.js:39:16)
    at Socket.<anonymous> (/home/duard/projetoSIG/sigpharmaAPI/node_modules/mysql/lib/Connection.js:103:28)
    at Socket.emit (events.js:160:13)
    at addChunk (_stream_readable.js:269:12)
    at readableAddChunk (_stream_readable.js:256:11)
    at Socket.Readable.push (_stream_readable.js:213:10)
    at TCP.onread (net.js:599:20)

async / await on controllers

Why you dont use async / await on controllers ?

/**
 * GET /api/users
 */
router.get('/', (req, res, next) => {
try { 
  resources = userService.getAllUsers();
  return resources;
} catche(error) {
  res.json(error);
});

Strange return after createrecord

When I run this code

export function createResourceFromAbcFarma(resource) {

  return new Resource({
    med_Abc: resource.ID_PRODUTO,
    med_Ctr: resource.NOME_FABRICANTE,
    med_Cap: resource.CAP,
    med_Tarja: resource.ID_TARJA,
    lab_Nom: resource.NOME_FABRICANTE,
    med_Tipmed: resource.DESCRICAO_TIPO_PRODUTO,
    med_Des: resource.NOME,
    med_Apr: resource.DESCRICAO,
    med_Princi: resource.COMPOSICAO,
    med_Barra: resource.EAN,
    med_Lab: resource.ID_FABRICANTE,
    med_Negpos: resource.ID_LCCT,
    med_pla17: resource.MED_PLA17,
    med_pla175: resource.PF_17_5,
    med_pla18: resource.PF_18,
    med_pla12: resource.PF_12,
    med_pla20: resource.PF_20
  })
    .save()
    .then(resource => {
      console.log(`Inserindo ${JSON.stringify(resource.refresh())}`);
      return resource;
    });
}

The record is inserted on my table, but resource.refresh() result in :

Inserindo {"isFulfilled":false,"isRejected":false}

Add docker

  • With proper documentation on how to setup/deploy

help with idAttribute

How can I set diferent idAttribute to my table ?

something like this.idAttribute: 'cpf';

Debug issue

Hi, first of all, excellent work!

I have a little issue, when you are debugging and save the code nodemon restart correctly but with the same version, this is because its no compiled again, only in the first run, its any way to achive that? i try diffents ways but im stuck.

Thanks!

Swagger info as yml

Why are the swagger info in src/docs as jsdoc? Why not just use yaml? Wouldn't that be simpler and easier to write?

Saving 3 inserts in one post route

How can I insert record in 3 tables (mysql) in one post route ?

I have 3 tables,

table A - id

table B id, a_id
table C id, a_id

I need to create the record on table A and them pass his id to the another tables records.

Logger timestamp issue

  • Date().toLocaleTimeString() doesn't seem to be working in winston

Observed behaviour:
image

Expected behaviour:
image

New Migrate

What is the way to generate ES6 migrations from knex ?
I try to create a new migration but it looks diferent

**knex migrate:make usuarios** 

exports.up = function(knex, Promise) {
  
};

exports.down = function(knex, Promise) {
  
};

404 Not Found has not been implemented

In src/index.js, the last middleware to fallback to is methodNotAllowed. This throws a 405. Shouldn't the fallback be 404, at least for a GET request? There already is a notFoundError implemented in middlewares/errorHandler.

Add prettier to the project

Prettier formatting is controversial but I believe is one of the most "agreeable" formattings out there, and that the whole of Facebook's source has been moved to it is a strong point.

Besides, formatting will always be a case of taste and that will defer from person to person. This usually leads to conflicts between people in a code review (comments like "put a space after if" and another "don't put a space after if").

Arguing about formatting in a code review takes the focus away from the actual code, and to how the code looks to one person.

Adding prettier as a linting rules takes the formatting variable out the code review. Everyone, whether they like it or not, will follow the same rule.

Get the correct error message when transaction fails

Hey,
how can I get the correct error message when my transaction fails. The correct message is where this arrow is showing.

screenshot from 2017-11-18 11-37-56

I want to show the message that field is null.


  let pessoa = RecordPessoa;
  let pessoaFisica = RecordPessoaFisica;
  let pessoaJuridica = RecordPessoaJuridica;
  let cliente = Record;

  bookshelf
    .transaction(t => {
      console.log('just trying transaction here ===>');
      // pessoa
      pessoa = {
        tipo_documento: tipoDocumento
      };

      const data = new RecordPessoa(pessoa)
        .save(null, { transacting: t })
        .then(pessoa => {
          if (tipoDocumento === 0) {
            // pessoa fisica
            pessoaFisica = {
              pessoa_id: pessoa.pessoa_id,
              cpf: record.cpf,
              nascimento: record.nascimento,
              nome_1: record.nome_1,
              nome_2: record.nome_2,
              genero: record.genero,
              estado_civil: record.estado_civil,
              identidade: record.identidade,
              orgao_emissor: record.orgao_emissor,
              emissao: record.emissao,
              nacionalidade: record.nacionalidade,
              naturalidade: record.naturalidade
            };
          } else {
            // pessoa juridica
            pessoaJuridica = {
              pessoa_id: pessoa.pessoa_id,
              cnpj: record.cnpj,
              nome_1: record.nome_1,
              nome_2: record.nome_2,
              cnae_id: record.cnae_id,
              crt: record.crt,
              insc_estadual: record.insc_estadual,
              insc_estadual_st: record.insc_estadual_st,
              insc_municipal: record.insc_municipal,
              insc_suframa: record.insc_suframa
            };
          }
          if (tipoDocumento === 0) {
            // grava pessoa fisica
            return new RecordPessoaFisica(pessoaFisica)
              .save(null, { transacting: t })
              .then(pessoaFisica => {
                // cliente
                cliente = {
                  pessoa_id: pessoaFisica.pessoa_id
                };

                return new Record(cliente).save(null, { transacting: t });
              });
          } else {
            // grava pessoa fisica
            return new RecordPessoaJuridica(pessoaJuridica)
              .save(null, { transacting: t })
              .then(pessoaJuridica => {
                // cliente
                cliente = {
                  pessoa_id: pessoaJuridica.pessoa_id
                };

                return new Record(Record).save(null, { transacting: t });
              });
          }
        });
      console.log('==> DATA => ' + JSON.stringify(data));

      return data;
    })
    .then(damba => {
      console.log(JSON.stringify(damba));
    })
    .catch(function (err) {
      console.log('<======= deveria dar ROLL BACK AQUI =======>');

      console.error(err);

      return err;
    });

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.