npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@comodinx/microservice

v0.1.2

Published

@comodinx/microservice is a Node.js microservice base helpers.

Downloads

11

Readme

@comodinx/microservice

Node.js microservice base helpers.

Index

Download & Install

NPM

npm i @comodinx/microservice

Source code

git clone https://gitlab.com/comodinx/microservice.git
cd microservice
npm i

How is it used?

NOTE: Based on bluebird promises.

Getting started

const pkg = require('./package.json');
const { app, listen } = require('@comodinx/microservice/server');
const { errors, health } = require('@comodinx/microservice/server/routes');

app.get('/', (req, res) => res.send('Hello World!'));

// Handle route for health check
health(app, { pkg /* , router, database, services: ['other-service-name'] */ });

// Handle all errors (400, 404, 500, etc...)
errors(app);

listen(app);
/*
 * Listen routes
 *  + GET  /        Home
 *  + GET  /health  Health check
 *  + ANY  /*       404 error. {code: 404, error: 'Not Found'}
 */

Configure

For app/server.

| Environment variable | Values | Type | Default value | Description | |:-------------------------------|:------------------------------|:--------|:------------------------|:-------------------------------------------------------------------------------------------| | SERVER_HOST | host name | string | undefined | Host name where the server listens | | SERVER_PORT / PORT | port number | number | 8000 | Port where the server listens | | SERVER_MULTIPART | true/false | boolean | false | Indicate if app use support for multipart middleware | | SERVER_HEALTH_PATH | health check path | string | "/health" | Route for health check endpoint | | BODY_PARSER_LIMIT | request limit | string | "5mb" | Indicate request size limit (generic, apply to raw, text, json and urlencoded) | | BODY_PARSER_RAW_LIMIT | request limit for raw | string | "5mb" | Indicate request size limit for raw | | BODY_PARSER_TEXT_LIMIT | request limit for text | string | "5mb" | Indicate request size limit for text | | BODY_PARSER_JSON_LIMIT | request limit for json | string | "5mb" | Indicate request size limit for json | | BODY_PARSER_URLENCODED_LIMIT | request limit for url encoded | string | "5mb" | Indicate request size limit for url encoded |

For database

Simple configuration

| Environment variable | Values | Type | Default value | Description | |:-------------------------------|:----------------------|:--------|:------------------------|:-------------------------------------------------------------------------------------------| | DB_ENABLED | true/false | boolean | true | Indicate if need support for database | | DB_NAME | database name | string | null | | | DB_HOST | database host name | string | 'localhost' | | | DB_PORT | database port | number | 3306 | | | DB_USER | database user | string | 'username' | | | DB_PASS | database password | string | null | | | DB_TIMEZONE | database timezone | string | '+00:00' | |

Read/Write replication configuration

| Environment variable | Values | Type | Default value | Description | |:-------------------------------|:----------------------|:--------|:------------------------|:-------------------------------------------------------------------------------------------| | DB_HOST_WRITE | database host name | string | DB_HOST | Database host name for write replication | | DB_PORT_WRITE | database port | number | DB_PORT | Database port for write replication | | DB_USER_WRITE | database user | string | DB_USER | Database username for write replication | | DB_PASS_WRITE | database password | string | DB_PORT | Database password for write replication | | DB_HOST_READ | database host name | string | DB_HOST | Database host name for read replication | | DB_PORT_READ | database port | number | DB_PORT | Database port for read replication | | DB_USER_READ | database user | string | DB_USER | Database username for read replication | | DB_PASS_READ | database password | string | DB_PORT | Database password for read replication |

Pool configuration

| Environment variable | Values | Type | Default value | Description | |:-------------------------------|:----------------------|:--------|:------------------------|:-------------------------------------------------------------------------------------------| | DB_POOL_ENABLED | true/false | boolean | true | Indicate if need support for db pool connections | | DB_POOL_MAX | max pool connections | number | 10 | Maximum number of connection in pool | | DB_POOL_MIN | min pool connections | number | 0 | Minimum number of connection in pool | | DB_POOL_IDLE | max idle time | number | 10000 | Maximum time, in milliseconds, that a connection can be idle before being released | | DB_POOL_ACQUIRE | max time reconnect | number | 60000 | Maximum time, in milliseconds, that pool will try to get connection before throwing error | | DB_POOL_EVICT | interval time | number | 1000 | Time interval, in milliseconds, after which sequelize-pool will remove idle connections |

For services

| Environment variable | Values | Type | Default value | Description | |:-------------------------------|:----------------------|:--------|:------------------------|:-------------------------------------------------------------------------------------------| | SERVICE_AGENT | service agent name | string | '' | | | SERVICE_CONNECTION_TIMEOUT | number in miliseconds | number | 21000 | | | SERVICE_REQUEST_TIMEOUT | number in miliseconds | number | 20000 | |

For global dependencies

| Environment variable | Values | Type | Default value | Description | |:-------------------------------|:----------------------|:--------|:------------------------|:-------------------------------------------------------------------------------------------| | DEFAULT_LOCALE | locale | string | 'es' | Default locale | | MOMENT_LOCALE | locale | string | DEFAULT_LOCALE | Default locale for moment module | | MOMENT_DEFAULT_FORMAT | date format | string | 'YYYY-MM-DD HH:mm:ss' | Default format for moment.format | | NUMERAL_LOCALE | locale | string | DEFAULT_LOCALE | Default locale for numeral module | | NUMERAL_DEFAULT_INTEGER_FORMAT | number format | string | '0,0' | Example usage numeral(1000).format(numeral.defaultIntegerFormat) | | NUMERAL_DEFAULT_DECIMAL_FORMAT | number format | string | '0,0.00' | Example usage numeral(10.01).format(numeral.defaultDecimalFormat) | | NUMERAL_DEFAULT_BALANCE_FORMAT | number format | string | '$ 0,0.00' | Example usage numeral(100.2).format(numeral.defaultBalanceFormat) | | LODASH_TRUNCATE_LENGTH | length | number | 24 | Default truncate length use for lodash. Example usage _.truncate('hi-diddly-ho there'); | | LODASH_TRUNCATE_SEPARATOR | string separator | string | ' ' | Default truncate separatotr use for lodash. Example usage _.truncate('hi diddly there'); |

Detailed explanation

Server

const {
    // Base express application instance
    //  Example usage:
    //   app.get('/', (req, res) => res.send('Hello World!'));
    app,

    // Listen express application instance.
    // If the `config('server.https.enabled')` is false, listen from the express application instance will be executed.
    // If the `config('server.https.enabled')` is true, listen from the instance of https.createServer({ key, cert }) will be executed.
    //  Example usage:
    //   listen(app);
    //
    // NOTE: Listen does nothing when NODE_ENV=test
    listen
} = require('@comodinx/microservice/server');

Routes

const {
    // Routes for error handling. Handle all responses errors (400, 404, 500, etc...)
    errors,

    // Route for health check.
    health
} = require('@comodinx/microservice/server/routes');
Examples for errors

Simple usage

errors(app);
Examples for health

Simple usage

health(app);

Complex usage

health(/* express appplication or express.Router */ app, {

  // To be able to change the url of health check.
  url: '/health',

  // To be able to import package.json and tag.json if they exist. <process.cwd()>
  rootDir: null,

  // For add package information details on health response. (name, description and version) <require('./package.json')>
  pkg: null,

  // For add tag details on health response. <{commit, version, name}>
  tag: null,

  // IDEM url. Default `url`
  path: null,

  // In order to run the health check on a specific router (express.Router).
  router: null,

  // For add database information details on health response. (is alive, error). <database instance require('@comodinx/sequelize')>
  database: null,

  // For add required services information details on health response. (is alive, error) <string list of services added to @comodinx/microservice/helpers/service>
  service: null
});
Get by ID

Get model by id

const Route = require('@comodinx/microservice/server/routes/getById');

const route = new Route('YourModel', {
    // Indicates the name of the parameter to search in `req.params`. Default 'id'
    paramNameId: 'id',

    // Indicates the validation that will be applied to the parameter. Default 'isInteger'
    // Possible values:
    //  Function
    //    Example:
    //      function (id, req) { return id > 10; }
    //  String (https://www.gitlab.com/comodinx/microservice#validator)
    validatorIdType: 'isInteger'
});

module.exports = route.handlerize();
Destroy

Delete model. (**WARNING** - Physical erasure! If req.query.force = true)

const Route = require('@comodinx/microservice/server/routes/destroy');

