Quick Start

vMagic is a RESTFul framework for NodeJS application.

Installation

Step One

npm install vmagic-cli

vmagic-cli new <NameProject>

Project Structure

Project Name
    src
        Component
        Config
        Controller
        Model
    test

Step Two

  • Enter in the <NameProject> && npm install
  • Set your IP / PORT in your file init.js
  • Execute node init.js to start server.

Config

All project configurations you can find here

core.json you might:

  • Configure the database connection.
  • Configure the Sender email.
  • Configure a default path to save the images whenever client send an media's upload.

MySQL Connection

"dataSources" : {
	"default" : {
		"dataSource" : "MySQL",
		"host" : "127.0.0.1",
		"port" : 3306,
		"user" : "root",
		"password" : "",
		"database" : "dbname",
        "connectionLimit" : 50
	},
	"test" : {
		"dataSource" : "MySQL",
		"host" : "127.0.0.1",
		"port" : 3306,
		"user" : "root",
		"password" : "",
		"database" : "dbname_test",
        "connectionLimit" : 50
	}
}
PostgreSQL Connection

"dataSources" : {
	"default" : {
		"dataSource" : "PgSQL",
		"host" : "127.0.0.1",
		"port" : 5432,
		"user" : "root",
		"password" : "",
		"database" : "dbname",
        "connectionLimit" : 50
	},
	"test" : {
		"dataSource" : "PgSQL",
		"host" : "127.0.0.1",
		"port" : 5432,
		"user" : "root",
		"password" : "",
		"database" : "dbname_test",
        "connectionLimit" : 50
	}
}

Controller

Each /resource in your API is referenced by one Controller.

For example: If you create an UsersController, Than you available a resource /Users that you can call It as http://ip:port/Users.

It's sample show you how to work with request GET.
"use strict";
const AppController = require("./AppController");
class UsersController extends AppController {

    init() {
        this.model([
            "User"
        ]);
    }

    //http://127.0.0.1:5555/Users
    get() {
        //To get query params.
        const query = this.query;

        return {"message" : "Test request"}; //Response to the client who sent request.
    }
}
module.exports = UsersController;
Request POST.
"use strict";
const AppController = require("./AppController");
class UsersController extends AppController {

    init() {
        this.model([
            "User"
        ]);
    }

    //http://127.0.0.1:5555/Users
    post() {
        //To get payload.
        const payload = this.payload;

        return {"message" : "Test request"}; //Response to the client who sent request.
    }
}
module.exports = UsersController;
Request PUT.
"use strict";
const AppController = require("./AppController");
class UsersController extends AppController {

    init() {
        this.model([
            "User"
        ]);
    }

    //http://127.0.0.1:5555/Users/id
    put() {
        //To get payload.
        const payload = this.payload;
        //To get param id.
        const id = this.id;

        return {"message" : "Test request"}; //Response to the client who sent request.
    }
}
module.exports = UsersController;
Request DELETE.
"use strict";
const AppController = require("./AppController");
class UsersController extends AppController {

    init() {
        this.model([
            "User"
        ]);
    }

    //http://127.0.0.1:5555/Users/id
    delete() {
        //To get payload.
        const payload = this.payload;
        //To get param id.
        const id = this.id;

        return {"message" : "Test request"}; //Response to the client who sent request.
    }
}
module.exports = UsersController;
It's sample show you how to work with a custom action.
"use strict";
const AppController = require("./AppController");
class UsersController extends AppController {

    init() {
        this.model([
            "User"
        ]);
    }

    //http://127.0.0.1:5555/Users/customAction
    customAction() {
        //To get payload.
        const payload = this.payload;
        //To get query params.
        const query = this.query;

        return {"message" : "Test request"}; //Response to the client who sent request.
    }
}
module.exports = UsersController;
It's sample show you how to work with the files from form-data.
"use strict";
const AppController = require("./AppController");
class UsersController extends AppController {

    init() {
        this.model([
            "User"
        ]);
    }

    //http://127.0.0.1:5555/Users
    async post(request) {
        //To get form-data values.
        const formData = await this.getFormData(request);

        return {"message" : "Test request"}; //Response to the client who sent request.
    }
}
module.exports = UsersController;

Model

