mii-js
Mii is NodeJS (MVC) Framework, Inspired By Yii-2
Last updated 2 years ago by ch3ll0v3k .
MIT · Repository · Bugs · Original npm · Tarball · package.json
$ cnpm install mii-js 
SYNC missed versions from official npm registry.

Mii-js Logo

IS IN DEV-MODE: USE IT AT YOUR OWN RISK


Mii-js is NodeJS, MVC, Framework, Inspired By Yii-2

License: MIT npm version

Yii-2 Framework: Yii-2
NPMJS: Mii-js
GitHub : Mii
License: MIT License


Dependencies [ node-js ]

package min. version required
cookie-parser v 1.4.3 yes
events v 3.0.0 yes
express v 4.16.3 yes
express-session v 1.15.6 yes
helmet v 3.13.0 yes
pretty v 2.0.0 yes
querystring v 0.2.0 yes
serve-static v 1.13.2 yes
session-file-store v 1.2.0 yes
compression v 1.7.3 no
csurf v 1.9.0 no
hpp v 0.2.2 no
mysql v 2.16.0 no
morgan v 1.9.1 no
debug v 4.0.1 no
nodemailer v 4.6.8 no

install

$ npm i mii-js --save

MiiHelper

MiiHelper will help create basic app structure with simple bootstrap based page and controllers / views

Examples:
    $ node ./MiiHelper --create --app-root ./sites/my-new-site.com
    // or
    $ node ./MiiHelper -c -r my-site.com

    $ node ./MiiHelper -c -r ./any/path/to/my/my-site.com

output

[06:04:54][O] :  # MiiHelper
[06:04:54][O] :  # Mii. newProject: creating app_root
[06:04:55][O] :  # Mii: newProject: created ..
[06:04:55][O] :      To start: 
[06:04:55][O] :          cd my-new-site.com
[06:04:55][O] :          node ./app.js

Start new created App

$ cd my-new-site.com
$ node ./app.js 

output

toor@abi:abc.com$ node ./app.js 
    [09:23:52][O] :  # readConfig: [./configs/main.json]
    [09:23:52][O] :  # Mii::Express: serveStatic:[ public_html ]
    [09:23:52][O] :  # Mii::Security: dnsPrefetchControl:[ true ]
    [09:23:52][O] :  # Mii::Security: frameguard:[ true ]
    [09:23:52][O] :  # Mii::Security: hidePoweredBy:[ true ]
    [09:23:52][O] :  # Mii::Security: hsts:[ true ]
    [09:23:52][O] :  # Mii::Security: ieNoOpen:[ true ]
    [09:23:52][O] :  # Mii::Security: noSniff:[ true ]
    [09:23:52][O] :  # Mii::Security: xssFilter:[ true ]
    [09:23:52][O] :  # Mii::Security: HPP:[ true ]
    [09:23:52][O] :  # Mii::Server: compression:[ true ]
    [09:23:52][O] :  # Mii::Session: path     :[ ./sessions ]
    [09:23:52][O] :  # Mii::Session: key      :[ srf*********** ]
    [09:23:52][O] :  # Mii::Session: sameSite :[ true ]
    [09:23:52][O] :  # Mii::Session: httpOnly :[ true ]
    [09:23:52][O] :  # Mii::Session: secure   :[ true ]
    [09:23:52][L] : 
    [09:23:52][O] :  # Mii::createServer: type: [http]
    [09:23:52][O] :  # Mii::createServer: type: [https]
    [09:23:52][O] :  # Mii::createServer: type: [http] => status: [200] => 127.0.0.1:8080 
    [09:23:52][O] :  # Mii::createServer: type: [https] => status: [200] => 127.0.0.1:8433 
    [09:23:52][O] :  # MySqlDB: Connected ...
    [06:08:14][O] :  # MySqlDB: Connected ...

Created App structure


├── app.js
├── cert
│   ├── 127.0.0.1.pem
│   └── 127.0.0.1.cert
│
├── configs
│   └── main.json
│
├── controllers
│   ├── Site.js
│   ├── MyClass.js
│   └── UpperCaseControllerName.js
│
├── components
│   └── MyComponent.js
│
├── layouts
│   ├── layout-template.html
│   └── main.html
│
├── runtime
│   └── logs
│
├── public_html
│   ├── css
│   ├── img
│   ├── robots.txt
│   └── vendor
│
├── sessions
└── views
    └── site
        └── index.html


Basic Controller

// camel-case-url-names => CamelCaseUrlNames


const BaseController = require('./mii/BaseController');

