Commit fa0142b6 authored by Lucas Fernandes de Oliveira's avatar Lucas Fernandes de Oliveira

Merge branch 'issue/84' into 'develop'

Issue #84: Add code docs in Typedoc format

See merge request !66
parents 4339c078 433595a1
Pipeline #15848 passed with stages
in 52 seconds
...@@ -20,3 +20,4 @@ ...@@ -20,3 +20,4 @@
/database/views /database/views
/service /service
schema.sql schema.sql
/doc/code
...@@ -10,7 +10,8 @@ ...@@ -10,7 +10,8 @@
"show-coverage": "xdg-open coverage/lcov-report/index.html", "show-coverage": "xdg-open coverage/lcov-report/index.html",
"doc-api": "raml2html -i specs/blendb-api-v1.raml -o doc/api-v1-reference.html", "doc-api": "raml2html -i specs/blendb-api-v1.raml -o doc/api-v1-reference.html",
"schema": "env $(cat config/config.env ) ts-node scripts/schema.ts config/config.yaml schema.sql", "schema": "env $(cat config/config.env ) ts-node scripts/schema.ts config/config.yaml schema.sql",
"service": "./scripts/service.sh" "service": "./scripts/service.sh",
"doc-code": "typedoc --mode 'file' --module 'commonjs' --target 'ES6' --ignoreCompilerErrors --exclude '**/*.spec.ts' --out 'doc/code' 'src'"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
...@@ -42,6 +43,7 @@ ...@@ -42,6 +43,7 @@
"raml2html": "^3.0.1", "raml2html": "^3.0.1",
"supertest": "^3.0.0", "supertest": "^3.0.0",
"tslint": "^3.15.1", "tslint": "^3.15.1",
"tslint-stylish": "^2.1.0-beta" "tslint-stylish": "^2.1.0-beta",
"typedoc": "^0.11.1"
} }
} }
...@@ -23,33 +23,73 @@ import { View } from "../core/view"; ...@@ -23,33 +23,73 @@ import { View } from "../core/view";
import { Source } from "../core/source"; import { Source } from "../core/source";
import { FilterOperator } from "../core/filter"; import { FilterOperator } from "../core/filter";
import { DataType } from "../common/types"; import { DataType } from "../common/types";
/** @hidden */
const MDB = require("monetdb")(); const MDB = require("monetdb")();
/**
* Params required to connect with a MonetDB database and
* to create a MonetAdapter object.
*/
export interface MonetConfig { export interface MonetConfig {
/** Database hostname */
host: string; host: string;
/** Database port */
port: number; port: number;
/** Database name */
dbname: string; dbname: string;
/** Database user */
user: string; user: string;
/** Datavase password */
password: string; password: string;
} }
/**
* Represent the data format returned by MonetDB.
* This interface is used to parse this format to the BlenDB Standart.
*/
interface MonetResult { interface MonetResult {
/** Query result as a list of values */
data: any[]; data: any[];
/** Meta data of each attribute required. */
structure: {type: string, column: string, index: number}[]; structure: {type: string, column: string, index: number}[];
} }
/**
* Adapter which connects with a MonetDB database.
*/
export class MonetAdapter extends SQLAdapter { export class MonetAdapter extends SQLAdapter {
/** Information used to connect with a MonetDB database. */
private config: MonetConfig; private config: MonetConfig;
/**
* Creates a new adapter with the database connection configuration.
* @param conf - The information required to create a connection with
* the database.
*/
constructor (conf: MonetConfig) { constructor (conf: MonetConfig) {
super(); super();
this.config = conf; this.config = conf;
} }
/**
* Asynchronously reads all data from given view.
* In other words perform a SELECT query.
* @param view - "Location" from all data should be read.
* @param cb - Callback function which contains the data read.
* @param cb.error - Error information when the method fails.
* @param cb.result - Data got from view.
*/
public getDataFromView(view: View, cb: (error: Error, result?: any[]) => void): void { public getDataFromView(view: View, cb: (error: Error, result?: any[]) => void): void {
const query = this.getQueryFromView(view); const query = this.getQueryFromView(view);
this.executeQuery(query, cb); this.executeQuery(query, cb);
} }
/**
* Asynchronously executes a query and get its result.
* @param query - Query (SQL format) to be executed.
* @param cb - Callback function which contains the data read.
* @param cb.error - Error information when the method fails.
* @param cb.result - Query result.
*/
private executeQuery(query: string, cb: (error: Error, result?: any[]) => void): void { private executeQuery(query: string, cb: (error: Error, result?: any[]) => void): void {
let pool: any = new MDB(this.config); let pool: any = new MDB(this.config);
pool.connect(); pool.connect();
...@@ -79,15 +119,31 @@ export class MonetAdapter extends SQLAdapter { ...@@ -79,15 +119,31 @@ export class MonetAdapter extends SQLAdapter {
pool.close(); pool.close();
} }
/**
* Materialize a given view.
* @param view - View to be materialized.
*/
public materializeView(view: View): boolean { public materializeView(view: View): boolean {
return false; return false;
} }
/**
* Asynchronously insert one register into a given Source.
* @param source - Insertion "location".
* @param cb - Callback function which contains the query result.
* @param cb.error - Error information when the method fails.
* @param cb.result - Query result.
*/
public insertIntoSource(source: Source, data: any[], cb: (err: Error, result: any[]) => void): void { public insertIntoSource(source: Source, data: any[], cb: (err: Error, result: any[]) => void): void {
const query = this.getQueryFromSource(source, data); const query = this.getQueryFromSource(source, data);
this.executeQuery(query, cb); this.executeQuery(query, cb);
} }
/**
* Cast BlenDB data types to be used in MonetDB queries.
* @param quotedValue - SQL query attribute wrapped by quotes.
* @param dt - Attribute data type.
*/
protected typeCast(quotedValue: string, dt: DataType): string { protected typeCast(quotedValue: string, dt: DataType): string {
switch (dt) { switch (dt) {
case DataType.DATE: case DataType.DATE:
...@@ -101,6 +157,12 @@ export class MonetAdapter extends SQLAdapter { ...@@ -101,6 +157,12 @@ export class MonetAdapter extends SQLAdapter {
} }
} }
/**
* Translate filter operator to be used in MonetDB queries.
* @param lSide - Operation left side operator.
* @param rSide - Operation right side operator.
* @param op - Operation to be performed.
*/
protected applyOperator(lSide: string, rSide: string, op: FilterOperator): string { protected applyOperator(lSide: string, rSide: string, op: FilterOperator): string {
switch (op) { switch (op) {
case FilterOperator.EQUAL: case FilterOperator.EQUAL:
......
...@@ -25,18 +25,41 @@ import { FilterOperator } from "../core/filter"; ...@@ -25,18 +25,41 @@ import { FilterOperator } from "../core/filter";
import { Pool, PoolConfig } from "pg"; import { Pool, PoolConfig } from "pg";
import { DataType } from "../common/types"; import { DataType } from "../common/types";
/** Adapter which connects with a PostgreSQL database. */
export class PostgresAdapter extends SQLAdapter { export class PostgresAdapter extends SQLAdapter {
/** Information used to connect with a PostgreSQL database. */
private pool: Pool; private pool: Pool;
/**
* Creates a new adapter with the database connection configuration.
* @param config - The information required to create a connection with
* the database.
*/
constructor (config: PoolConfig) { constructor (config: PoolConfig) {
super(); super();
this.pool = new Pool(config); this.pool = new Pool(config);
} }
/**
* Asynchronously reads all data from given view.
* In other words perform a SELECT query.
* @param view - "Location" from all data should be read.
* @param cb - Callback function which contains the data read.
* @param cb.error - Error information when the method fails.
* @param cb.result - Data got from view.
*/
public getDataFromView(view: View, cb: (error: Error, result?: any[]) => void): void { public getDataFromView(view: View, cb: (error: Error, result?: any[]) => void): void {
const query = this.getQueryFromView(view); const query = this.getQueryFromView(view);
this.executeQuery(query, cb); this.executeQuery(query, cb);
} }
/**
* Asynchronously executes a query and get its result.
* @param query - Query (SQL format) to be executed.
* @param cb - Callback function which contains the data read.
* @param cb.error - Error information when the method fails.
* @param cb.result - Query result.
*/
private executeQuery(query: string, cb: (err: Error, result?: any[]) => void): void{ private executeQuery(query: string, cb: (err: Error, result?: any[]) => void): void{
this.pool.connect((err, client, done) => { this.pool.connect((err, client, done) => {
if (err) { if (err) {
...@@ -50,15 +73,32 @@ export class PostgresAdapter extends SQLAdapter { ...@@ -50,15 +73,32 @@ export class PostgresAdapter extends SQLAdapter {
}); });
}); });
} }
/**
* Asynchronously insert one register into a given Source.
* @param source - Insertion "location".
* @param cb - Callback function which contains the query result.
* @param cb.error - Error information when the method fails.
* @param cb.result - Query result.
*/
public insertIntoSource(source: Source, data: any[], cb: (err: Error, result?: any[]) => void): void { public insertIntoSource(source: Source, data: any[], cb: (err: Error, result?: any[]) => void): void {
const query = this.getQueryFromSource(source, data); const query = this.getQueryFromSource(source, data);
this.executeQuery(query, cb); this.executeQuery(query, cb);
} }
/**
* Materialize a given view.
* @param view - View to be materialized.
*/
public materializeView(view: View): boolean { public materializeView(view: View): boolean {
return false; return false;
} }
/**
* Cast BlenDB data types to be used in PostgreSQL queries.
* @param quotedValue - SQL query attribute wrapped by quotes.
* @param dt - Attribute data type.
*/
protected typeCast(quotedValue: string, dt: DataType): string { protected typeCast(quotedValue: string, dt: DataType): string {
switch (dt) { switch (dt) {
case DataType.DATE: case DataType.DATE:
...@@ -72,6 +112,12 @@ export class PostgresAdapter extends SQLAdapter { ...@@ -72,6 +112,12 @@ export class PostgresAdapter extends SQLAdapter {
} }
} }
/**
* Translate filter operator to be used in PostgreSQL queries.
* @param lSide - Operation left side operator.
* @param rSide - Operation right side operator.
* @param op - Operation to be performed.
*/
protected applyOperator(lSide: string, rSide: string, op: FilterOperator): string { protected applyOperator(lSide: string, rSide: string, op: FilterOperator): string {
switch (op) { switch (op) {
case FilterOperator.EQUAL: case FilterOperator.EQUAL:
......
This diff is collapsed.
...@@ -24,11 +24,28 @@ import { Source, Field } from "../../core/source"; ...@@ -24,11 +24,28 @@ import { Source, Field } from "../../core/source";
import { EnumType } from "../../core/enumType"; import { EnumType } from "../../core/enumType";
import { DataType } from "../../common/types"; import { DataType } from "../../common/types";
/**
* Dictionary indexed by a type name which return a
* validation function that returns true if the
* objetct is a valid object of that type
* or false otherwise.
*/
interface Valid{ interface Valid{
[key: string]: (value: any) => boolean; [key: string]: (value: any) => boolean;
} }
/**
* Constroller responsable for collect part from the API. In other
* words, controller responsable for inserting data in BlenDB.
*/
export class CollectCtrl { export class CollectCtrl {
/**
* Route that validates and insert data.
* @param req - Object with request information
* @param res - Object used to create and send the response
* @param next - Call next middleware or controller. Not used but required
* by typescript definition of route.
*/
public static write(req: Request, res: express.Response, next: express.NextFunction) { public static write(req: Request, res: express.Response, next: express.NextFunction) {
const validador: Valid = { const validador: Valid = {
......
...@@ -22,7 +22,18 @@ import * as express from "express"; ...@@ -22,7 +22,18 @@ import * as express from "express";
import { Request } from "../types"; import { Request } from "../types";
import { Query } from "../../common/query"; import { Query } from "../../common/query";
/**
* Constroller responsable for data part from the API. In other
* words, controller responsable for reading data in BlenDB.
*/
export class DataCtrl { export class DataCtrl {
/**
* Route that validates a query and returns the query data.
* @param req - Object with request information
* @param res - Object used to create and send the response
* @param next - Call next middleware or controller. Not used but required
* by typescript definition of route.
*/
public static read(req: Request, res: express.Response, next: express.NextFunction) { public static read(req: Request, res: express.Response, next: express.NextFunction) {
let metrics = req.query.metrics.split(",").filter((item: string) => item !== ""); let metrics = req.query.metrics.split(",").filter((item: string) => item !== "");
let dimensions = req.query.dimensions.split(",").filter((item: string) => item !== ""); let dimensions = req.query.dimensions.split(",").filter((item: string) => item !== "");
......
...@@ -21,19 +21,52 @@ ...@@ -21,19 +21,52 @@
import * as express from "express"; import * as express from "express";
import { Request } from "../types"; import { Request } from "../types";
/**
* Constroller responsable for the static part from the API. In other
* words, controller responsable for return the meta data stored in the
* engine object that API users can use to create queries.
*/
export class EngineCtrl { export class EngineCtrl {
/**
* Route that returns the list of available metrics.
* @param req - Object with request information
* @param res - Object used to create and send the response
* @param next - Call next middleware or controller. Not used but required
* by typescript definition of route.
*/
public static metrics(req: Request, res: express.Response, next: express.NextFunction) { public static metrics(req: Request, res: express.Response, next: express.NextFunction) {
res.status(200).json(req.engine.getMetricsDescription()); res.status(200).json(req.engine.getMetricsDescription());
} }
/**
* Route that returns the list of available dimensions.
* @param req - Object with request information
* @param res - Object used to create and send the response
* @param next - Call next middleware or controller. Not used but required
* by typescript definition of route.
*/
public static dimensions(req: Request, res: express.Response, next: express.NextFunction) { public static dimensions(req: Request, res: express.Response, next: express.NextFunction) {
res.status(200).json(req.engine.getDimensionsDescription()); res.status(200).json(req.engine.getDimensionsDescription());
} }
/**
* Route that returns the list of available enumerable types.
* @param req - Object with request information
* @param res - Object used to create and send the response
* @param next - Call next middleware or controller. Not used but required
* by typescript definition of route.
*/
public static enumTypes(req: Request, res: express.Response, next: express.NextFunction) { public static enumTypes(req: Request, res: express.Response, next: express.NextFunction) {
res.status(200).json(req.engine.getEnumTypesDescription()); res.status(200).json(req.engine.getEnumTypesDescription());
} }
/**
* Route that returns the list of available data sources for insertion.
* @param req - Object with request information
* @param res - Object used to create and send the response
* @param next - Call next middleware or controller. Not used but required
* by typescript definition of route.
*/
public static sources(req: Request, res: express.Response, next: express.NextFunction) { public static sources(req: Request, res: express.Response, next: express.NextFunction) {
res.status(200).json(req.engine.getSourcesDescription()); res.status(200).json(req.engine.getSourcesDescription());
} }
......
...@@ -25,6 +25,11 @@ import { MonetAdapter, MonetConfig } from "../../adapter/monet"; ...@@ -25,6 +25,11 @@ import { MonetAdapter, MonetConfig } from "../../adapter/monet";
import { PoolConfig } from "pg"; import { PoolConfig } from "pg";
import { Connection } from "../../util/configParser"; import { Connection } from "../../util/configParser";
/**
* Creates a PostgreSQL adapter and middleware that
* inserts the adapter into the request objects.
* @param config - Parameters required to connect in database.
*/
export function PostgresMw(config: Connection): Middleware { export function PostgresMw(config: Connection): Middleware {
let parsedConfig: PoolConfig = { let parsedConfig: PoolConfig = {
user: config.user, user: config.user,
...@@ -43,6 +48,11 @@ export function PostgresMw(config: Connection): Middleware { ...@@ -43,6 +48,11 @@ export function PostgresMw(config: Connection): Middleware {
} }
/**
* Creates a MonetDB adapter and middleware that
* inserts the adapter into the request objects.
* @param config - Parameters required to connect in database.
*/
export function MonetMw(config: Connection): Middleware { export function MonetMw(config: Connection): Middleware {
let parsedConfig: MonetConfig = { let parsedConfig: MonetConfig = {
user: config.user, user: config.user,
......
...@@ -22,6 +22,11 @@ import { Engine } from "../../core/engine"; ...@@ -22,6 +22,11 @@ import { Engine } from "../../core/engine";
import { ParsedConfig } from "../../util/configParser"; import { ParsedConfig } from "../../util/configParser";
import { Middleware } from "../types"; import { Middleware } from "../types";
/**
* Creates a engine and middleware that
* inserts the engine into the request objects.
* @param config - Parsed database schema.
*/
export function EngineMw (config: ParsedConfig): Middleware { export function EngineMw (config: ParsedConfig): Middleware {
let engine: Engine = new Engine(); let engine: Engine = new Engine();
......
...@@ -20,6 +20,10 @@ ...@@ -20,6 +20,10 @@
import * as express from "express"; import * as express from "express";
/**
* Creates a middleware to handle errors proper to each API version.
* @param config - API version.
*/
export function ErrorMw(config: string): express.ErrorRequestHandler { export function ErrorMw(config: string): express.ErrorRequestHandler {
const handlers: { [key: string]: express.ErrorRequestHandler } = { const handlers: { [key: string]: express.ErrorRequestHandler } = {
"v1": function(err, req, res, next) { "v1": function(err, req, res, next) {
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
* along with blendb. If not, see <http://www.gnu.org/licenses/>. * along with blendb. If not, see <http://www.gnu.org/licenses/>.
*/ */
/** @hidden */
const osprey = require("osprey"); const osprey = require("osprey");
// import controllers // import controllers
...@@ -25,6 +26,7 @@ import { DataCtrl } from "./controllers/data"; ...@@ -25,6 +26,7 @@ import { DataCtrl } from "./controllers/data";
import { CollectCtrl } from "./controllers/collect"; import { CollectCtrl } from "./controllers/collect";
import { EngineCtrl } from "./controllers/engine"; import { EngineCtrl } from "./controllers/engine";
/** @hidden */
export const router = osprey.Router(); export const router = osprey.Router();
router.get("/metrics", EngineCtrl.metrics); router.get("/metrics", EngineCtrl.metrics);
......
...@@ -22,11 +22,26 @@ import * as express from "express"; ...@@ -22,11 +22,26 @@ import * as express from "express";
import { Engine } from "../core/engine"; import { Engine } from "../core/engine";
import { Adapter} from "../core/adapter"; import { Adapter} from "../core/adapter";
/**
* Extension of Express requests that suports the addition
* of an engine and an adapter.
* This extension is required because some Middlewares
* add some objetcs, in this case metrics and dimensions,
* to the Request object. To typescript compiler do not
* return a error the extension must be made.
*/
export interface Request extends express.Request { export interface Request extends express.Request {
/** A engine object. Represents the database in BlenDB perspective. */
engine: Engine; engine: Engine;
/** A adapter object. Used to communicate with the database in use. */
adapter: Adapter; adapter: Adapter;
} }
/**
* Extension Middleware function of ExpressJS Module.
* Uses the custom Request object and is used to define
* the middlewares of BlenDB API.
*/
export interface Middleware { export interface Middleware {
(req: Request, res: express.Response, next: express.NextFunction): void; (req: Request, res: express.Response, next: express.NextFunction): void;
} }
...@@ -20,13 +20,41 @@ ...@@ -20,13 +20,41 @@
import { View } from "../core/view"; import { View } from "../core/view";
/**
* Operation codes to each allowed operation over a view.
*/
export enum Opcode { export enum Opcode {
/**
* Push operation.
* This operation means that the view is materialized.
* This also means that there are no need to create it
* using other views.
* And also means that this view is a valid data location.
*/
PUSH, PUSH,
/**
* Join operation.
* The view will be created using a set of others view.
* This operation is equivalent a INNER JOIN of SQL
* or as close as possible of JOIN.
*/
JOIN, JOIN,
/**
* Reduce operation.
* The reduce operation removes irrelevant metrics and
* dimensions and apply clauses. Represents the Projection
* and Selecion operations of Relational Algebra.
*/
REDUCE REDUCE
} }
/**
* Defines how to construct a View with a operation
* and a set of chidren Views.
*/
export interface Operation { export interface Operation {
/** Operation code used. */
opcode: Opcode; opcode: Opcode;
/** Set of views required to perform the operation. */
values: View[]; values: View[];
} }
...@@ -22,9 +22,16 @@ import { Metric } from "../core/metric"; ...@@ -22,9 +22,16 @@ import { Metric } from "../core/metric";
import { Dimension } from "../core/dimension"; import { Dimension } from "../core/dimension";
import { Clause } from "../core/clause"; import { Clause } from "../core/clause";
/**
* Internal representation of a query in BlenDB perspective.
*/
export interface Query { export interface Query {
public metrics: Metric[]; /** Set of metrics of the query. */
public dimensions: Dimension[]; metrics: Metric[];
public clauses?: Clause[]; /** Set of dimensions of the query. */
public sort?: (Metric|Dimension)[]; dimensions: Dimension[];
/** Set of clauses of the query. */
clauses?: Clause[];
/** List of metrics and dimensions to sort the query. */
sort?: (Metric|Dimension)[];
} }
...@@ -18,28 +18,71 @@ ...@@ -18,28 +18,71 @@
* along with blend. If not, see <http://www.gnu.org/licenses/>. * along with blend. If not, see <http://www.gnu.org/licenses/>.
*/ */
/**
* Available aggregation function to metrics.
*/
export enum AggregationType { export enum AggregationType {
NONE, /** Used as error code. So suitable aggregation found. */
SUM, NONE,
AVG, /** Sum aggregation function. Sum of all registers. */
COUNT, SUM,
MAX, /** Average aggregation function. Average of all registers. */
MIN AVG,
/** Count agggreation function. Count the number of registers. */
COUNT,
/** Maximum aggregation function. The biggest value of all registers. */
MAX,
/** Minimum aggregation function. The smallest value of all registers. */
MIN
}; };
/**
* Available relationships between sub dimensions and its parents.
*/
export enum RelationType { export enum RelationType {
NONE, /** Used when there are no relation. The dimension is not a sub dimension. */
DAY, NONE,
MONTH, /**
YEAR, * Day relation.
* The parent is a timestamp and the dimension is only the day of
* the timestamp.
*/
DAY,
/**
* Month relation.
* The parent is a timestamp and the dimension is only the month of
* the timestamp.
*/
MONTH,
/**
* Year relation.
* The parent is a timestamp and the dimension is only the year of
* the timestamp.
*/
YEAR,
}; };
/**
* Available data types for metrics, dimensions and source members.
* In other words types that BlenDB can handle.
*/
export enum DataType { export enum DataType {
/** Used as error code when no suitable type is found. */
NONE,