Each model is a reference from database table.

Each model is a reference from database table.

INSERT

INSERT INTO <table_name> VALUES ($1, $2).
async post() {
    let response = null;
    try {
        const res = await this.User.save({
            "name": "Diego Vargas",
            "age": 28
        });
        response = res;
    } catch (err) {
        if (!this.statusCode) {
            this.statusCode = 500;
        }
        response = {
            "error": {
                "statusCode": this.statusCode,
                "title": "Failed",
                "detail": err.message
            }
        }
    }
    
    return response; //Response to the client who sent request.
}

UPDATE

UPDATE <table_name> SET <field> = ? WHERE id = ?
async put() {
    let response = null;
    try {

        const res = await this.User.update({
            "name": "Diego Vargas Updated"
        }, { "id" : 1 });

        response = res;
    } catch (err) {
        if (!this.statusCode) {
            this.statusCode = 500;
        }
        response = {
            "error": {
                "statusCode": this.statusCode,
                "title": "Failed",
                "detail": err.message
            }
        }
    }
    
    return response; //Response to the client who sent request.
}

DELETE

DELETE FROM <table_name> WHERE id = ?
async delete() {
    let response = null;
    try {

        const res = await this.User.delete({ "id" : 1 });

        response = res;
    } catch (err) {
        if (!this.statusCode) {
            this.statusCode = 500;
        }
        response = {
            "error": {
                "statusCode": this.statusCode,
                "title": "Failed",
                "detail": err.message
            }
        }
    }
    
    return response; //Response to the client who sent request.
}

FIND ALL

It's sample show you how to get query with the JOIN and operations as OR, IN, EQUALS...
async get() {
    let response = null;
    try {

        const params = {
            "conditions": [
                {
                    "id": 1,
                    "operation": "="
                },
                {
                    "code": [
                        "code1",
                        "code2",
                        "code3",
                    ],
                    "operation": "IN"
                },
                {
                    "tag": [
                        "tag1",
                        "tag2",
                        "tag3",
                    ],
                    "operation": "OR"
                }
            ],
            "join": [
                { "INNER": { "table": "company", "on": "company.id = user.company_id" } }
            ],
            "fields": [
                "user.*",
                "company.trade_name"
            ],
            "order": [
                "user.id"
            ]
        }

        const res = await this.User.findAll(params);

        response = res;
    } catch (err) {
        if (!this.statusCode) {
            this.statusCode = 500;
        }
        response = {
            "error": {
                "statusCode": this.statusCode,
                "title": "Failed",
                "detail": err.message
            }
        }
    }
    
    return response; //Response to the client who sent request.
}

FIND BY

SELECT * FROM <table_name> WHERE <field> = ?
async findBy() {
    let response = null;
    try {

        const res = await this.User.findBy({ "id": 1 });

        response = res;
    } catch (err) {
        if (!this.statusCode) {
            this.statusCode = 500;
        }
        response = {
            "error": {
                "statusCode": this.statusCode,
                "title": "Failed",
                "detail": err.message
            }
        }
    }
    
    return response; //Response to the client who sent request.
}

Validations

init() {
    //Table name
    this.useTable = "public.user";
    this.validate([
        {
            "name": {
                "rule": "notEmpty",
                "message": "field name cannot be empty."
            }
        },
        {
            "email": {
                "rule": "notEmpty",
                "message": "field email cannot be empty."
            }
        },
        {
            "password": {
                "rule": "notEmpty",
                "message": "field password cannot be empty."
            }
        }
    ]);
}

Custom query

'use strict';
const AppModel = require('./AppModel');

class User extends AppModel {

    init() {
        //Table name
        this.useTable = "public.user";
        this.pgsql = this.component("PgSQL");
    }

    example() {
        const that = this;

        return new Promise((resolve,reject) => {
            this.pgsql.connect().
                then(connection => {
                    connection.query("SELECT * FROM <table_name> WHERE name = $1 and permission = $2",["vMagic", "ADMINISTRATOR"], (err,res) => {
                        that.pgsql.close(connection);
                        if (err) {
                            reject(err);

                            return;
                        }

                        resolve(res);
                    });
                }).
                catch(err => {
                    reject(err);
                });
        });
    }
}
module.exports = User;