module.exports = class Site extends BaseController{

    # site.com/
    actionIndex( Mii ){

        # [Mii] is reference to [this]

        Mii.render({});
        # or
        this.render({});

    }

    # site.com/site/my-method/
    actionMyMethod( Mii ){

    }

}


const BaseController = require('./mii/BaseController');

module.exports = class MyClass extends BaseController{

    # Not required, will be executed if available
    before( Mii ){
        # change default layout for all actions in current class
        this.layout = 'main';
    }

    actionLogin( Mii ){

        # change layout at runtime for given action
        this.layout = 'main-2';

        this.title = 'Users';

        this.render({
            users: ['Bob','Alice']
        });

    }

    actionOther( Mii ){

        try{

            # ...

        }catch( e ){
            this.exception( e ); # Not required
        }

    }

}

Custom Components

app_root/components/MyComponent


const BaseComponent = require('./mii/BaseComponent');

module.exports = class MyComponent extends BaseComponent{

    api( path,cb ){

        this.Mii.httpGet({url:'https://api.binance.com/api/v3/'+path, json: true}, function( http_res ) {
            ( http_res.code == 200 ) ? cb( http_res.data ) : cb( [] );

        });

    }

    sqrt(num) {
        return Math.sqrt( num );

    }

    isPrime(num) {
        for ( var i = 2; i < num; i++ )
            if ( num % i === 0 ) 
                return false;

        return true;
    }

    getPrimes(upto) {
        var arr = [2];
        for ( var i = 3; i < upto; i+=2 )
            if ( this.isPrime(i) )
                arr.push(i);

        return arr;

    }

}

const BaseController = require('./mii/BaseController');

module.exports = class MyClass extends BaseController{

    actionIndex( Mii ){

        let MyComponent = Mii.getComponent('MyComponent');

        let sqrt = MyComponent.sqrt(37);
        let primes = MyComponent.getPrimes(10);

        Mii.renderJson( {sqrt, primes} );

    }

    actionApiPrices( Mii ){
        Mii.getComponent('MyComponent').api( 'ticker/price', function(res){
            Mii.renderJson( res );
        });

    }
}

Controller Methods :: request and/or output JSON


const BaseController = require('./mii/BaseController');

module.exports = class MyClass extends BaseController{

    # site.com/my-class/show-users/
    actionShowUsers( Mii ){

        # Will output pure JSON with header [application/json]
        # Any layout will be ignored

        this.renderJson([
            { Name: "Bob", role: "Admin"},
            { Name: "Alice", role: "User"},
        ]);

    }

    # site.com/my-class/api/type/my-type/id/32/?abc=123

    actionApi( Mii ){

        let id = Mii.getParam('id');

        let type = Mii.getParam('type');

        let abc = Mii.getGet('type');


        this.httpGet({url "http://api.com/prices/type/"+type+"/id/"+id, json:true}, function(json_t){

            if( json.code == 200 ){
                // ...
            }

            // [Mii] is reference to [this]
            Mii.renderJson( json );

        });

    }
}

Controller Methods :: Models && Post/Get/Ajax


const BaseController = require('./mii/BaseController');

