npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@dellasera/plugdo-mvc

v1.2.11

Published

plugdo mvc web server

Downloads

17

Readme

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.