Skip to content
Snippets Groups Projects
Commit cd64fcb6 authored by Vytor Calixto's avatar Vytor Calixto :space_invader:
Browse files

Change jsdoc to Docco

parent 9c48e5c5
No related branches found
No related tags found
1 merge request!15Change jsdoc to Docco
Pipeline #
......@@ -10,7 +10,7 @@ const nodemon = require('gulp-nodemon');
const Cache = require('gulp-file-cache');
const jsdoc = require('gulp-jsdoc3');
const docco = require('gulp-docco');
const cache = new Cache();
......@@ -38,12 +38,14 @@ function compile() {
gulp.task('build', compile);
gulp.task('doc', (cb) => {
let config = require('./jsdoc.json');
gulp.src(['README.md', './src/**/*.js'], {read: false})
.pipe(jsdoc(config, cb));
gulp.task('docco', () => {
gulp.src('./src/**/*.js')
.pipe(docco())
.pipe(gulp.dest('./docs'));
});
gulp.task('doc', ['docco']);
gulp.task('test', () => {
gulp.src('test/test.js', {read: false})
.pipe(mocha())
......
......@@ -48,6 +48,7 @@
"gulp": "^3.9.1",
"gulp-babel": "^6.1.2",
"gulp-cli": "^1.2.2",
"gulp-docco": "0.0.4",
"gulp-eslint": "^3.0.1",
"gulp-file-cache": "0.0.1",
"gulp-jsdoc3": "^0.3.0",
......
......@@ -18,25 +18,30 @@ const mongoose = require('./db/mongoose');
const db = mongoose();
// Set default node environment
process.env.NODE_ENV = process.env.NODE_ENV || 'development';
// Parse json received in requests
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
// Enable Cross-Origin Resource Sharing (CORS)
app.use(cors());
app.use(methodOverride());
// Enable cache for 1 day
app.use(cache('1 day'));
// Enable maximum compression
app.use(compression(9));
app.use(api);
// catch 404 and forward to error handler
// Catch 404 and forward to error handler
app.use((req, res, next) => {
res.status(404);
log.debug('%s %d %s', req.method, res.statusCode, req.url);
res.json({ error: 'Not found' }).end();
});
// error handlers
// Error handlers
app.use((err, req, res, next) => {
res.status(err.status || 500);
log.error('%s %d %s', req.method, res.statusCode, err.message);
......
const nconf = require('nconf');
// Exports the config.json as an object with get functions
nconf.argv()
.env()
.file({ file: `${process.cwd()}/config.json` });
......
......@@ -4,10 +4,12 @@ const libs = `${process.cwd()}/libs`;
const config = require(`${libs}/config`);
// Connection options
const poolOptions = {
nrConnections: config.get('monetdb:nrConnections'),
};
// Configuration options
const options = {
host: config.get('monetdb:host'),
port: config.get('monetdb:port'),
......@@ -16,6 +18,7 @@ const options = {
password: config.get('monetdb:password'),
};
// Connection singleton
const conn = new MonetDBPool(poolOptions, options);
conn.connect();
......
......@@ -7,8 +7,10 @@ const log = require(`${libs}/log`)(module);
const mongoose = require('mongoose');
module.exports = () => {
// Get mongodb URI (ip and port) in config file
const mongoUri = config.get('mongodb:uri');
log.debug(`Connecting to MongDB on URI ${mongoUri}`);
// Connection singleton
const db = mongoose.connect(mongoUri);
mongoose.connection.once('open', () => { log.info("MongoDB connected"); });
......
const libs = `${process.cwd()}/libs`;
const log = require(`${libs}/log`)(module);
const conn = require(`${libs}/db/monet`);
/**
* Promise that executes an SQL query with optional parameters
*
* Examples:
* Query with no parameters:
* execSqlQuery('SELECT * FROM people');
* Query with one parameter:
* execSqlQuery('SELECT name, age FROM people WHERE id = ?', [1]);
* Query with more than one parameter:
* execSqlQuery('SELECT name, age FROM people WHERE city = ? AND age > ?', ['São Paulo', 35]);
*
* @param {string} sqlQuery - SQL query to be executed by the Promise
* @param {array} sqlQueryParams - SQL query parameters
*/
// Promise that executes an SQL query with optional parameters
// ```
// Examples:
// Query with no parameters:
// execSqlQuery('SELECT * FROM people');
// Query with one parameter:
// execSqlQuery('SELECT name, age FROM people WHERE id = ?', [1]);
// Query with more than one parameter:
// execSqlQuery('SELECT name, age FROM people WHERE city = ? AND age > ?', ['São Paulo', 35]);
// ```
function execSqlQuery(sqlQuery, sqlQueryParams = []) {
log.debug(`Executing SQL query '${sqlQuery}' with params '${sqlQueryParams}'`);
return new Promise((resolve, reject) => {
// Prepare statement
conn.prepare(sqlQuery, true).then(
(dbQuery) => {
// Execute query
dbQuery.exec(sqlQueryParams).then(
// Success
(dbResult) => {
log.debug(`Query result: ${dbResult.data}`);
log.debug(dbResult.data);
resolve(dbResult.data);
},
// Error
(dbError) => {
log.error(`SQL query execution error: ${dbError.message}`);
reject(new Error(dbError.message));
}
);
// release resources allocated for prepared statement
// Release resources allocated for prepared statement
conn.release();
}
);
......
/**
* Dimensions middleware
*
* EXAMPLE:
* Use it with no parameters to get all the dimensions specified
* app.get('/', dimensions(), function(req, res, next){})
*
* Use it with an array of accepted values
* app.get('/', dimensions(['year', 'location']), function(req, res, next){})
*
* Use it globally
* app.use(dimensions())
*/
/**
* This function returns the intersection of two arrays
* @param {array} a [description]
* @param {array} b [description]
* @return {array} [description]
*/
// This function returns the intersection of two arrays
function intersect(a, b) {
let t;
if (b.length > a.length) {
......@@ -26,23 +8,35 @@ function intersect(a, b) {
return a.filter((e) => b.indexOf(e) !== -1);
}
// Dimensions middleware
// ```
// EXAMPLE:
// Use it with no parameters to get all the dimensions specified
// app.get('/', dimensions(), function(req, res, next){})
//
// Use it with an array of accepted values
// app.get('/', dimensions(['year', 'location']), function(req, res, next){})
//
// Use it globally
// app.use(dimensions())
// ```
function dimensions(dims) {
return (req, res, next) => {
req.dims = {};
if (req.query.dims) {
// Split the string and get all dimensions.
// Example string: 'state:41,year:2013,urban'
const params = req.query.dims.split(',');
const dimObj = {};
// For each dimension in the array see if there is a value associated
for (const param of params) {
const kv = param.split(':');
dimObj[kv[0]] = (typeof kv[1] === 'undefined') ? null : kv[1];
}
// for(let i=0; i<params.length; ++i) {
// let kv = params[i].split(':');
// dimObj[kv[0]] = (typeof kv[1] === 'undefined') ? null : kv[1];
// }
// If the dims array exists and is not empty
if (typeof dims !== 'undefined' && dims.length > 0) {
// Intersect the two arrays
const intersection = intersect(dims, Object.keys(dimObj));
for (let i = 0; i < intersection.length; ++i) {
req.dims[intersection[i]] = dimObj[intersection[i]];
......
......@@ -2,12 +2,7 @@ const libs = `${process.cwd()}/libs`;
const log = require(`${libs}/log`)(module);
const execQuery = require(`${libs}/db/query_exec`);
/**
* Middleware that executes a query defined by a squel object in req.sql
* @param {Object} req [description]
* @param {Object} res [description]
* @param {Function} next [description]
*/
// Middleware that executes a query defined by a squel object in req.sql
function query(req, res, next) {
log.debug(req.sql);
execQuery(req.sql.text, req.sql.values).then((result) => {
......
......@@ -3,10 +3,8 @@ const log = require(`${libs}/log`)(module);
const xml = require('js2xmlparser');
const csv = require('csv-express');
/**
* Custom generic middleware used to send api responses
* @param {string} value text to be used in the xml response
*/
// Custom generic middleware used respond requests.
// The function reads the req.query.format param and respond in json, xml or csv
function response(value) {
return (req, res, next) => {
log.debug(req.query.format);
......
......@@ -12,11 +12,11 @@ const city = require('./city');
const school = require('./school');
// API status route
api.get('/api/v1', (req, res) => {
res.json({ msg: 'SimCAQ API is running' });
});
// mount API routes
api.use('/api/v1/enrollment', enrollment);
api.use('/api/v1/state', state);
api.use('/api/v1/region', region);
......
......@@ -10,23 +10,27 @@ const query = require(`${libs}/middlewares/query`);
const response = require(`${libs}/middlewares/response`);
// Return all cities
cityApp.get('/', (req, res, next) => {
req.sql = squel.select().from('municipios').toParam();
next();
}, query, response('city'));
// Return a specific city by it's id
cityApp.get('/:id', (req, res, next) => {
req.sql = squel.select().from('municipios').where('pk_municipio_id = ?',
parseInt(req.params.id, 10)).toParam();
next();
}, query, response('city'));
// Return a specific city by it's IBGE code
cityApp.get('/ibge/:id', (req, res, next) => {
req.sql = squel.select().from('municipios').where('codigo_ibge = ?',
req.params.id).toParam();
next();
}, query, response('city'));
// Return all the cities from a specific state
cityApp.get('/state/:id', (req, res, next) => {
req.sql = squel.select().from('municipios').where('fk_estado_id = ?',
parseInt(req.params.id, 10)).toParam();
......
......@@ -35,45 +35,36 @@ function filter(req, q) {
}
}
/**
* Complete range of the enrollments dataset
*
* Returns a tuple of start and ending years of the complete enrollments dataset.
*/
// Complete range of the enrollments dataset.
// Returns a tuple of start and ending years of the complete enrollments dataset.
enrollmentApp.get('/year_range', (req, res, next) => {
req.sql = squel.select()
.from('turmas')
.field('MIN(turmas.ano_censo)', 'start_year')
.field('MAX(turmas.ano_censo)', 'end_year')
.toParam();
.from('turmas')
.field('MIN(turmas.ano_censo)', 'start_year')
.field('MAX(turmas.ano_censo)', 'end_year')
.toParam();
next();
}, query, response('range'));
/**
* Returns all educational levels avaible
*
*/
// Returns all educational levels avaible
enrollmentApp.get('/education_level', (req, res, next) => {
req.sql = squel.select()
.from('etapa_ensino')
.field('pk_etapa_ensino_id', 'id')
.field('desc_etapa', 'name')
.toParam();
.from('etapa_ensino')
.field('pk_etapa_ensino_id', 'id')
.field('desc_etapa', 'name')
.toParam();
next();
}, query, response('education_level'));
/**
* Returns all adm dependency
*
*/
// Returns all adm dependencies
enrollmentApp.get('/adm_dependency', (req, res, next) => {
req.sql = squel.select()
.from('dependencia_adms')
.field('pk_dependencia_adm_id', 'id')
.field('nome', 'name')
.toParam();
.from('dependencia_adms')
.field('pk_dependencia_adm_id', 'id')
.field('nome', 'name')
.toParam();
next();
}, query, response('adm_dependency'));
......@@ -125,9 +116,9 @@ enrollmentApp.use('/', (req, res, next) => {
if (typeof params.aggregate !== 'undefined' && params.aggregate === 'region') {
log.debug('Using enrollments query for regions');
const q = squel.select().from('mat_regioes')
.field('name')
.field('SUM(total)', 'total')
.field('ano_censo', 'year');
.field('name')
.field('SUM(total)', 'total')
.field('ano_censo', 'year');
filter(req, q);
......@@ -144,9 +135,9 @@ enrollmentApp.use('/', (req, res, next) => {
if (typeof params.aggregate !== 'undefined' && params.aggregate === 'state') {
log.debug('Using enrollments query for states');
const q = squel.select().from('mat_estados')
.field('name')
.field('SUM(total)', 'total')
.field('ano_censo', 'year');
.field('name')
.field('SUM(total)', 'total')
.field('ano_censo', 'year');
filter(req, q);
......@@ -163,9 +154,9 @@ enrollmentApp.use('/', (req, res, next) => {
if (typeof params.aggregate !== 'undefined' && params.aggregate === 'city') {
log.debug('Using enrollments query for cities');
const q = squel.select().from('mat_municipios')
.field('name')
.field('SUM(total)', 'total')
.field('ano_censo', 'year');
.field('name')
.field('SUM(total)', 'total')
.field('ano_censo', 'year');
filter(req, q);
......@@ -182,9 +173,9 @@ enrollmentApp.use('/', (req, res, next) => {
if (typeof params.aggregate !== 'undefined' && params.aggregate === 'school') {
log.debug('Using enrollments query for schools');
const q = squel.select().from('mat_escolas')
.field('name')
.field('SUM(total)', 'total')
.field('ano_censo', 'year');
.field('name')
.field('SUM(total)', 'total')
.field('ano_censo', 'year');
filter(req, q);
......@@ -201,8 +192,8 @@ enrollmentApp.use('/', (req, res, next) => {
if (typeof params.aggregate === 'undefined') {
log.debug('Using enrollments query for the whole country');
const q = squel.select().from('turmas').field("'Brasil'", 'name')
.field('COALESCE(SUM(num_matriculas),0)', 'total')
.field('ano_censo', 'year');
.field('COALESCE(SUM(num_matriculas),0)', 'total')
.field('ano_censo', 'year');
filter(req, q);
......@@ -216,27 +207,4 @@ enrollmentApp.get('/', (req, res, next) => {
next();
}, query, response('enrollments'));
// enrollmentApp.get('/', (req, res, next) => {
// log.debug(`Request parameters: ${req}`);
// if (typeof req.sqlQuery === 'undefined') {
// // Should only happen if there is a bug in the chaining of the
// // '/enrollments' route, since when no +aggregate+ parameter is given,
// // it defaults to use the query for the whole country.
// log.error('BUG -- No SQL query was found to be executed!');
// next('Internal error, request could not be satisfied at this moment. Please, '
// + 'try again later');
// } else {
// log.debug('SQL query: ${ req.sqlQuery }?');
// log.debug(req.sqlQuery);
// dbQuery(req.sqlQuery).then((result) => {
// req.result = result;
// return response(req, res);
// }, (error) => {
// log.error(`[${req.originalUrl}] SQL query error: ${error}`);
// next('Internal error, request could not be satisfied at this moment. Please, '
// + 'try again later');
// });
// }
// });
module.exports = enrollmentApp;
......@@ -10,11 +10,13 @@ const query = require(`${libs}/middlewares/query`);
const response = require(`${libs}/middlewares/response`);
// Get all regions
regionApp.get('/', (req, res, next) => {
req.sql = squel.select().from('regioes').toParam();
next();
}, query, response('region'));
// Get a region by it's id
regionApp.get('/:id', (req, res, next) => {
req.sql = squel.select().from('regioes').where('pk_regiao_id = ?',
parseInt(req.params.id, 10)).toParam();
......
......@@ -16,23 +16,26 @@ const response = require(`${libs}/middlewares/response`);
* A api fica sobrecarregada
* Pense na cena do elevador de driver mas o elevador é uma bomba de fusão e demora mais que uma luta do DBz
*/
// schoolApp.get('/', (req, res, next) => {
// req.sql = squel.select().from('escolas')
// .field('pk_escola_id')
// .field('nome_entidade', 'name')
// .field('ano_censo', 'year')
// .field('fk_cod_estado')
// .field('fk_cod_municipio')
// .toParam();
// next();
// }, query, response('school'));
/* schoolApp.get('/', (req, res, next) => {
* req.sql = squel.select().from('escolas')
* .field('pk_escola_id')
* .field('nome_entidade', 'name')
* .field('ano_censo', 'year')
* .field('fk_cod_estado')
* .field('fk_cod_municipio')
* .toParam();
* next();
* }, query, response('school'));
*/
// Get a school by it's id
schoolApp.get('/:id', (req, res, next) => {
req.sql = squel.select().from('escolas').where('pk_escola_id = ?',
parseInt(req.params.id, 10)).toParam();
next();
}, query, response('school'));
// Get all schools from a state
schoolApp.get('/state/:id', (req, res, next) => {
req.sql = squel.select().from('escolas')
.field('pk_escola_id')
......@@ -46,6 +49,7 @@ schoolApp.get('/state/:id', (req, res, next) => {
next();
}, query, response('school'));
// Get all schools from a city
schoolApp.get('/city/:id', (req, res, next) => {
req.sql = squel.select().from('escolas')
.field('pk_escola_id')
......
......@@ -10,17 +10,20 @@ const query = require(`${libs}/middlewares/query`);
const response = require(`${libs}/middlewares/response`);
// Get all states
stateApp.get('/', (req, res, next) => {
req.sql = squel.select().from('estados').toParam();
next();
}, query, response('state'));
// Get a state
stateApp.get('/:id', (req, res, next) => {
req.sql = squel.select().from('estados').where('pk_estado_id = ?',
parseInt(req.params.id, 10)).toParam();
next();
}, query, response('state'));
// Get all states from a region
stateApp.get('/region/:id', (req, res, next) => {
req.sql = squel.select().from('estados').where('fk_regiao_id = ?',
parseInt(req.params.id, 10)).toParam();
......
......@@ -8,8 +8,10 @@ const log = require(`${libs}/log`)(module);
const app = require(`${libs}/app`);
// Set default port: first environment variable PORT, then configuration and last 3000
app.set('port', process.env.PORT || config.get('port') || 3000);
// Set default ip: first environment variable IOP, then configuration and last '127.0.0.1'
app.set('ip', process.env.IP || config.get('ip') || '127.0.0.1');
const server = app.listen(app.get('port'), () => {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment