1.1.35 • Published 5 years ago

mii-js v1.1.35

Weekly downloads
88
License
MIT
Repository
github
Last release
5 years ago

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

packagemin. versionrequired
cookie-parserv 1.4.3yes
eventsv 3.0.0yes
expressv 4.16.3yes
express-sessionv 1.15.6yes
helmetv 3.13.0yes
prettyv 2.0.0yes
querystringv 0.2.0yes
serve-staticv 1.13.2yes
session-file-storev 1.2.0yes
compressionv 1.7.3no
csurfv 1.9.0no
hppv 0.2.2no
mysqlv 2.16.0no
morganv 1.9.1no
debugv 4.0.1no
nodemailerv 4.6.8no

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 "
}

1.1.35

5 years ago

1.1.34

5 years ago

1.1.33

5 years ago

1.1.32

6 years ago

1.1.31

6 years ago

1.1.30

6 years ago

1.1.29

6 years ago

1.1.28

6 years ago

1.1.27

6 years ago

1.1.26

6 years ago

1.1.25

6 years ago

1.1.24

6 years ago

1.1.23

6 years ago

1.1.22

6 years ago

1.1.21

6 years ago

1.1.20

6 years ago

1.1.18

6 years ago

1.1.17

6 years ago

1.1.16

6 years ago

1.1.15

6 years ago

1.1.14

6 years ago

1.1.13

6 years ago

1.1.12

6 years ago

1.1.11

6 years ago

1.1.10

6 years ago

1.1.9

6 years ago

1.1.8

6 years ago

1.1.7

6 years ago

1.1.6

6 years ago

1.1.5

6 years ago

1.1.4

6 years ago

1.1.3

6 years ago

1.1.2

6 years ago

1.0.69

6 years ago

1.0.68

6 years ago

1.0.67

6 years ago

1.0.66

6 years ago

1.0.65

6 years ago

1.0.64

6 years ago

1.0.62

6 years ago

1.0.61

6 years ago

1.0.60

6 years ago

1.0.59

6 years ago

1.0.58

6 years ago

1.0.57

6 years ago

1.0.56

6 years ago

1.0.55

6 years ago

1.0.54

6 years ago

1.0.53

6 years ago

1.0.52

6 years ago

1.0.51

6 years ago

1.0.50

6 years ago

1.0.49

6 years ago

1.0.48

6 years ago

1.0.47

6 years ago

1.0.46

6 years ago

1.0.45

6 years ago

1.0.44

6 years ago

1.0.43

6 years ago

1.0.42

6 years ago

1.0.41

6 years ago

1.0.40

6 years ago

1.0.39

6 years ago

1.0.38

6 years ago

1.0.37

6 years ago

1.0.35

6 years ago

1.0.34

6 years ago

1.0.33

6 years ago

1.0.32

6 years ago

1.0.31

6 years ago

1.0.30

6 years ago

1.0.29

6 years ago

1.0.28

6 years ago

1.0.27

6 years ago

1.0.26

6 years ago

1.0.25

6 years ago

1.0.24

6 years ago

1.0.23

6 years ago

1.0.22

6 years ago