cwserver
TypeScript icon, indicating that this package has built-in type declarations

4.0.0 • Public • Published

Cwserver Logo

NPM Downloads Coverage Status

cwserver

The aim of the project is to create an easy to use, lightweight, Complete Web Server Framework with default NodeJs HTTP Server.

  • The framework also provides default
    • Secure User Session,
    • Cookie Parser,
    • Flexible Router,
    • Multiple Views,
    • Virtual Directory,
    • Hidden Directory,
    • Template Engine,
    • Nested Master Template Engine,
    • Post Data Handler (with multipart form data and large file),
    • Mimetype Handler,
    • WebStream Handler,
    • JS/CSS Bundler,
    • socket.io Interface,
    • Easy way to bind with IIS/NGINX

Install cwserver by this command npm i cwserver
How to use cwserver core IApplication?

const { App } = require('cwserver');
const app = App();
const port = 8080;
app.on("request-begain", (req) => {
    console.log(`${req.method} ${req.path}`);
});
app.on("response-end", (req, res) => {
    console.log(`Send ${res.statusCode} ${req.path}`);
});
app.use((req, res, next) => {
    res.status(200).send("Hello World...");
});
app.listen(port, () => {
    console.log(`Listing port => ${port}`);
});

Or you may use full application by following:
Create createProjectTemplate.js as following

const { createProjectTemplate } = require( 'cwserver' );
createProjectTemplate( {
    appRoot: __dirname,
    projectRoot: "www" /** Your project root folder name*/,
    allExample: false
} );

Then run this commmand node createProjectTemplate
It will create default project template for cwserver in your application root.
Now your appRoot look like this

appRoot 
├─┬ wwww ( projectRoot )
│ └─┬ config
│   ├ lib
│   ├ template (this contains master template file)
│   ├ web (this contains temp and cache files)
│   └ index.html
├─ node_modules
├─ server.js
├─ package.json
└─ README.md

After, run this command node server www /**your project root*/

How to setup middleware

First process app.prerequisites every request and then run app.use

global.cw.server.on( "register-view", ( app, controller, server ) => {
	app.prerequisites( ( req, res, next ): void => {
		res.setHeader( 'x-frame-options', 'sameorigin' );
		return next();
	} );
	app.use( ( req, res, next ): void => {
		res.setHeader( 'x-frame-options', 'sameorigin' );
		return next();
	} );
} );

How to setup router ?

global.cw.server.on( "register-view", ( app, controller, server ) => {
    controller
        .any( '/test-any/*', ( ctx, match ) => {
            return ctx.res.json( { reqPath: ctx.path, servedFrom: "/test-any/*", q: match } );
        } )
        .get( '/task/:id/*', ( ctx, match ) => {
            return ctx.res.json( { reqPath: ctx.path, servedFrom: "/task/:id/*", q: match } );
        } )
        .get( '/dist/*', ( ctx, match ) => {
            return ctx.res.json( { reqPath: ctx.path, servedFrom: "/dist/*", q: match } );
        } )
        .get( '/user/:id/settings', ( ctx, match ) => {
            return ctx.res.json( { reqPath: ctx.path, servedFrom: "/user/:id/settings", q: match } );
        } );
} );

How to add Virtual Directory ?

global.cw.server.on( "register-view", ( app, controller, server ) => {
    const vDir = path.join( path.resolve( server.getRoot(), '..' ), "/project_template/test/" );
    server.addVirtualDir( "/vtest", vDir, ( ctx ) => {
        return mimeHandler.render( ctx, vDir, true );
    } );
    server.addVirtualDir( "/test-virtual", vDir );
    server.addVirtualDir( "/vtest/virtual/", vDir );
} );

Authetication

Session cookie name use from app.config.json => session.cookie
and session encryption use app.config.json => session.key

global.cw.server.on( "register-view", ( app, controller, server ) => {
    controller.get( '/authenticate/:loginId/:roleid', ( ctx, requestParam ) => {
        if ( ctx.req.session.isAuthenticated ) {
            ctx.res.status( 200 ).type( "html" ).send( `Hello ${ctx.req.session.loginId}` );
        } else {
            ctx.setSession(/*loginId*/requestParam.query.loginId,/*roleId*/requestParam.query.roleId, /*userData*/{ token: ctx.req.query.token } );
            ctx.res.status( 200 ).type( "html" ).send( `Authentication success ${ctx.req.query.loginId}` );
        }
        return ctx.next( 200 );
    } );
} );

SignOut From Application

global.cw.server.on( "register-view", ( app, controller, server ) => {
	controller.get( '/signout', ( ctx, requestParam ) => {
		if ( ctx.session.isAuthenticated ) {
			ctx.signOut();
		}
		ctx.redirect( "/" ).next( 302, true );
	} );
} );

Handle post data

