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

@coolgk/mvc

v1.0.21

Published

A simple, light javascript / typescript nodejs mvc framework that helps you to create object oriented, modular and testable code

Downloads

27

Readme

@coolgk/mvc

npm install @coolgk/mvc

A simple, lightweight javascript / typescript nodejs mvc framework that helps you to create object oriented, modular and testable code.

Build Status Coverage Status dependencies Status Known Vulnerabilities

Documentation

This framework routes HTTP requests to class methods.

e.g. "GET /shop/product/description/1" calls the "description" method in "/modules/shop/controllers/product.js" (see example code below)

In this example request, "shop" is a module (folder), "product" is a controller (file), "description" is an action (method) and "1" is a parameter. The format of the request is /module/[controller]/[action]/[param]

The framework looks for files from the folder structure below.

./index.js
./modules
    /shop
        /controllers
            product.js
            anothercontroller.js
        /models
            model.js
    /anothermodule
        /controllers
        ...

Controller

The controller module must export a "default" property which is a class that extends the base "Controller" class from @coolgk/mvc/controller. Folder (module), file (controller) and method (action) names must be in lowercase without special characters except for hyphens and numbers /[a-z0-9\-]/ or in camelCase if a request contains hyphens e.g. action-one is converted to actionOne

product.js controller example

const { Controller } = require('@coolgk/mvc/controller');

class Product extends Controller {
    /**
     * @param {object} dependencies - this param is destructured in this example
     * @param {object} dependencies.params - url param values based on the patterns configured in getRoutes()
     * @param {object} dependencies.globals - the object passed into the router's constructor
     * @param {*} dependencies.services - services returned by getServices()
     */
    description ({ params, services, globals }) {
        // globals contains global dependencies passed into the router class (see example below)
        globals.response.json(
            services.model.find(params.id)
        );
    }

    /**
     * setup valid routes to methods
     */
    getRoutes () {
        return {
            GET: {
                description: ':id' // allow GET request to access the description() method
            }
        }
    }

    /**
     * setup local dependencies
     */
    getServices () {
        return {
            model: new (require('../models/model.js'))()
        };
    }

    /**
     * setup permission callbacks for accessing methods
     */
    getPermissions () {
        return {
            // * the is default permission for all methods in this class
            // can be used for checking app level permissions e.g. login sessions etc.
            '*': () => false, // false = deny all by default
            // true or Promise<true>: skip permission check for the description() method
            'description': () => true
        };
    }
}

exports.default = Product;

Entry Point (Router)

index.js / server.js however you name it...

An example of using express with this framework

const express = require('express');
const { Router } = require('@coolgk/mvc/router');

const app = express();

app.use(async (request, response, next) => {

    // initialise router
    const router = new Router({
        rootDir: __dirname, // required
        url: request.originalUrl, // required
        method: request.method, // required
        response // you can pass anything into router, these variables are injected into controllers methods in globals
    });

    // router.route() returns the return value of the controller method if the return value is not falsy
    // otherwise it returns an object formatted by the "response" object (see the documention for @coolgk/mvc/response at the bottom)
    // e.g. { code: 200, text: 'SUCCESS' }, { code: 200, json: {...} }, { code: 200, file: { name: ..., path: ... } } etc.
    const result = (await router.route());

    // for handling 404 / 403 returned from the router
    result && result.code && response.status(result.code).send(result.text);

});

app.listen(3000);

Unit Test

Dependencies are injected into methods, you can easily mock them in your tests.

'use strict';

const sinon = require('sinon');
const expect = require('chai').expect;

describe('Test Example', function () {
    // this test is for the example code in https://github.com/coolgk/node-mvc/tree/master/src/examples
    // i.e. not the product.js controller above
    const ControllerClass = require(`../javascript/modules/example/controllers/extended`).default;

    let controller;
    let params;
    let response;
    let services;
    let globals;

    beforeEach(() => {
        // initialise controller for each test case
        controller = new ControllerClass();
        // setup dependencies
        params = { id: 123 };
        // create test spy on global dependency: response
        response = {
            json: sinon.spy()
        };
        // create test stub on local dependency: services
        services = {
            model: {
                getUser: sinon.stub().returns({ name: 'abc' })
            }
        };
        // create test stub on global dependency: globals
        globals = {
            session: {
                getAll: sinon.stub().returns({ session: 'data' })
            }
        };
    });

    it('should show user name and session', async () => {
        await controller.user({ params, response, services, globals });
        expect(services.model.getUser.calledWithExactly(params.id)).to.be.true;
        expect(globals.session.getAll.calledOnce).to.be.true;
        expect(response.json.calledWithExactly({
            user: { name: 'abc' },
            session: { session: 'data' }
        })).to.be.true;
    });

});

More Examples

JavaScript Examples

TypeScript Examples TypeScript version of the examples above

Also See

@coolgk/mongo

A javascript / typescript MongoDB modelling library which enables joins in collections, simplifies CRUD operations for sub / nested documents and implements schema based data validation.

@coolgk/utils

A javascript / typescript utility library. Modules: array, string, base64, ampq, bcrypt, cache, captcha, csv, email, jwt, number, pdf, tmp, token, unit conversion, url params, session, form data

Report bugs here: https://github.com/coolgk/node-mvc/issues

Controller

Base controller class

Kind: global class

controller.getServices(dependencies) ⇒ object

Kind: instance method of Controller
Returns: object - - class dependencies, which is injected into the class methods by the router

| Param | Type | Description | | --- | --- | --- | | dependencies | object | global dependencies passed into the router's controller |

Response

setting / getting standard responses in controllers

Kind: global class

response.getResponse() ⇒ object

Kind: instance method of Response
Returns: object - - last set response. format: { code: number, json?: any, status?: string, file?: { path: string, name?: string } }

response.send(data, [code]) ⇒ object

set arbitrary response

Kind: instance method of Response
Returns: object - - set response. format: { code: number, ...data }

| Param | Type | Default | Description | | --- | --- | --- | --- | | data | object | | any json data | | [code] | number | 200 | http status code |

response.json(json, [code]) ⇒ object

set a json response

Kind: instance method of Response
Returns: object - - set response. format: { code: number, json }

| Param | Type | Default | Description | | --- | --- | --- | --- | | json | object | | any json data | | [code] | number | 200 | http status code |

response.text([text], code) ⇒ object

set a http status response

Kind: instance method of Response
Returns: object - - set response. format: { code, status }

| Param | Type | Default | Description | | --- | --- | --- | --- | | [text] | string | | text in response | | code | number | 200 | http status code |

response.file(path, [name], [type], [code]) ⇒ object

set a file download response

Kind: instance method of Response
Returns: object - - set response. format: { file: { path, name }, code }

| Param | Type | Default | Description | | --- | --- | --- | --- | | path | string | | file path | | [name] | string | | file name, if undefined require('path').basename(path) will be used | | [type] | string | | mime type | | [code] | number | 200 | http status code |