Commit ca428c12 authored by Eduardo L. Buratti's avatar Eduardo L. Buratti

Move to TypeScript as main language

parent a97d836f
*.log
*.out
*.pid
*.js
*.js.map
/.trash
/pids
/logs
......@@ -10,3 +12,4 @@
/config/*.yaml
/doc/build
/coverage
/typings
......@@ -4,7 +4,10 @@
"description": "BlenDB",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
"prestart": "tsc",
"start": "node build/src/boot",
"pretest": "tsc",
"test": "mocha"
},
"repository": {
"type": "git",
......@@ -31,7 +34,9 @@
"jshint": "^2.9.2",
"mongodb": "^2.2.5",
"osprey": "^0.3.2",
"raml2html": "^2.4.0"
"raml2html": "^2.4.0",
"typescript": "^1.8.10",
"typings": "^1.3.2"
},
"devDependencies": {
"chai": "^3.5.0",
......
......@@ -18,25 +18,17 @@
* along with blendb. If not, see <http://www.gnu.org/licenses/>.
*/
'use strict';
import * as express from "express";
const MongoClient = require('mongodb').MongoClient;
export class CollectCtrl {
static write(req: express.Request, res: express.Response, next: express.NextFunction) {
if ('_id' in req.body) {
res.status(400)
.json({ message: 'Property named \'_id\' is protected.' });
return;
}
class Mongo {
constructor() {
this.db = undefined;
}
connect(connectionString) {
MongoClient.connect(connectionString, (err, db) => {
if (err) {
console.error(err);
return;
}
this.db = db;
});
res.status(500)
.json({ message: 'Error while writing to the database.' });
}
}
module.exports = new Mongo();
/*
* Copyright (C) 2015 Centro de Computacao Cientifica e Software Livre
* Departamento de Informatica - Universidade Federal do Parana
*
* This file is part of blendb.
*
* blendb is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* blendb is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with blendb. If not, see <http://www.gnu.org/licenses/>.
*/
import * as express from "express";
export class DataCtrl {
static read(req: express.Request, res: express.Response, next: express.NextFunction) {
let metrics = req.query.metrics.split(',');
let dimensions = req.query.dimensions.split(',');
res.status(500).json({ message: 'Query execution failed ' +
'because of an unknown error.' });
}
}
......@@ -18,15 +18,13 @@
* along with blendb. If not, see <http://www.gnu.org/licenses/>.
*/
'use strict';
const osprey = require('osprey');
// import controllers
const data = require('./controllers/data');
const collect = require('./controllers/collect');
import { DataCtrl } from './controllers/data';
import { CollectCtrl } from './controllers/collect';
const router = module.exports = osprey.Router();
export const router = osprey.Router();
router.get('/data', data.read);
router.post('/collect/{class}', collect.write);
router.get('/data', DataCtrl.read);
router.post('/collect/{class}', CollectCtrl.write);
#!/usr/bin/env node
/*
* Copyright (C) 2015 Centro de Computacao Cientifica e Software Livre
* Departamento de Informatica - Universidade Federal do Parana
......@@ -18,26 +19,41 @@
* along with blendb. If not, see <http://www.gnu.org/licenses/>.
*/
'use strict';
// external libraries
import express = require('express');
import path = require('path');
const aggregator = require('core/aggregator');
const osprey = require('osprey');
const ramlParser = require('raml-parser');
class Data {
read(req, res, next) {
let metrics = req.query.metrics.split(',');
let dimensions = req.query.dimensions.split(',');
// create a new express app
const app = module.exports = express();
aggregator.query(metrics, dimensions, (err, data) => {
if (err) {
console.error(err);
res.status(500).json({ message: 'Query execution failed ' +
'because of an unknown error.' });
return;
}
// load router
import { router } from './api/router-v1';
// parse the RAML spec and load osprey middleware
ramlParser.loadFile('specs/blendb-api-v1.raml')
.then((raml: any) => {
app.use('/v1',
osprey.security(raml),
osprey.server(raml),
router);
res.json({ data });
});
}
}
if (!module.parent) {
let port = process.env.PORT || 3000;
app.listen(port);
module.exports = new Data();
if (app.get('env') === 'development') {
console.log('Server listening on port ' + port + '.');
}
}
else {
// signalize to the test suite that the server is ready to be tested
app.locals.ready = true;
}
},
(err: any) => {
console.error('RAML Parsing Error: ' + err.message);
process.exit(1);
});
......@@ -18,30 +18,23 @@
* along with blendb. If not, see <http://www.gnu.org/licenses/>.
*/
'use strict';
import { expect } from 'chai';
const mongo = require('core/mongo');
import { Aggregate } from './aggregate';
class Collect {
write(req, res, next) {
let collection = mongo.db.collection('raw.' + req.params.class);
describe('aggregate class', () => {
it('should be instantiated with an array metrics and one of dimensions', () => {
let aggr = new Aggregate(['met:one'], ['dim:one', 'dim:two']);
expect(aggr).to.be.an('object');
});
if ('_id' in req.body) {
res.status(400)
.json({ message: 'Property named \'_id\' is protected.' });
return;
}
it('should not be instantiated with an empty array of metrics', () => {
let aggr = new Aggregate([], ['dim:one', 'dim:two']);
expect(aggr).to.be.an('object');
});
collection.insertOne(req.body, function (err, r) {
if (err) {
res.status(500)
.json({ message: 'Error while writing to the database.' });
return;
}
res.status(200).json({ _id: r.insertedId });
});
}
}
module.exports = new Collect();
it('should not be instantiated with an empty array of dimensions', () => {
let aggr = new Aggregate(['met:one'], []);
expect(aggr).to.be.an('object');
});
});
......@@ -18,17 +18,19 @@
* along with blendb. If not, see <http://www.gnu.org/licenses/>.
*/
'use strict';
export class Aggregate {
metrics: string[];
dimensions: string[];
data: any[];
class Aggregate {
constructor(metrics, dimensions, options) {
constructor(metrics: string[], dimensions: string[], options?: any) {
this.metrics = metrics;
this.dimensions = dimensions;
this.data = [];
}
push(data) {
push(data: any) {
this.data.push(data);
}
......@@ -36,5 +38,3 @@ class Aggregate {
this.data = [];
}
}
module.exports = Aggregate;
......@@ -20,20 +20,24 @@
'use strict';
const hash = require('util/hash');
import { Hash } from '../util/hash';
const Source = require('core/source');
const Transformer = require('core/transformer');
const Aggregate = require('core/aggregate');
import { Source } from './source';
import { Transformer } from './transformer';
import { Aggregate } from './aggregate';
export class Server {
sources: Map<string,Source>;
transformers: Map<string,Transformer>;
aggregates: Map<string,Aggregate>;
class BlenDB {
constructor() {
this.sources = new Map();
this.transformers = new Map();
this.aggregates = new Map();
}
source(name, options) {
source(name: string, options?: any) {
if (this.sources.has(name)) {
return this.sources.get(name);
}
......@@ -44,7 +48,7 @@ class BlenDB {
}
}
transformer(name, options) {
transformer(name: string, options?: any) {
if (this.transformers.has(name)) {
return this.transformers.get(name);
}
......@@ -55,11 +59,8 @@ class BlenDB {
}
}
aggregate(metrics, dimensions, options) {
metrics = Array.from(metrics);
dimensions = Array.from(dimensions);
const id = hash.sha1(metrics.sort() + dimensions.sort());
aggregate(metrics: string[], dimensions: string[], options?: any) {
const id = Hash.sha1(metrics.sort(), dimensions.sort());
if (this.aggregates.has(id)) {
return this.aggregates.get(id);
......@@ -72,12 +73,12 @@ class BlenDB {
}
process() {
this.transformers.forEach((transformer) => {
this.transformers.forEach((transformer: Transformer) => {
const source = this.source(transformer.source);
const aggr = this.aggregate(transformer.metrics,
transformer.dimensions);
source.forEach((doc) => {
source.forEach((doc: any) => {
aggr.push({
metrics: transformer.extractMetrics(doc),
dimensions: transformer.extractDimensions(doc)
......@@ -93,5 +94,3 @@ class BlenDB {
console.log(this.aggregates);
}
}
module.exports = { BlenDB, Source, Transformer };
......@@ -20,20 +20,23 @@
'use strict';
class Source {
constructor(name, options) {
export class Source {
name: string;
data: any[];
constructor(name: string, options: any) {
this.name = name;
this.data = [];
}
push(doc) {
push(doc: any) {
this.data.push(doc);
}
forEach(callback) {
this.data.forEach(callback);
forEach(callback: Function) {
this.data.forEach((value: any, index: number, array: any[]) => {
callback(value);
});
}
}
module.exports = Source;
......@@ -20,24 +20,27 @@
'use strict';
class Transformer {
constructor(name, options) {
export class Transformer {
source: string;
metrics: string[];
dimensions: string[];
extractors: any;
constructor(name: string, options: any) {
this.source = options.source || null;
this.metrics = options.metrics || [];
this.dimensions = options.dimensions || [];
this.extractors = {
metrics: options.extractors.metrics || ((doc) => null),
dimensions: options.extractors.dimensions || ((doc) => null)
metrics: options.extractors.metrics || ((doc: any): any => null),
dimensions: options.extractors.dimensions || ((doc: any): any => null)
};
}
extractMetrics(doc) {
extractMetrics(doc: any) {
return this.extractors.metrics(doc);
}
extractDimensions(doc) {
extractDimensions(doc: any) {
return this.extractors.dimensions(doc);
}
}
module.exports = Transformer;
......@@ -18,26 +18,21 @@
* along with blendb. If not, see <http://www.gnu.org/licenses/>.
*/
'use strict';
import { expect } from 'chai';
/* globals expect */
/* jshint -W024 */
/* jshint expr:true, maxlen:false */
/* jscs:disable maximumLineLength */
const hash = require('util/hash');
import { Hash } from './hash';
describe('hash utility library', () => {
it('should generate a sha1 hash for a collection of objects', () => {
let h = hash.sha1('test', { obj: 'test' }, ['list', 'of', 'things']);
let h = Hash.sha1('test', { obj: 'test' }, ['list', 'of', 'things']);
expect(h).to.be.a('string');
expect(h).to.not.be.empty;
});
it('should generate the same hash for the same input', () => {
let h1 = hash.sha1('test', { obj: 'test' }, ['list', 'of', 'things']);
let h2 = hash.sha1('test', { obj: 'test' }, ['list', 'of', 'things']);
let h1 = Hash.sha1('test', { obj: 'test' }, ['list', 'of', 'things']);
let h2 = Hash.sha1('test', { obj: 'test' }, ['list', 'of', 'things']);
expect(h1).to.be.a('string');
expect(h2).to.be.a('string');
......@@ -45,8 +40,8 @@ describe('hash utility library', () => {
});
it('should generate the same hash for different order of input', () => {
let h1 = hash.sha1('test', { obj: 'test' }, ['list', 'of', 'things']);
let h2 = hash.sha1('test', ['list', 'of', 'things'], { obj: 'test' });
let h1 = Hash.sha1('test', { obj: 'test' }, ['list', 'of', 'things']);
let h2 = Hash.sha1('test', ['list', 'of', 'things'], { obj: 'test' });
expect(h1).to.be.a('string');
expect(h2).to.be.a('string');
......@@ -54,8 +49,8 @@ describe('hash utility library', () => {
});
it('should not generate the same hash for distinct input', () => {
let h1 = hash.sha1('test', { obj: 'test' }, ['list', 'of', 'things']);
let h2 = hash.sha1('test', { obj: 'test', x: true },
let h1 = Hash.sha1('test', { obj: 'test' }, ['list', 'of', 'things']);
let h2 = Hash.sha1('test', { obj: 'test', x: true },
['list', 'of', 'things']);
expect(h1).to.be.a('string');
......@@ -64,8 +59,8 @@ describe('hash utility library', () => {
});
it('should not generate the same hash for different order in deep lists', () => {
let h1 = hash.sha1('test', { obj: 'test' }, ['list', 'of', 'things']);
let h2 = hash.sha1('test', { obj: 'test' }, ['of', 'list', 'things']);
let h1 = Hash.sha1('test', { obj: 'test' }, ['list', 'of', 'things']);
let h2 = Hash.sha1('test', { obj: 'test' }, ['of', 'list', 'things']);
expect(h1).to.be.a('string');
expect(h2).to.be.a('string');
......
......@@ -20,10 +20,10 @@
'use strict';
const crypto = require('crypto');
import crypto = require('crypto');
class Hash {
sha1(...objects) {
export class Hash {
static sha1(...objects: any[]): string {
let hash = crypto.createHash('sha1');
objects
......@@ -46,5 +46,3 @@ class Hash {
return hash.digest('hex');
}
}
module.exports = new Hash();
......@@ -18,12 +18,4 @@
* along with blendb. If not, see <http://www.gnu.org/licenses/>.
*/
'use strict';
process.env.NODE_ENV = 'test';
global.expect = require('chai').expect;
// Add the ./src directory to require's search path to facilitate import
// modules later on (avoiding the require('../../../../module') problem).
require('app-module-path').addPath(__dirname + '/../src');
--require ./test/global.js
--require ./build/test/global.js
--reporter spec
--ui bdd
--recursive
......@@ -7,3 +7,4 @@
--slow 300
--check-leaks
--globals expect
./build/**/*.spec.js
{
"compilerOptions": {
"pretty": true,
"target": "es5",
"module": "commonjs",
"outDir": "./build",
"noImplicitAny": true,
"removeComments": true,
"preserveConstEnums": true,
"sourceMap": true
},
"exclude": [
"node_modules"
],
"compileOnSave": false
}
{
"globalDependencies": {
"chai": "registry:dt/chai#3.4.0+20160601211834",
"express": "registry:dt/express#4.0.0+20160708185218",
"express-serve-static-core": "registry:dt/express-serve-static-core#4.0.0+20160817171221",
"mime": "registry:dt/mime#0.0.0+20160316155526",
"mocha": "registry:env/mocha#2.2.5+20160723033700",
"node": "registry:env/node#6.0.0+20160813135048",
"serve-static": "registry:dt/serve-static#0.0.0+20160606155157"
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment