Issue #84: Add code docs in Typedoc format

Signed-off-by: Lucas Fernandes de Oliveira's avatarLucas Fernandes de Oliveira <lfoliveira@inf.ufpr.br>
parent 4339c078
Pipeline #15845 passed with stages
in 1 minute and 50 seconds
......@@ -20,3 +20,4 @@
/database/views
/service
schema.sql
/doc/code
......@@ -10,7 +10,8 @@
"show-coverage": "xdg-open coverage/lcov-report/index.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",
"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": {
"type": "git",
......@@ -42,6 +43,7 @@
"raml2html": "^3.0.1",
"supertest": "^3.0.0",
"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";
import { Source } from "../core/source";
import { FilterOperator } from "../core/filter";
import { DataType } from "../common/types";
/** @hidden */
const MDB = require("monetdb")();
/**
* Params required to connect with a MonetDB database and
* to create a MonetAdapter object.
*/
export interface MonetConfig {
/** Database hostname */
host: string;
/** Database port */
port: number;
/** Database name */
dbname: string;
/** Database user */
user: string;
/** Datavase password */
password: string;
}
/**
* Represent the data format returned by MonetDB.
* This interface is used to parse this format to the BlenDB Standart.
*/
interface MonetResult {
/** Query result as a list of values */
data: any[];
/** Meta data of each attribute required. */
structure: {type: string, column: string, index: number}[];
}
/**
* Adapter which connects with a MonetDB database.
*/
export class MonetAdapter extends SQLAdapter {
/** Information used to connect with a MonetDB database. */
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) {
super();
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 {
const query = this.getQueryFromView(view);
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 {
let pool: any = new MDB(this.config);
pool.connect();
......@@ -79,15 +119,31 @@ export class MonetAdapter extends SQLAdapter {
pool.close();
}
/**
* Materialize a given view.
* @param view - View to be materialized.
*/
public materializeView(view: View): boolean {
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 {
const query = this.getQueryFromSource(source, data);
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 {
switch (dt) {
case DataType.DATE:
......@@ -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 {
switch (op) {
case FilterOperator.EQUAL:
......
......@@ -25,18 +25,41 @@ import { FilterOperator } from "../core/filter";
import { Pool, PoolConfig } from "pg";
import { DataType } from "../common/types";
/** Adapter which connects with a PostgreSQL database. */
export class PostgresAdapter extends SQLAdapter {
/** Information used to connect with a PostgreSQL database. */
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) {
super();
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 {
const query = this.getQueryFromView(view);
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{
this.pool.connect((err, client, done) => {
if (err) {
......@@ -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 {
const query = this.getQueryFromSource(source, data);
this.executeQuery(query, cb);
}
/**
* Materialize a given view.
* @param view - View to be materialized.
*/
public materializeView(view: View): boolean {
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 {
switch (dt) {
case DataType.DATE:
......@@ -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 {
switch (op) {
case FilterOperator.EQUAL:
......
This diff is collapsed.
......@@ -24,11 +24,28 @@ import { Source, Field } from "../../core/source";
import { EnumType } from "../../core/enumType";
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{
[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 {
/**
* 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) {
const validador: Valid = {
......
......@@ -22,7 +22,18 @@ import * as express from "express";
import { Request } from "../types";
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 {
/**
* 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) {
let metrics = req.query.metrics.split(",").filter((item: string) => item !== "");
let dimensions = req.query.dimensions.split(",").filter((item: string) => item !== "");
......
......@@ -21,19 +21,52 @@
import * as express from "express";
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 {
/**
* 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) {
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) {
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) {
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) {
res.status(200).json(req.engine.getSourcesDescription());
}
......
......@@ -25,6 +25,11 @@ import { MonetAdapter, MonetConfig } from "../../adapter/monet";
import { PoolConfig } from "pg";
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 {
let parsedConfig: PoolConfig = {
user: config.user,
......@@ -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 {
let parsedConfig: MonetConfig = {
user: config.user,
......
......@@ -22,6 +22,11 @@ import { Engine } from "../../core/engine";
import { ParsedConfig } from "../../util/configParser";
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 {
let engine: Engine = new Engine();
......
......@@ -20,6 +20,10 @@
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 {
const handlers: { [key: string]: express.ErrorRequestHandler } = {
"v1": function(err, req, res, next) {
......
......@@ -18,6 +18,7 @@
* along with blendb. If not, see <http://www.gnu.org/licenses/>.
*/
/** @hidden */
const osprey = require("osprey");
// import controllers
......@@ -25,6 +26,7 @@ import { DataCtrl } from "./controllers/data";
import { CollectCtrl } from "./controllers/collect";
import { EngineCtrl } from "./controllers/engine";
/** @hidden */
export const router = osprey.Router();
router.get("/metrics", EngineCtrl.metrics);
......
......@@ -22,11 +22,26 @@ import * as express from "express";
import { Engine } from "../core/engine";
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 {
/** A engine object. Represents the database in BlenDB perspective. */
engine: Engine;
/** A adapter object. Used to communicate with the database in use. */
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 {
(req: Request, res: express.Response, next: express.NextFunction): void;
}
......@@ -20,13 +20,41 @@
import { View } from "../core/view";
/**
* Operation codes to each allowed operation over a view.
*/
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,
/**
* 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,
/**
* Reduce operation.
* The reduce operation removes irrelevant metrics and
* dimensions and apply clauses. Represents the Projection
* and Selecion operations of Relational Algebra.
*/
REDUCE
}
/**
* Defines how to construct a View with a operation
* and a set of chidren Views.
*/
export interface Operation {
/** Operation code used. */
opcode: Opcode;
/** Set of views required to perform the operation. */
values: View[];
}
......@@ -22,9 +22,16 @@ import { Metric } from "../core/metric";
import { Dimension } from "../core/dimension";
import { Clause } from "../core/clause";
/**
* Internal representation of a query in BlenDB perspective.
*/
export interface Query {
public metrics: Metric[];
public dimensions: Dimension[];
public clauses?: Clause[];
public sort?: (Metric|Dimension)[];
/** Set of metrics of the query. */
metrics: Metric[];
/** Set of dimensions of the query. */
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 @@
* along with blend. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* Available aggregation function to metrics.
*/
export enum AggregationType {
NONE,
SUM,
AVG,
COUNT,
MAX,
MIN
/** Used as error code. So suitable aggregation found. */
NONE,
/** Sum aggregation function. Sum of all registers. */
SUM,
/** Average aggregation function. Average of all registers. */
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 {
NONE,
DAY,
MONTH,
YEAR,
/** Used when there are no relation. The dimension is not a sub dimension. */
NONE,
/**
* 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 {
/** Used as error code when no suitable type is found. */
NONE,
/** Interger type. */
INTEGER,
/** Floating number type. */
FLOAT,
/** String type. */
STRING,
/** Timestamp type. ISO format */
DATE,
/** True/False type. */
BOOLEAN,
ENUMTYPE,
/**
* Enumerable type.
* Custom type, that only accepts a set of previeous defined values.
* Custom enumeration defined in configuration file.
*/
ENUMTYPE
};
......@@ -21,8 +21,32 @@
import { View } from "./view";
import { Source } from "./source";
/**
* Absraction of the SGBD from the BlenDB perspective. Used to
* perform all the operations into the database that the Blendb
* requires. This operations include read and write data.
*/
export abstract class Adapter {
/**
* 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 abstract getDataFromView(view: View, cb: (err: Error, result: any[]) => void): void;
/**
* Materialize a given view.
* @param view - View to be materialized.
*/
public abstract materializeView(view: View): boolean;
/**
* 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 abstract insertIntoSource(source: Source, data: any[], cb: (err: Error, result: any[]) => void): void;
}
......@@ -23,15 +23,25 @@ import { Hash } from "../util/hash";
import { Dimension } from "./dimension";
import { Metric } from "./metric";
/** Parameters used to create a Clause object. */
export interface ClauseOptions {
/** Set of filters that form the clause. */
filters: Filter[];
}
/** Set of restrictions applied to a query united by the operator OR. */
export class Clause {
/** Hash of components that unique identify the clause. */
public readonly id: string;
/** Set of filters the form the clause. */
public readonly filters: Filter[];
/** Set of attributes affected by this clause. */
public readonly targets: (Metric|Dimension)[];
/**
* Create a clause object.
* @param options - Parameters required to create a clause object.
*/
constructor (options: ClauseOptions) {
this.filters = options.filters.map((i) => i);
const t = this.filters.map((i) => i.target).sort((a, b) => {
......@@ -52,6 +62,14 @@ export class Clause {
this.id = Hash.sha1(filtersIds.sort());
}
/**
* Checks if the targets of this clause is a sub set of
* the given coverage set.
* In other words, this clause could be applied to a view
* which has the coverage set as set of metrics and dimensions
* @param coverage - Set of attributes which will be verified if
* contain all targets in the clause.
*/
public isCovered(coverage: (Metric|Dimension)[]): boolean {
return this.targets.every((i) => coverage.some((j) => i.name === j.name));
}
......
......@@ -21,31 +21,64 @@
import { RelationType, DataType } from "../common/types";
import { EnumType } from "./enumType";
/** Parameters used to create a Dimension object. */
export interface DimensionOptions {
/** Dimension name. */
name: string;
/** Dimension data type. */
dataType: DataType;
/** Parent dimension, in case this dimension is a sub dimenion. */
parent?: Dimension;
/** Relationship with the parent. */
relation?: RelationType;
/** Breif description of what this dimension represents. */
description?: string;
/* Enumerable type name, used if data type is enumerable type. */
enumType?: string;
}
/**
* Parameters used to define dimension object in the configuration file.
* Also the string description of a dimension.
*/
export interface DimensionStrOptions {
/** Dimension name. */
name: string;
/** Dimension data type. */
dataType: string;
/** Parent dimension, in case this dimension is a sub dimenion. */
parent?: string;
/** Relationship with the parent. */
relation?: string;
/** Breif description of what this dimension represents. */
description?: string;
}
/**
* One attribute of database that can be read.
* A dimension defines a aspect or characteristic of the data.
* Used in a query as a desired information and is separated from
* the metrics because this two types of attributes behave differently
* in the query. While dimensions are grouped, metrics are aggregated.
*/
export class Dimension {
/** Dimension name. */
public readonly name: string;
/** Dimenion data type. */
public readonly dataType: DataType;
/** Parent dimension, in case this dimension is a sub dimenion. */
public readonly parent: Dimension;
/** Relationship with the parent. */
public readonly relation: RelationType;
/** Breif description of what this dimension represents. */
public readonly description: string;
/* Enumerable type name, used if data type is enumerable type. */
public readonly enumType: string;
/**
* Creates a dimension.
* @param options - Parameters required to create a dimension.
*/
constructor(options: DimensionOptions) {
this.name = options.name;
this.dataType = options.dataType;
......@@ -55,6 +88,10 @@ export class Dimension {
this.enumType = (options.enumType) ? (options.enumType) : "";
}
/**
* Creates a object with the same options used to create this
* dimension as strings. Used to inform the API users.
*/
public strOptions(): DimensionStrOptions {
if (this.relation === RelationType.NONE) {
return {
......@@ -74,6 +111,10 @@ export class Dimension {
}
}
/**
* Parse a string to enum(Relation Type).
* @param r - Relation in string format.
*/
public static parseRelationType(r: string): RelationType {
switch (r) {
case "day":
......@@ -87,6 +128,10 @@ export class Dimension {
}
}