
Security News
Axios Maintainer Confirms Social Engineering Attack Behind npm Compromise
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.
@comodinx/microservice
Advanced tools
Node.js microservice base helpers.
npm i @comodinx/microservice
git clone https://gitlab.com/comodinx/microservice.git
cd microservice
npm i
NOTE: Based on bluebird promises.
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'}
*/
| 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 |
| 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' |
| 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 |
| 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 |
| 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 |
| 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'); |
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');
const {
// Routes for error handling. Handle all responses errors (400, 404, 500, etc...)
errors,
// Route for health check.
health
} = require('@comodinx/microservice/server/routes');
Simple usage
errors(app);
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 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();
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();
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 (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();
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();
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();
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
In order to see all database documentation click here
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;
});
Bear in mind that everything has an order. Extending the models (for now) requires an order in the
requireIn 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'); ...
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 => ...);
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" } }
In order to see all validation functions click here
const validator = require('@comodinx/microservice/helpers/validator');
validator.isEmail('johndoe@gmail.com'); // true
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
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
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!
In order to see more concrete examples, I INVITE YOU TO LOOK AT THE TESTS :)
npm test
FAQs
@comodinx/microservice is a Node.js microservice base helpers.
We found that @comodinx/microservice demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.

Security News
The Axios compromise shows how time-dependent dependency resolution makes exposure harder to detect and contain.