const { getBodyParser, fsw } = require( 'cwserver' );
global.cw.server.on( "register-view", ( app, controller, server ) => {
    const downloadDir = server.mapPath( "/upload/data/" );
    if ( !fs.existsSync( downloadDir ) ) {
        fsw.mkdirSync( server.mapPath( "/" ), "/upload/data/" );
    }
    const tempDir = server.mapPath( "/upload/temp/" );
    controller.post( '/post-async', async ( ctx ) => {
        const parser = getBodyParser( ctx.req, tempDir );
        await parser.parseSync();
        if ( parser.isUrlEncoded() || parser.isAppJson() ) {
            ctx.res.status( 200, { 'Content-Type': 'application/json' } );
            ctx.res.end( JSON.stringify( parser.getJson() ) );
            parser.dispose();
            return ctx.next( 200 );
        }
        parser.saveAsSync( downloadDir ); parser.dispose();
        return ctx.res.status( 200 ).send( "<h1>success</h1>" );
        // or
        // return ctx.res.asHTML( 200 ).end( "<h1>success</h1>" );
        // or
        /*const data = [];
        parser.getFilesSync( ( file ) => {
            data.push( {
                content_type: file.getContentType(),
                name: file.getName(),
                file_name: file.getFileName(),
                content_disposition: file.getContentDisposition(),
                temp_path: file.getTempPath()
            } );
            file.saveAsSync( `${downloadDir}/${Util.guid()}_${file.getFileName()}` );
        } );
        return ctx.res.status( 200 ).json( data );*/
    } )
} );

See more test here

Template Engine

Template can run config.defaultExt file extension or ctx.res.render( ctx, to_file_path )
Example of server-side script in config.defaultExt or app.config.json => template.ext

ctx.res.render( ctx, server.mapPath( `/index${server.config.defaultExt || ".html"}` ) );

Code block:

{%
    if( !ctx.session.isAuthenticated ){
       return ctx.next( 401, true );
    } else {
       ctx.write( JSON.stringify( ctx.session ) );
    }
%}
<ul>
  {% users.forEach(function(user){ %}
    {= user =}
  {% }); %}
</ul>

<ul>
  <!--{%--> users.forEach(function(user){ <!--%}-->
    {= user =}
  <!--{%--> }); <!--%}-->
</ul>

<script>
    var userLength = 0;
    /*{%*/ if ( users.length > 0 ) {/*%}*/
    userLength = {= users.length =};
    /*{%*/ } /*%}*/
</script>

<script>
    var userLength = 0;
    {% if ( users.length > 0 ) { %}
    userLength = {= users.length =};
    {% } %}
</script>

Response write: {= myVar =} or ctx.write(myVar)

{%
    const result = await ctx.server.db.pgsql.executeIoAsync( "my_shcema.__get_dataset", JSON.stringify( {
        login_id: ctx.req.session.loginId
    } ), JSON.stringify( {
        trade_date: "2020-02-03"
    } ) );
%}
{% if ( result.ret_val < 0) { %}
    <span style="color:red">No Data Found...</span>
{% } else { %}
<table style="width:100%">
   <thead>
      <tr>
         <th>Firstname</th>
         <th>Lastname</th>
         <th>Age</th>
      </tr>
   </thead>
   <tbody>
   {% for( const row of result.ret_data_table ){ %}
        <tr>
            <td>{= row.first_name =}</td>
            <td>{= row.last_name =}</td>
            <td>{= row.age_name =}</td>
        </tr>
   {% } %}
   </tbody>
</table>
{% } %}

Nested Master Template

#extends keyword define my master template
You can add multiple file by #attach keyword

www
├─┬ template
│ └─┬ master.html 
│   ├ footer.html
│   ├ header.html
│   └ readme.html
├─ index.html

index.html  ==> #extends /template/readme.html
==> index.html impliment placeholder id of readme.html (parent master)
-------------------------------------------
#extends /template/readme.html
<impl-placeholder id="container">
    container here
</impl-placeholder>
-------------------------------------------
readme.html ==> #extends /template/master.html (parent master)
==> readme.html like as master template and its contains own placeholder and impliment placeholder id of master.html
-------------------------------------------
#extends /template/master.html
<impl-placeholder id="body">
    <!--Here create new placeholder-->
    <placeholder id="container">
    </placeholder>
</impl-placeholder>
<impl-placeholder id="header">
    #attach /template/header.html
</impl-placeholder>
-------------------------------------------
master.html ==> root master template
--------------------------------------------
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<placeholder id="header">
</placeholder>
<body>
    <placeholder id="body">
    </placeholder>
    #attach /template/footer.html
</body>
</html>
--------------------------------------------

see more about template /dist/project_template/www

server.js

You may create server.js file by you:

const { ConsoleColor, initilizeServer } = require( 'cwserver' );
let wwwName = void 0;
if ( process.argv.length > 2 ) {
    wwwName = process.argv[2];
} else {
    if ( process.env.APP_POOL_ID ) {
        wwwName = process.env[process.env.APP_POOL_ID];
    }
}
const server = initilizeServer( __dirname, wwwName );
const app = server.init();
process.on( 'exit', () => {
    console.log( "Exited..." );
} );
process.on( 'SIGINT', () => {
    server.log.error( "Caught interrupt signal" );
    server.log.error( "Application Exited..." );
    server.log.reset(); server.log.dispose();
    setTimeout( () => {
        process.exit( 0 );
    }, 200 );
} );
app.listen( server.port, () => server.log.write( `
    [+] Maintance      : https://www.fsys.tech
    [+] Server         : http://localhost:${server.port}
    [+] Socket         : ws://localhost:${server.port}${server.socketPath}
    [~] Running Server...
`, ConsoleColor.FgMagenta ) );

Read more about app.config.json
run node server your_app_dir_name or npm start your_app_dir_name

Package Sidebar

Install

npm i cwserver

Weekly Downloads

4

Version

4.0.0

License

MIT

Unpacked Size

1.13 MB

Total Files

137

Last publish

Collaborators

  • rajibchy