const route = new Route('YourModel', {
    // Indicates the name of the parameter to search in `req.params`. Default 'id'
    paramNameId: 'id',

    // Indicates the validation that will be applied to the parameter. Default 'isInteger'
    // Possible values:
    //  Function
    //    Example:
    //      function (id, req) { return id > 10; }
    //  String (https://www.gitlab.com/comodinx/microservice#validator)
    validatorIdType: 'isInteger'
});

module.exports = route.handlerize();
List

DEPRECATED List (pagination, filter, order and group) from database model

const Route = require('@comodinx/microservice/server/routes/list');

const route = new Route('YourModel', {
    // Indicates the page size. Default 10
    defaultPageSize: 10,

    // Indicates the validation that will be applied to the parameter. Default null
    // Possible values:
    //  Object with key-value, where the key is the name of the parameter in the filter, and the value is the name of the column in the database
    //    Example:
    //      { idType: 'id_yourmodel_type' }
    mapKeyParse: null
});

module.exports = route.handlerize();
List by query

List (pagination, filter, order and group) from database model

const Route = require('@comodinx/microservice/server/routes/listByQuery');

const route = new Route('User', {
    // Relationship with others tables or services. Default value is null
    relationships: [
        // Example for related table
        {
            // relationship name
            name: 'attributes',
            // related table name
            table: 'job_candidates',
            // field needed from related table for join relationship
            fieldSource: 'candidates.id_job',
            // field needed from model for match join relationship
            fieldTarget: 'jobs.id'
        },

        // Example for related with remote service
        {
            // relationship name
            name: 'person',
            // indicate that relationship is with a remote service
            remote: 'true',
            // service name. helpers/service[<service name>]
            service: 'people',
            // url of remote endpoint
            uri: '/people',
            // field needed from remote service for join relationship
            fieldSource: 'id',
            // field needed from model for match join relationship
            fieldTarget: 'users.id_person'
        }
    ],

    // Indicates the page size. Default 10
    defaultPageSize: 10,

    // Indicates the validation that will be applied to the parameter. Default null
    // Possible values:
    //  Object with key-value, where the key is the name of the parameter in the filter, and the value is the name of the column in the database
    //    Example:
    //      { idType: 'id_yourmodel_type' }
    mapKeyParse: null
});

module.exports = route.handlerize();
Proxy

Handrails between microservices

const Route = require('@comodinx/microservice/server/routes/proxy');

const route = new Route({
    // Indicates the service name defined on @comodinx/microservice/helpers/service.
    serviceName: 'myService',

    // Indicates the function use on service instance. Default `req.method`
    serviceMethod: req.method,

    // Indicates the path use when calling service. Default `req.path`
    serviceUrl: req.path,

    // Extra service request options. Default `{}`
    serviceOptions: {
      responseType: 'json'
    },

    // Indicate if response with the same service response content type.
    sameContentType: true

    // TODO :: Send in service request, the same header from original request
    // headers: [
    //   'authorization'
    // ]
});

module.exports = route.handlerize();
Base route
const _ = require('lodash');
const Base = require('@comodinx/microservice/server/routes');
const { validator } = require('@comodinx/microservice/helpers');
const { errors, database } = require('@comodinx/microservice');
// ...
class Route extends Base {
    /**
     * Validate request
     */
    validate (req) {
        if (_.isEmpty(req.params)) {
            throw new errors.BadRequest('Bad request. Please set "id" parameter');
        }
        if (!validator.isInteger(req.params.id)) {
            throw new errors.BadRequest('Bad request. Please use "id" on parameters');
        }
        return req;
    }

    /**
     * Handle request
     */
    handler (req) {
        return database.models.YourModel.getById(req.params.id).then(model => {
            if (!model) {
                throw new errors.NotFound(`Not found model ${context.id}`);
            }
            return model;
        });
    }
}

module.exports = (new Route()).handlerize();

Config

In order to see all config documentation click here

const { config } = require('@comodinx/microservice');
// ...
// Read configuration
config('server.port'); // 8000

// Extend current configuration.
config.extend({ server: { port: 8001 } });
config('server.port'); // 8001

// Use default value.
config('server.port2', 8001); // 8001

Database

In order to see all database documentation click here

database instance
const { errors, database } = require('@comodinx/microservice');
// ...
return database.models.YourModel.getById(id).then(yourModel => {
    if (!yourModel) {
        throw new errors.NotFound(`Model not found ${id}`);
    }
    return yourModel;
});

Example use raw database, function query

In order to see all operators click here

const { database } = require('@comodinx/microservice');
// ...
return database.models.YourModel.find({
    where: {
        deleted_at: {
            [database.Op.is]: null
        }
    },
    order: [['id', 'DESC']],
    limit: 100,
    offset: 0
});

Example use raw database, function query

In order to see all query types click here

const { database } = require('@comodinx/microservice');
// ...
return database.query('UPDATE users SET active = 0 WHERE id = 1', { type: database.QueryTypes.UPDATE }).spread((results, metadata) => {
    // ...
    return metadata;
});
database model

Bear in mind that everything has an order. Extending the models (for now) requires an order in the require

In the first file of our app / microservice, we have to do the require in the following order

// Setting
require('./config');

// Dependencies
require('@comodinx/microservice/helpers/dependencies');

// Our model extensions
require('./models');

...
Example add extra functionality on model.

File path models/organizations.js

File source:

const { database, database: { Model } } = require('@comodinx/microservice');

class Organizations extends Model {
    /*
     * Function used for populate relationships when model if loaded.
     */
    populate (organization, options) {
        options = options || {};

        if ((options.tiny && !options.with) || options.small) {
            return super.populate(organization, options);
        }

        return super.populate(organization, options)
            // Load users, from remote users service, related with the organization.
            .then(() => this.populateRemotes(organization, 'users', options));
    }

    /*
     * Another extra function
     */
    findAllActives () {
        // ...
    }
}

// Export model Organizations, and extend model organizations on database instance.
module.exports = database.models.Organizations = Organizations;

Usage model extension:

const { database } = require('@comodinx/microservice');

database.models.Organizations.findAllActives().then(models => ...);

Errors

const { errors } = require('@comodinx/microservice');
// ...
throw new errors.NotFound();
// All HTTP Status Code are an Exception
const e = new errors.NotFound('My custom message', {hello: 'world'});
// ...
console.log(e.toJson());
// { "error": 'My custom message', "code": 404, "extra": { "hello": "world" } }

Validator

In order to see all validation functions click here

const validator = require('@comodinx/microservice/helpers/validator');

validator.isEmail('[email protected]'); // true
Custom validations.
Integer
validator.isInteger(); // false
validator.isInteger(null); // false
validator.isInteger('a'); // false
validator.isInteger('6'); // true
validator.isInteger('6.1'); // false
validator.isInteger('-6'); // true
validator.isInteger(6); // true
validator.isInteger(6.1); // false
validator.isInteger(-6); // true
Number
validator.isNumber(); // false
validator.isNumber(null); // false
validator.isNumber('a'); // false
validator.isNumber('6'); // true
validator.isNumber('6.1'); // true
validator.isNumber('-6'); // true
validator.isNumber(6); // true
validator.isNumber(6.1); // true
validator.isNumber(-6); // true

Logger

const logger = require('@comodinx/microservice/helpers/logger');

logger.error(new Error('Not Found')); // [2020-01-28T17:16:50.379Z] - ERROR - ✘ Ooops... Error: Not Found
logger.error('This is an error');     // [2020-01-28T17:16:50.379Z] - ERROR - ✘ Ooops... This is an error
logger.warn('This is a warning');     // [2020-01-28T17:16:50.381Z] - WARN - ⚠ This is a warning
logger.info('Hello World!');          // [2020-01-28T17:16:50.381Z] - INFO - Hello World!
logger.title('Hello World!');         // [2020-01-28T17:16:50.382Z] - INFO - ==========   Hello World!   ==========
logger.success('Hello World!');       // [2020-01-28T17:16:50.383Z] - INFO - ✔ Hello World!
logger.arrow('Hello World!');         // [2020-01-28T17:16:50.384Z] - INFO - • Hello World!
logger.step('Hello World!');          // [2020-01-28T17:16:50.384Z] - INFO - ✦ Hello World!
logger.lap('Hello World!');           // [2020-01-28T17:16:50.384Z] - INFO - ➜ Hello World!

Tests

In order to see more concrete examples, I INVITE YOU TO LOOK AT THE TESTS :)

Run the unit tests

npm test