module.exports = class MyClass extends BaseController{

    # site.com/my-class/find-user/name/Tom/id/32/age/54/?lang=en
    actionFindUser( Mii ){

        # GET
        let id    = Mii.getParam('id');
        let age   = Mii.getParam('age');
        let name  = Mii.getParam('name');

        let lang  = Mii.getGet('lang');

        Mii.model('user').find({id: id, name: name }, function( model ){

            if( model.id ){

                Mii.setSession( 'user_id', model.id );

                model.set({
                    email:'ch3ll0v3k@yandx.com', 
                    pwd: 'new-password', 
                    role: 'new', 
                });

                model.save( function(res){
                    Mii.renderJson( res );
                });

            }else{
                # not found ?
                Mii.renderJson( model );
            }

        });

    }

    # site.com/my-class/new-user/
    actionNewUser( Mii ){

        if( Mii.isPost() && Mii.isAjax() ){

            # POST
            let email = Mii.getPost('email');
            let pwd   = Mii.getPost('pwd');
            let role  = Mii.getPost('role');

            # Model find data
            Mii.model('user').find({email: email}, function( model ){

                if( model ){
                    # User exists ...
                    return false;
                }

                pwd = Mii.hashPwd( pwd ); // F3E9D8-D9C9BC-CAB86B-9DA938-1FAD58

                # Create new user 
                Mii.newModel('user', function( model ){
                    if( model ){
                        model.set({
                            email : email, 
                            pwd   : pwd,
                            role  : role,
                            created: Mii.getUnixTime()
                        });

                        model.save( function(res){
                            Mii.renderJson( res );
                        });
                    }
                });
    
            }

        }
    }


}

Controller Methods :: Models && Options


const BaseController = require('./mii/BaseController');

module.exports = class MyClass extends BaseController{

    # site.com/my-class/
    actionIndex( Mii ){

        # Havy data processing ...
        Mii.setTimeout( 30 ); // max sec. exec. time (0 == disable)

        Mii.setContentType('application/json');

        Mii.cleanUp( "dangerous string <%> \"'/ -->\ß23'  " )
        Mii.toJson({"ABC", 123}); 
        Mii.fromJson( '{"ABC", 123}' );

        Mii.getUnixTime();          # 154543344

        Mii.csrfToken();            # CSRF (if enabled in config file) 

        // GET / POST / URL-PARAM

        // /site.com/site/index/name/Tom/?lang=en

        Mii.getParam("name");       # "Tom" || false
        Mii.getGet("lang");         # "en" || false

        Mii.getGet();               # "_GET" || {}

        Mii.getPost("key");         # "value" || false
        Mii.getPost();              # "_POST" || {}

        Mii.isPost();               # true || false
        Mii.isAjax();               # true || false
        Mii.isFile("./to/file");    # true || false
        Mii.isDir("./to/dir");      # true || false

        Mii.getHeaders();           # array with all headers
        Mii.getHeader("HOST");      # "value" || false

        Mii.setSession( key, val ); # true || false
        Mii.getSession( key );      # "value" || false

        // Add headers to output
        Mii.setHeader('my-key', 'my-val'); 

        Mii.httpGet({ url: 'http://site.com' json: true }, function(res){

            res.headers  # response headers
            res.code     # response status code
            res.data     # response data 
            res.msg      # response status message

            if( res.code == 200 ){
                Mii.renderJson( res );
            }

        });

        let params = {
            url: 'http://127.0.0.1:8080/api/post', 
            data: { ABC:123, DEF:456 },     # not required
            json: true,                     # not required
            headers: {                      # not required
                'Content-Length': 1024,
                'My-Key': 'My-Val',

            }
        }

        Mii.httpPost( params, function(res){

            res.headers  # resp. headers
            res.code     # status code
            res.data     # data 
            res.msg      # status message

            if( res.code == 200 ){
                Mii.renderJson( {headers: res.headers, data: res.data} );
            }else{
                Mii.renderJson( res );
            }

        });

    }
}

Controller Methods :: Models && Render


const BaseController = require('./mii/BaseController');

module.exports = class MyClass extends BaseController{

    # site.com/my-class/
    actionIndex( Mii ){

        Mii.renderRaw('<H4>Hello</H4>');
        Mii.renderRaw( {Name: "Tom"} );

        Mii.renderJson( {Name: "Tom"} );
        Mii.renderPartial( "./views/user/_part.html" );

        Mii.render('view-name', {});

        # Will get view according to [controller]/[action] name
        Mii.render({
            user: [
                {name:"Bob"}, {name:"Alice"},
            ]
        });

    }
}

Controller Methods :: Sending mail [smtp options required => config]


const BaseController = require('./mii/BaseController');

module.exports = class MyClass extends BaseController{

    actionIndex( Mii ){

        let to = 'email@host.com';
        let subject = 'Welcome mail';
        let msg = ' Welcome <h4> {user-name} <h4> ';

        Mii.newMail( {to, subject, msg} ).send(function( res ){ 

            Mii.renderJson( res );

            if( res.code == 200 ){
                // ...
            }else{
                // ...
            }

        });

    }

}

Controller Methods :: Models && DataBase


const BaseController = require('./mii/BaseController');

module.exports = class MyClass extends BaseController{

    # site.com/my-class/
    actionIndex( Mii ){

        Mii.DB("select * from user", function(db_res){

            if( db_res.code == 200 ){
                Mii.render({ user: db_res.data });
            }else{
                Mii.renderRaw('<h5> User Not found ... </h5>');

            }

        });

    }

}

Micro Template-Engine with basic logic

http://site.com/my-class/my-action/

const BaseController = require('./mii/BaseController');

module.exports = class MyClass extends BaseController{

    actionMyAction( Mii ){

        Mii.render({
            balance: 124.45,
            users: [
                {name : 'Tom', gender : 'Male', age : 120 },
                {name : 'Bob', gender : 'Male', age : 88 },
                {name : 'Alica', gender : 'Female', age : 79 },
            ],
            show_header: true,
            show_footer: false,
            show_users_list: true,
        });

    }

}


<html lang="<? $lang ?>">
    <head>

        <meta charset="<? $charset ?>"/>
        <meta name="csrf-token" content="<? $_csrf ?>"/>
        <title> <? $app_name ?> - <? $title ?> </title>

    </head>

    <body>

        <div> Balance : <? echo( $balance ) ?> </div>

        <div> Balance or : <?( $balance )?> </div>

        <? if( $show_header ) ?>
            <? include( "my-controller/_header" ) ?>
        <? endif ?>

        <? if( $show_users_list ) ?>
        <div>
            <h4> Users: <? echo ( $total_users ) ?> </h4>
            <? foreach( $users as $user ){ ?>
                <p> 
                    Name: <? echo ( $user.name ) ?>, 
                    Age: <? echo ( $user.age ) ?>, 
                    Gender: <? echo ( $user.gender ) ?> 
                </p>
            <? } ?>
        </div>
        <? endif ?>

        <? if( $show_footer ) ?>
            <? include( "my-controller/_footer" ) ?>
        <? endif ?>

        <? include( "my-controller/_description" ) ?>

        // Or from other view directory
        <? include( " other-controller/_other_view" ) ?>

    </body>
</html>

App Config ./configs/main.json

{
    "site": {
        "host": "site.com",
        "url": "https://site.com",
        "name": "Mii",
        "lang": "en",
        "charset": "utf-8",
        "version": "1.0.1"
    },
    "mii": {
        "paths": {
            "configs": "configs",
            "controllers": "controllers",
            "components": "components",
            "layouts": "layouts",
            "views": "views",
            "public_html": "public_html"
        }
    },
    "logs": {
        "log": true,
        "root": "runtime/logs",
        "file_size_mb": 1
    },
    "runtime": {
        "debug": true,
        "morgan": false,
        "onError": {
            "controller": "Site",
            "action": "Error"
        }
    },
    "server": {
        "ip": "127.0.0.1",
        "host": "127.0.0.1",
        "timeout": 5,
        "compression": true,
        "time-zone": "+1",
        "http": {
            "port": 8080
        },
        "https": {
            "port": 8433
        },
        "headers": [{
                "X-Powered-By": "Mii-js"
            }],
        "document_root": "public_html"
    },
    "security": {
        "CSRF": {
            "enabled": false,
            "secret": "some-secret",
            "key": "_csrf",
            "sameSite": false,
            "httpOnly": true,
            "domain": "*"
        },
        "HPP": {
            "enabled": true
        },
        "helmet": {
            "contentSecurityPolicy": false,
            "descr: contentSecurityPolicy": "for setting Content Security Policy, default: [false]",
            "expectCt": false,
            "descr: expectCt": "for handling Certificate Transparency, default: [false]",
            "dnsPrefetchControl": true,
            "descr: dnsPrefetchControl": "controls browser DNS prefetching, default: [true]",
            "frameguard": true,
            "descr: frameguard": "to prevent clickjacking, default: [true]",
            "hidePoweredBy": true,
            "descr: hidePoweredBy": "to remove the X-Powered-By header, default: [true]",
            "hpkp": false,
            "descr: hpkp": "for HTTP Public Key Pinning, default: [false]",
            "hsts": true,
            "descr: hsts": "for HTTP Strict Transport Security, default: [true]",
            "ieNoOpen": true,
            "descr: ieNoOpen": "sets X-Download-Options for IE8+, default: [true]",
            "noCache": false,
            "descr: noCache": "to disable client-side caching, default: [false]",
            "noSniff": true,
            "descr: noSniff": "to keep clients from sniffing the MIME type, default: [true]",
            "referrerPolicy": false,
            "descr: referrerPolicy": "to hide the Referer header, default: [false]",
            "xssFilter": true,
            "descr: xssFilter": "adds some small XSS protections, default: [true]"
        }
    },
    "session": {
        "name": "server-session-cookie-id",
        "secret": "super-secret-stuff",
        "saveUninitialized": true,
        "resave": true,
        "path": "./sessions",
        "cookie": {
            "key": "_csrf",
            "sameSite": true,
            "httpOnly": true,
            "secure": true
        }
    },
    "cache": {
        "controllers": false,
        "files": false,
        "components": false,
        "modules": false
    },
    "ssl": {
        "keys": {
            "key": "cert/127.0.0.1.key",
            "cert": "cert/127.0.0.1.pem"
        }
    },
    "db": {
        "mysql": {
            "connection": {
                "host": "localhost",
                "port": 3306,
                "user": "root",
                "password": "toor",
                "database": "Mii"
            }
        },
        "redis": {},
        "mongo": {}
    },
    "memcached": {
        "secret": "memcached-secret-key",
        "key": "test",
        "proxy": "true",
        "hosts": ["127.0.0.1:12345"]
    },
    "smtp": {
        "host": "smtp.yandex.ru",
        "port": 465,
        "secure": true,
        "auth": {
            "user": "user@mail-server.com",
            "pass": "my-password"
        }
    },
    "app_root": " will be set at runtime ",
    "mii_root": " will be set at runtime "
}

Current Tags

  • 1.1.35                                ...           latest (2 years ago)

79 Versions

  • 1.1.35                                ...           2 years ago
  • 1.1.34                                ...           2 years ago
  • 1.1.33                                ...           2 years ago
  • 1.1.32                                ...           2 years ago
  • 1.1.31                                ...           2 years ago
  • 1.1.30                                ...           2 years ago
  • 1.1.29                                ...           2 years ago
  • 1.1.28                                ...           2 years ago
  • 1.1.27                                ...           2 years ago
  • 1.1.26                                ...           2 years ago
  • 1.1.25                                ...           2 years ago
  • 1.1.24                                ...           2 years ago
  • 1.1.23                                ...           2 years ago
  • 1.1.22                                ...           2 years ago
  • 1.1.21                                ...           2 years ago
  • 1.1.20                                ...           2 years ago
  • 1.1.18                                ...           2 years ago
  • 1.1.17                                ...           2 years ago
  • 1.1.16                                ...           2 years ago
  • 1.1.15                                ...           2 years ago
  • 1.1.14                                ...           2 years ago
  • 1.1.13                                ...           2 years ago
  • 1.1.12                                ...           2 years ago
  • 1.1.11                                ...           2 years ago
  • 1.1.10                                ...           2 years ago
  • 1.1.9                                ...           2 years ago
  • 1.1.8                                ...           2 years ago
  • 1.1.7                                ...           2 years ago
  • 1.1.6                                ...           2 years ago
  • 1.1.5                                ...           2 years ago
  • 1.1.4                                ...           2 years ago
  • 1.1.3                                ...           2 years ago
  • 1.1.2                                ...           2 years ago
  • 1.0.69                                ...           2 years ago
  • 1.0.68                                ...           2 years ago
  • 1.0.67                                ...           2 years ago
  • 1.0.66                                ...           2 years ago
  • 1.0.65                                ...           2 years ago
  • 1.0.64                                ...           2 years ago
  • 1.0.62                                ...           2 years ago
  • 1.0.61                                ...           2 years ago
  • 1.0.60                                ...           2 years ago
  • 1.0.59                                ...           2 years ago
  • 1.0.58                                ...           2 years ago
  • 1.0.57                                ...           2 years ago
  • 1.0.56                                ...           2 years ago
  • 1.0.55                                ...           2 years ago
  • 1.0.54                                ...           2 years ago
  • 1.0.53                                ...           2 years ago
  • 1.0.52                                ...           2 years ago
  • 1.0.51                                ...           2 years ago
  • 1.0.50                                ...           2 years ago
  • 1.0.49                                ...           2 years ago
  • 1.0.48                                ...           2 years ago
  • 1.0.47                                ...           2 years ago
  • 1.0.46                                ...           2 years ago
  • 1.0.45                                ...           2 years ago
  • 1.0.44                                ...           2 years ago
  • 1.0.43                                ...           2 years ago
  • 1.0.42                                ...           2 years ago
  • 1.0.41                                ...           2 years ago
  • 1.0.40                                ...           2 years ago
  • 1.0.39                                ...           2 years ago
  • 1.0.38                                ...           2 years ago
  • 1.0.37                                ...           2 years ago
  • 1.0.35                                ...           2 years ago
  • 1.0.34                                ...           2 years ago
  • 1.0.33                                ...           2 years ago
  • 1.0.32                                ...           2 years ago
  • 1.0.31                                ...           2 years ago
  • 1.0.30                                ...           2 years ago
  • 1.0.29                                ...           2 years ago
  • 1.0.28                                ...           2 years ago
  • 1.0.27                                ...           2 years ago
  • 1.0.26                                ...           2 years ago
  • 1.0.25                                ...           2 years ago
  • 1.0.24                                ...           2 years ago
  • 1.0.23                                ...           2 years ago
  • 1.0.22                                ...           2 years ago
Maintainers (1)
Downloads
Today 0
This Week 0
This Month 0
Last Day 0
Last Week 0
Last Month 0
Dependencies (16)
Dev Dependencies (0)
None
Dependents (0)
None

Copyright 2014 - 2016 © taobao.org |