1.2.11 • Published 4 years ago

@dellasera/plugdo-mvc v1.2.11

Weekly downloads
58
License
MIT
Repository
-
Last release
4 years ago

plugdo-mvc

A module that implements mvc, webapi and realtime web software architecture. It help you focus in the implementation of the business logic, instance of writing express routing each time you need a new section.

Compatibility: Node.js version 6+ and Express version 4+

Install with npm:

npm install @dellasera/plugdo-mvc

IMPORTANT Directory Structure

In order to found the components, a directory structure must be created as follow:

--content
- source
--source/controllers
--source/dependencies
--source/webapi
--source/realtime
--views

Directories definitions:

content: you will add the css, js, font files.
source: the MVC logic will be added here.
source/controllers: You can create directories and js files, the js files will have the controller logic.
source/dependencies: You can create directories and js files, the js files will have the services, utilities, classes, helper, etc.
source/webapi: You can create directories and js files, the js files will have the web api logic.
source/realtime: You can create directories and js files, the js files will have the realtime channel logic.
views: the EJS views will be added here.

IMPORTANT ERROR and 404 Not Found

The error and 404 not found are returned in XML format, because the PLUGDO MVC is a mix between Web Page and Web API, the general response for erros and 404 not found was changed to XML format.

PLUGDO MVC

Controllers

Create a new controller is easy, just add a new file in source/controllers, plugdo MVC will load the new file after initialization, the loading is not automatic. You must restart the nodejs execution.

First, start the plugdo-mvc server. (use nodemon for development is recommended)

const mvc = require("@dellasera/plugdo-mvc").mvc();
const path = require("path");
const port = process.env.PORT === undefined ? 3000 : process.env.PORT;

mvc.start(port, path.resolve(__dirname)); // The port and root path is required

Create a controller, adding a file in source/controllers. The controller must return a json model. An example is:

mvc.controller({
    name: "customer",
    action: "index"
}, function (req) {
    return {
        title: "Customer Home Page",
        message: "Welcome to our web page!"
    };
});

The expected URL will be: http://domain.com/customer/index

You can also replace the default URL format as name/action, just including the path: "/new-path". Also a dependency injection simple way is available to pass the dependencies previously defined.

mvc.controller({
    name: "customer",
    action: "index",
    path: "/new-path"
}, "customerService", function (req, customerService) {
    return customerService.getAll();
});

The expected URL will be: http://domain.com/new-path

The default view to be required is:

views/customer/index.ejs

If you need to use another file, skiping the default, just add the view option as follow:

mvc.controller({
    name: "customer",
    action: "index",
    view: "customer-index.ejs" // Also a directory, view: "customer/index/home.ejs"
}, function (req) {
    return {
        title: "Customer Home Page",
        message: "Welcome to our web page!"
    };
});

Dependencies

Create a new dependency is easy, just add a new file in source/dependencies, plugdo MVC will load the new file after initialization, the loading is not automatic. You must restart the nodejs execution.

mvc.dependencies.customerService = {
    "getAll":  function () {
        return [
            {
                name: "Marco A. Castillo",
                country: "Panama"
            },
            {
                name: "Rafael Della Sera",
                country: "Panama"
            }
        ]
    }
};

Added in version 1.0.31 the mvc.service() fnction. This new function allow you to add services or collect services. The same example above:

mvc.service("customerService", {
    "getAll":  function () {
        return [
            {
                name: "Marco A. Castillo",
                country: "Panama"
            },
            {
                name: "Rafael Della Sera",
                country: "Panama"
            }
        ]
    }
});

Web API

Create a new webapi is easy, just add a new file in source/webapi, plugdo MVC will load the new file after initialization, the loading is not automatic. You must restart the nodejs execution.

mvc.api({
    name: "customer",
    action: "all"
}, function (req) {
    return [
        {
            name: "Marco A. Castillo",
            country: "Panama"
        },
        {
            name: "Rafael Della Sera",
            country: "Panama"
        }
    ];
});

The expected URL for XML format will be: http://domain.com/api/customer/all/xml

The expected URL for JSON format will be: http://domain.com/api/customer/all/json

You can also replace the default URL format as name/action, just including the path: "/new-path". Also a dependency injection simple way is available to pass the dependencies previously defined.

mvc.api({
    name: "customer",
    action: "all",
    path: "/service/customer/get/all"
}, "customerService", function (req, customerService) {
    return customerService.getAll();
});

The expected URL for XML format will be: http://domain.com/api/service/customer/get/all/xml

The expected URL for JSON format will be: http://domain.com/api/service/customer/get/all/json

Real Time

Create a new realtime channel is easy, just add a new file in source/realtime, plugdo MVC will load the new file after initialization, the loading is not automatic. You must restart the nodejs execution.

mvc.realtime("channel1");

Using the realtime channel throught the Web Page

Create a new ejs view file, including the required socket.io files and publish the new view creating a Controller.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Realtime Example</title>
    <link rel="stylesheet" href="/css/enterpriseui.min.css"/>
    <script src="/socket.io/socket.io.js"></script>
    <script src="/js/plugdo-dependency.min.js"></script>
    <script src="/js/plugdoeui.min.js"></script>
</head>
<body id="eui">
    <script>
        var realtime = new PlugdoRealtime("http://localhost:3000");
        function PlugdoRealtime (host) {
            var self = this;
            self.io = io.connect(host);

            this.register = function (name, callback) {
                self.io.on("client" + name, function (data) {
                    callback(data);
                });
            };

            this.send = function (name, data) {
                self.io.emit("server" + name, data);
            }
        }

        load(function () {
            plugdo.ready(function() {
                realtime.send("channel1", { date: Date.now(), author: "Marco Castillo"} );

                realtime.register("channel1", function (data) {
                    console.log(data);
                });
            });
        }, true);
    </script>
</body>
</html>

Using the realtime channel from the server side

Create a new Controller or Web API.

Calling the realtime

mvc.broadcast.publish("channel1", { date: Date.now(), author: "Marco Castillo"});
mvc.api({
    name: "customer",
    action: "new"
}, "customerService", function (req, customerService) {
    // Create the customer model
    let customer = {
        date: Date.now(),
        author: req.params.name
    };
    
    // Insert the new customer and collect the response back from the service
    let responseModel = customerService.createCustomer(customer);

    if(responseModel.success) {
        // Send the new customer to the realtime channel if the customer was created successfully
        mvc.broadcast.publish("channel1", customer);
    }

    return responseModel;
});

Upload Files

mvc.upload("/upload");

Adding this path using the method mvc.upload before the mvc.start is executed, allow you to accept files through form multipart. the default behavior is to response a json object. The /upload path become a Web API. If you want to avoid this default behavior, you must pass options to the mvc.upload.

The following next=true options, will upload the file and create a json model injected in the req.files. The mvc.upload accept multiple files by default so the req.files is an array. With the next=true option, you can create a controller or a web api. Now you can execute your on logic, like, uploading a file and adding the file in the database.

mvc.upload("/upload", { next: true });

You can register to the realtime channel "plugdo-mvc-upload-in-progress" to collect the progress of the file. The model sent is:

let realtimeModel = {
    path,
    file: {
        field,
        name,
        path,
        encoding,
        type,
        size
    }
}

PLUGDO MS (Micro-service)

Create a new micro-service is easy, just implement the ms.start() framework to start working with RabbitMQ task. You can create an application that just open a connection with RabbitMQ to consume or emit message to the queue.

Consume a Queue

Let's see the following example to open a connection with RabbitMQ waiting for a payload message in JSON format. (Just JSON payload is supported).

// index.js

const ms = require("./modules/plugdo-mvc").ms();

// "localhost" is the host used in this example
ms.start("localhost").then(() => {

    // Queue channel "PLUGDO_MS"
    // ms.consume() function register this queue as listener
    ms.consume("PLUGDO_MS", function (payload, end) {
        // Add your own logic here to process the payload JSON object
        
        end(payload); // Always end the process
    });

});

Also you can emit message. This node app will end as soon as the message is sent. The connection remain open when you consume a queue, otherwise the app will close.

// index.js

const ms = require("./modules/plugdo-mvc").ms();

// "localhost" is the host used in this example
ms.start("localhost").then(() => {

    // Queue channel "PLUGDO_MS"
    // Emit a message to this queue
    let payload = {
        id: 1,
        message: "Payload Message"
    };

    ms.emit("PLUGDO_MS", payload);

});

The following demo consume a queue, and also emit a message to that queue. You will be able to log the payload recieved in the consume method.

// index.js

const ms = require("./modules/plugdo-mvc").ms();

// "localhost" is the host used in this example
ms.start("localhost").then(() => {

    // Queue channel "PLUGDO_MS"
    // ms.consume() function register this queue as listener
    ms.consume("PLUGDO_MS", function (payload, end) {
        // Add your own logic here to process the payload JSON object
        console.log(payload);
        
        end(payload); // Always end the process
    }).emit("PLUGDO_MS", {
        id: 1,
        message: "Payload Message"
    });

});

Release Notes

  • v1.2.11: Adding the confiuration mvc.forceJSON = true before the server starts, you are able to avoid the response type json or xml in the api path because It is force to be JSON. Using http://localhost/api/name/action without json or xml at the end. Also the global error response in XML format is replace for json format as follow: { response: { success: false, errorCode: 500, error: "error message here (stack value)" } }

Quick Notes

The req parameter injected in the controller is the express object, if you need more details about the properties available, just go to expressjs.com documentation.

1.2.11

4 years ago

1.2.10

4 years ago

1.2.9

4 years ago

1.2.8

4 years ago

1.2.7

4 years ago

1.2.6

4 years ago

1.2.0

4 years ago

1.2.5

4 years ago

1.1.0

4 years ago

1.0.31

4 years ago

1.0.30

4 years ago

1.0.29

4 years ago

1.0.27

4 years ago

1.0.26

4 years ago

1.0.25

4 years ago

1.0.22

4 years ago

1.0.21

6 years ago

1.0.20

6 years ago

1.0.19

6 years ago

1.0.18

6 years ago

1.0.17

6 years ago

1.0.16

6 years ago

1.0.15

6 years ago

1.0.14

6 years ago

1.0.13

6 years ago

1.0.12

6 years ago

1.0.11

6 years ago

1.0.10

6 years ago

1.0.9

6 years ago

1.0.8

6 years ago

1.0.7

6 years ago

1.0.6

6 years ago

1.0.5

6 years ago

1.0.4

6 years ago

1.0.3

6 years ago

1.0.2

6 years ago

1.0.1

6 years ago

1.0.0

6 years ago