{"id":18977495,"url":"https://github.com/grandjs/grandjs","last_synced_at":"2025-04-19T17:23:19.733Z","repository":{"id":55951942,"uuid":"148303336","full_name":"grandjs/grandjs","owner":"grandjs","description":"A backend framework for solid web apps based on node.js","archived":false,"fork":false,"pushed_at":"2021-07-05T21:25:27.000Z","size":376,"stargazers_count":125,"open_issues_count":2,"forks_count":12,"subscribers_count":4,"default_branch":"master","last_synced_at":"2024-10-28T23:58:57.558Z","etag":null,"topics":["http-server","javascript","nodejs","typescript"],"latest_commit_sha":null,"homepage":"https://grandjs.netlify.app","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/grandjs.png","metadata":{"files":{"readme":"README.MD","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-09-11T10:56:49.000Z","updated_at":"2023-08-18T10:27:11.000Z","dependencies_parsed_at":"2022-08-15T10:10:45.094Z","dependency_job_id":null,"html_url":"https://github.com/grandjs/grandjs","commit_stats":null,"previous_names":["tareksalem/grandjs"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/grandjs%2Fgrandjs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/grandjs%2Fgrandjs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/grandjs%2Fgrandjs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/grandjs%2Fgrandjs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/grandjs","download_url":"https://codeload.github.com/grandjs/grandjs/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223707856,"owners_count":17189655,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["http-server","javascript","nodejs","typescript"],"created_at":"2024-11-08T15:29:17.944Z","updated_at":"2024-11-08T15:29:18.684Z","avatar_url":"https://github.com/grandjs.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\u003cimg width=\"200\" height=\"200\" src=\"https://i.ibb.co/t4MDdkq/grandjs.png\" alt=\"Grandjs logo\"\u003e\u003c/p\u003e\n\n# Grandjs\n\nA backend framework for solid web apps based on node.js\n\nYou want to build a solid web application but you don't want to use express and a lot of packages you need to build a basic website, Grandjs is one framework includes all main functionalities you need to build amazing, solid and secured web application without need for a ton of packages and libraries.\n\n* Grandjs is built for solid and extended web apps\n\n\n![GitHub contributors](https://img.shields.io/github/contributors/tareksalem/grandjs.svg?style=flat-square)\n![npm](https://img.shields.io/npm/v/grandjs.svg)\n![GitHub code size in bytes](https://img.shields.io/github/languages/code-size/tareksalem/grandjs.svg)\n![npm](https://img.shields.io/npm/dt/grandjs.svg?color=green\u0026style=popout)\n\n## Documentation\nyou can find the full documentation for Grandjs ecosystem [here](https://grandjs.netlify.app/)\n\n## Prerequisites\n\n1- you need to install node.js on your system\n2- init a new project using npm, so then we will be able to install this framework\n\n## Features\n* fewer packages and more productivity\n* Framework includes the most needed functionalities to build a perfect web app\n* depends on Handlebars template Engine which is friendly with many developers\n* solid routing system built on Javascript object-oriented programming and you can extend it as you need\n* controlled handling for every error page in your app\n* Grandjs is built for solid and extended web apps\n* Built in template engine using jsx\n* Extendable Routing System\n* Accepts Express Packages such as (body-parser, cookie-parser, morgan, cors)\n* built in cors Handler\nBuilt in request body parser\nUsable for Typescript Apps\n\n```javascript\n//require HTTP module\nconst http = require(\"http\");\n//require Grandjs framework\nconst Grandjs = require(\"grandjs\");\n\n// set the configuration of the framework\nGrandjs.setConfig({\n    //define the port\n    port: process.env.PORT || 3000,\n    // http is optional you can specify http or https, if you don't specify Grandjs automatically require HTTP module\n    http: http,\n    // if you specified https so you should ssl files in this object\n    httpsMode: {\n        key: fs.readFileSync('test/fixtures/keys/agent2-key.pem'),\n        cert: fs.readFileSync('test/fixtures/keys/agent2-cert.pem')\n    }\n    // define the static files container folder\n    staticFolder: {\n        // set the path of the folder of assets\n        path: path.join(process.cwd(), \"/public\"),\n        // set the global url that will be consumed by http request\n        url: \"/public\"\n    },\n        //set the encryption key, Grandjs uses encription key to cypher info\n    ENCRYPTION_KEY: \"ncryptiontestforencryptionproces\",\n    // use native request body parser or not\n    nativeParser: true || false,\n\n    //set error page for global error pages\n    errorPage(req, res) {\n        res.end(\"error page\");\n    }\n});\n\n// init Grandjs\nGrandjs.initServer();\n```\n**content**\n  - [Installing](#installing)\n  - [Getting Started](#getting-started)\n    - [Server configuration](#server-configuration)\n    - [Server Static](#server-static)\n    - [Cors]($cors)\n    -[Accessing Grandjs Server](#accessing-grandjs-server)\n    - [Grandjs MiddleWares](#grandjs-middlewares)\n    - [Router](#router)\n      - [extend Router class](#extend-router-class)\n      - [Router Static](#router-static)\n      - [define get routers](#define-get-routers)\n      - [define post routers](#define-post-routers)\n      - [Access on request and response objects](#access-on-request-and-response-objects)\n      - [Request object](#request-object)\n        - [Request params](#request-params)\n        - [Handle post request](#handle-post-request)\n        - [Request Uploaded Files](#request-uploaded-files)\n      - [Response object](#response-object)\n        - [``res.render`` function](#resrender-function)\n        - [``res.write`` function](#reswrite-function)\n        - [``res.end`` function](#resend-function)\n        - [``res.sendFile`` function](#ressendfile-function)\n        - [``res.json`` function](#resjson-function)\n        - [``res.redirect`` function](#resredirect-function)\n      - [middleWares](#middlewares)\n      - [Use Router class inside another router class](#Use-Router-class-inside-another-router-class)\n      - [TypeScript Decorators](#typescript-decorators)\n    - [Validation](#validation)\n      - [``validation.strip_html_tags`` function](#validationstriphtmltags-function)\n      - [``validation.checkEmail`` function](#validationcheckemail-function)\n      - [``validation.notEmpty`` function](#validationnotempty-function)\n      - [``validation.checkContainsNumber`` function](#validationcheckcontainsnumber-function)\n      - [``validation.checkIsNumber`` function](#validationcheckisnumber-function)\n    - [cryption](#cryption)\n      - [encrypt](#encrypt)\n      - [decrypt](#decrypt)\n    - [session](#session)\n    - [Auth module](#auth-module)\n    - [Flash Messages](#flash-messages)\n    - [Add MimeTypees](#add-mimetypes)\n    - [Grandjs File Upload](#grandjs-file-upload)\n    - [Socket Io Support](#socket-io-support)\n  - [Built With](#built-with)\n  - [Contributing](#contributing)\n  - [Versioning](#versioning)\n  - [Authors](#authors)\n  - [License](#license)\n  - [Acknowledgments](#acknowledgments)\n  - [JSX](#JSX)\n\n\n# Whats New ?\nGrandjs now supports the following\n- JSX Syntax for rendering dynamic content instead of using template engins\n- many of express packages are now compatible with Grandjs such as cookie-parser, session, flash, morgan, express-fileupload, body-parser\n- Typescript support!, Grandjs has major updates one of these updates is rebuilding the package again using typescript and changing the architecture of the project\n\n## Please don't Forget to support us by rating the project!, Also you can contribute us\n\n\n## Objectives\nWe aim to make grandjs the successor of express js with new vision, architecture, and modern javascript features like Router inheritance to build extendable, scalable web applications without repeating your self!\n\n## Installing\n\nopen the command prompt and navigate to the project folder and just say\n\n```\nnpm install grandjs --save\n```\n## Getting Started\n### Server configuration\nto start with Grandjs just install it and call it in your file as the following\n**Javascript**\n```javascript\n//require Grandjs framework in javascript\nconst {Server, Router, Request, Response} = require(\"grandjs\");\n```\n\n**Typescript**\n```typescript\nimport {Server, Router, Request, Response} from \"grandjs\"\n```\n\nif you want to require HTTP or HTTPS module to pass it to Grand js you can, in all cases, Grandjs behind the seen requires HTTP module as a default.\n\nNow you need to call setConfig function to set some configuration for the project\n\n```javascript\nGrandjs.setConfig({});\n```\n**this function takes one parameter as an object**\n\n**Example on all configuration**\n```javascript\n\n//javascript\nconst {Server, Router} = require(\"grandjs\");\n\n//typescript\nimport {Server, Router} from \"grandjs\";\n\n// define Grandjs configuration\nServer.setConfig({\n    //define the port\n    port: process.env.PORT || 3000,\n    // http is optional you can specify http or https, if you don't specify Grandjs automatically require HTTP module\n    http: http,\n    // if you specified https so you should ssl files in this object\n    httpsMode: {\n        key: fs.readFileSync('test/fixtures/keys/agent2-key.pem'),\n        cert: fs.readFileSync('test/fixtures/keys/agent2-cert.pem')\n    },\n    // define the static files container folder\n    staticFolder: {\n        // set the path of the folder of assets\n        path: path.join(process.cwd(), \"/public\"),\n        // set the global url that will be consumed by http request\n        url: \"/public\"\n    },\n    //set the encryption key, Grandjs uses encription key to cypher info\n    ENCRYPTION_KEY: \"ncryptiontestforencryptionproces\",\n    // use native request body parser or not\n    nativeParser: true || false,\n\n    //set error page for global error pages\n    errorPage(req, res) {\n        res.end(\"error page\");\n    },\n    // configure cors\n    cors : {\n        origin: '*',\n        methods: 'GET,HEAD,PUT,PATCH,POST,DELETE',\n        preflightContinue: false,\n        optionsSuccessStatus: 204\n    }\n})\n```\n\n\nuntil now Grandjs doesn't work so you need to call \"init function\" to initialize the server\n```javascript\nServer.initServer();\n```\n\n### Server Static\nGrandjs Exposes a function that allows you to specify static and assets directories easily with one function!\n\nThis function is called `Server.static`, this function takes one parameter as an object with the following properties\n\n|property|type|required|description|\n|-|-|-|-|\n|url|string|true|the exposed url that will be resolved when it requested|\n|path|string|true|the internal path that will be resolved to read the files from it|\n|middlewares|Array\u003cfunction\u003e|true|A set of middlewares that you can apply before reading the files or resolve the directory|\n\n**Example**\n\n```typescript\nclass MainRouter extends Router{}\nconst mainRouter = new MainRouter({base: \"/\"});\n\nmainRouter.static({\n    url: \"/assets\",\n    path: path.join(process.cwd(), \"/my-internal-assets\")\n})\n\n```\n\n### Cors\nGrandjs uses Cors Module which is used in express, you can use the default settings of it as you use in expressjs\n\nGrandjs installs cors and set default configuration automatically, however you can set your own configurations\n\n\n### Cors Configuration\nGrandjs allows you to set cors configuration on multiple level of routes as the following:\n- cors setting over all app routes\n**Example**\n\n```javascript\n// javascript\nconst {Server} = require(\"grandjs\");\n// typescript\n\nimport {Server} from \"grandjs\";\n\nServer.setConfig({\n    cors : {\n        origin: '*',\n        methods: 'GET,HEAD,PUT,PATCH,POST,DELETE',\n        preflightContinue: false,\n        optionsSuccessStatus: 204\n    },\n\n})\n```\n- cors setting over specific Router \"group of routes\"\n**Example**\n\n```javascript\n// javascript\nconst {Server, Router} = require(\"grandjs\");\n// typescript\n\nimport {Server, Router} from \"grandjs\";\nclass HomeRouter extends Router{\n    constructor(options) {\n        super(options);\n        this.cors = {\n            origin: '*',\n            methods: 'GET,HEAD,PUT,PATCH,POST,DELETE',\n            preflightContinue: false,\n            optionsSuccessStatus: 204\n        };\n    }\n}\n```\n- cors setting over specific route\n**Example**\n\n```javascript\n// javascript\nconst {Server, Router} = require(\"grandjs\");\n// typescript\n\nimport {Server, Router} from \"grandjs\";\nclass HomeRouter extends Router{\n    constructor(options) {\n        super(options);\n        this.getRouters = [this.homePage()];\n    }\n    homePage() {\n        return {\n            cors: {\n                origin: '*',\n                methods: 'GET,',\n                preflightContinue: false,\n                optionsSuccessStatus: 204\n        }   ,\n            //define the url of router\n            url: \"/\",\n            // define the method of the router\n            method: \"GET\",\n            handler: () =\u003e {\n                // handle the request and do the functionalities\n            }\n        }\n    }\n}\n```\n\n### Accessing Grandjs Server\nAfter initializing grandjs, maybe you want to use the created server or access on it's properties so you can access on grandjs node server via this property from grandjs\n\n```javascript\n// javascript\nconst {Server} = require(\"grandjs\");\n// typescript\n\nimport {Server} from \"grandjs\";\n\n\nServer.Server\n// -\u003e http Server\n```\n\n\n### Grandjs MiddleWares\nas every nodejs developer used to add middleware to the express app to be executed before the routes, grandjs does also something similar\n\nIn grandjs you have three types of middlewares\n- global middleare over app\n- global middleware over single router class (group of routes)\n- private middleware over single route\n\nwe will explain the last two types of middlewares in the Router section, but here we will talk about global middlewares over app.\n\nGlobal middlewares over app are middlewares you want to run before executing any router in the app, this type of middlewares often is used for injecting dependencies in the app or make global settings for the whole app.\n\nto set global middleware you can use `Server.use` function as the following:\n\n```javascript\n// javascript\nconst {Server} = require(\"grandjs\");\n// typescript\n\nimport {Server} from \"grandjs\";\nServer.setConfig({});\n\n// add global middleware here\nServer.use();\nServer.initServer();\n```\n`Server.use` function takes one argument which should be a function, this function has regular three arguments as the following:\n```javascript\nServer.use((req, res, next) =\u003e {\n    // continue\n    return next();\n});\n```\n\n- `req` is the incoming request object\n- `res` is the response object to send response or set headers\n- `next` is a function to call to continue to the next middleware or to start executing the routers\n\n\n**Note**\n\nGrandjs takes the function which passed in `use` function and pushes it to an array of middlewares which will be executed later when a route hs requested, so these middlewares will be executed by their arrange inside the array.\nTo continue to the next global middleware or to start executing the matched router class you have to call `next` function, without it the routes will not be executed.\n\n### Router\n\n* Grandjs Routing system is built upon object-oriented programming, so Router is a class inside Grandjs you extend it and add routes to it as you wanna\n\n**to work with router class you need to extend it or instatiate it directly and every class implies a group of routes have a specific base url**\n\n\n#### extend Router class\n\n```javascript\n// javascript\nconst {Server, Router} = require(\"grandjs\");\n// typescript\n\nimport {Server, Router} from \"grandjs\";\nclass HomeRouter extends Router{\n    constructor(options) {\n        super(options);\n    }\n}\n```\n\nAs any extended class, you should call the super inside the constructor and pass the options parameter\n\n| parameter   |     type   |\n|----------|:-------------:|\n| options |  Object |\n\nNow after defining the class, you should define the get routers which related to this class\nRouter class has a property called \"getRouters\" this is an array and you push inside it the routers you add within the class with the GET method\n\n**Example**\n\n```javascript\nclass HomeRouter extends Router{\n    constructor(options) {\n        super(options);\n        this.getRouters = []\n    }\n}\n```\n\n**you can add routers which related to this class as methods inside the class and every method you use it as a router it should return an object has the following properties**\n\n|Property   |  type |  description |\n|---|---|---|\n|  URL |  string (required)| the URL of the router  |\n| method  |  string (required) |  HTTP method get / post / patch / put / delete |\n| handler  |  function (required) | the function you want to run when the request URL matches the router url  |\n| middleWares  | array (optional)  |  if you want to run a function or more to check about something before running the final handler of the router |\n\n\n### Router Static\nGrandjs Exposes a function that allows you to specify static and assets directories easily with one function!\n\nThis function is called `Router.static`, this function takes one parameter as an object with the following properties\n\n|property|type|required|description|\n|-|-|-|-|\n|url|string|true|the exposed url that will be resolved when it requested|\n|path|string|true|the internal path that will be resolved to read the files from it|\n|middlewares|Array\u003cfunction\u003e|false|A set of middlewares that you can apply before reading the files or resolve the directory|\n\n**Example**\n\n```typescript\nclass MainRouter extends Router{}\nconst mainRouter = new MainRouter({base: \"/\"});\n\nmainRouter.static({\n    url: \"/assets\",\n    path: path.join(process.cwd(), \"/my-internal-assets\")\n})\n\n```\n\n### Define get routers\n\n**Example**\n\n```javascript\n// javascript\nconst {Server} = require(\"grandjs\");\n// typescript\n\nimport {Server} from \"grandjs\";\nclass HomeRouter extends Router{\n    constructor(options) {\n        super(options);\n\n        //push the homePage method route into getRouters array\n        this.getRouters.push(this.homePage());\n    }\n    homePage() {\n        return {\n            //define the url of router\n            url: \"/\",\n            // define the method of the router\n            method: \"GET\",\n            handler: (req, res) =\u003e {\n                // handle the request and do the functionalities\n            }\n        }\n    }\n}\n```\n\n\n### Define post routers\n\n**Example**\n\n```javascript\nclass HomeRouter extends Grandjs.Router{\n    constructor(options) {\n        super(options);\n\n        //push the homePage method route into getRouters array\n        this.postRouters.push(this.homePagePost());\n    }\n    homePagePost() {\n        return {\n            //define the url of router\n            url: \"/\",\n            // define the method of the router\n            method: \"POST\",\n            handler: (req, res) =\u003e {\n                // handle the request and do the functionalities\n            }\n        }\n    }\n}\n```\n\n### instantiate router class\n\n**Example**\n\n```javascript\n// javascript\nconst {Server, Router} = require(\"grandjs\");\n// typescript\n\nimport {Server, Router} from \"grandjs\";\nclass HomeRouter extends Router{\n    constructor(options) {\n        super(options);\n\n        //push the homePage method route into getRouters array\n        this.getRouters = [this.homePage()];\n    }\n    homePage() {\n        return {\n            //define the url of router\n            url: \"/\",\n            // define the method of the router\n            method: \"GET\",\n            handler: () =\u003e {\n                // handle the request and do the functionalities\n            }\n        }\n    }\n}\n// instantiate the class\nconst homeRoters = new HomeRouter({base: \"/\"});\n```\n\nwhen you instantiate the class you should define the options parameter as an object includes two properties\n\n| property   |     type   |descriptions |\n|----------|:-------------:|-----: |\n| base |  string (required) | implies the base URL you want to add routers to it. so if you defined it as \"/admin\" all routers inside this class would be added to /admin|\n| staticFolder  | object(optional)  | the name of the folder you want to serve assets and static files from it. The default value of it is the global staticFolder that you specified in setConfig function\n| staticFolder.path  | string(optional)  |the path to read files from|\n|staticFolder.url|string|the url that will resolve the static and assets content|\n\n**Example**\n\n```javascript\nconst homeRoters = new HomeRouter({\n    base: \"/\"\n});\n```\n####  Note\nyou can also specify the basename of the router class inside the class constructor as the following:\n\n```javascript\nclass HomeRouters extends Router{\n    constructor() {\n        this.base = \"/admin\"\n    }\n}\n```\n\nif you follow this pattern so you don't need to add base property when you instantiate the class because the base will be passed before\n\n\n### Build Router\n\nafter instantiating the router, to make it works you need to call `build` method to start building and constructing the router\n\n```javascript\n\nconst homeRoters = new HomeRouter({\n    base: \"/\"\n});\n// this builds the router to be ready for runtime execution\nhomeRouters.build();\n```\n**Note**\n\nBuilding routers should be before `Server.initServer` method\n\u003c!-- \u003chr style=\"border:.5px solid black;height:0\"\u003e --\u003e\n### Access on request and response objects\n\nto handle the routers and check requests and responses you need to access them, so these objects are accessible using different ways\n\n1- req \u0026 res objects are properties inside the class\n\n**Example**\n\n```javascript\nclass HomeRouter extends Router{\n    constructor(options) {\n        super(options);\n\n        //push the homePage method route into getRouters array\n        this.getRouters = [this.homePage()];\n    }\n    homePage() {\n        return {\n            //define the url of router\n            url: \"/\",\n            // define the method of the router\n            method: \"GET\",\n            handler: () =\u003e {\n                // handle the request and do the functionalities\n                //request object: this.req\n                // response object: this.res\n                //console the request object headers\n                console.log(this.req.headers);\n                this.res.end(\"hello home page\");\n            }\n        }\n    }\n}\n```\n\n2- request \u0026 response are accessable as parameters inside handler function\n\n**Example**\n\n```javascript\nhomePage() {\n    return {\n        url: \"/\",\n        method: \"get\",\n        handler: (req, res) =\u003e {\n            console.log(req.headers);\n            res.end(\"hello home page\");\n        }\n    }\n}\n```\n\u003c!-- \u003chr style=\"border:.5px solid black;height:0\"\u003e --\u003e\n\n#### Specify a separated folder for static files for this group of routes\n\n```javascript\nconst homeRoters = new HomeRouter({\n    base: \"/\",\n    //specify the container folder fo static file for all routes inside this class\n    // front path\n    staticFolder: {\n        path: path.join(process.cwd(), \"/assets\"),\n        url: \"/assets\"\n    },\n});\n```\n\u003c!-- \u003chr style=\"border:.5px solid black;height:0\"\u003e --\u003e\n\n#### Router add route\n\nThis function enables you to add routers to the class from outside it\n\n```javascript\nhomeRoters.addRoute(obj);\n```\nthis function takes one (required) parameter as an object has the following properties\n\n|Property   |  type |  description |\n|---|---|---|\n|  URL |  string (required)| the URL of the router  |\n| method  |  string (required) |  HTTP method get / post / patch / put / delete |\n| handler  |  function (required) | the function you want to run when the request URL matches the router url  |\n| middleWares  | array (optional)  |  if you want to run a function or more to check about something before running the final handler of the router |\n\n**Example**\n\n```javascript\n// javascript\nconst {Server, Router} = require(\"grandjs\");\n// typescript\n\nimport {Server, Router} from \"grandjs\";\nconst adminRoute = new Router({\n    baes: \"/admin\"\n})\n// add main route to admin base\nadminRoute.addRoute({\n    url: \"/\",\n    method: \"get\",\n    handler: (req, res) =\u003e {\n        res.end(\"hello admin\");\n    }\n});\n// add profile page route to admin base\nhomePage.addRoute({\n    url: \"/profile\",\n    method: \"get\",\n    handler: (req, res) =\u003e {\n        res.end(\"hello profile\");\n    }\n});\n```\n\u003c!-- \u003chr style=\"border:.5px solid black;height:0\"\u003e --\u003e\n\n### Router class errorPage\n\nyou can specify a custom error page for every class you instantiate it to control on error links in a group of routes\nto do that you need to define \"errorPage\" method to the class\n\n1- define it inside the class\n\n**Example**\n\n```javascript\nclass HomeRouter extends Grandjs.Router{\n    constructor(options) {\n        super(options);\n    }\n    homePage() {\n        return {\n            url: \"/\",\n            method: \"get\",\n            handler: () =\u003e {\n                this.res.end(\"hello home page\");\n            }\n        }\n    }\n    aboutPage() {\n        return {\n            url: \"/about\",\n            method: \"get\",\n            handler: () =\u003e {\n                this.res.end(\"hello about page\");\n            }\n        }\n    }\n    // customize error page\n    errorPage() {\n        this.res.end(\"error page\")\n    }\n}\n```\n2-Define error page from outside the class\n\n**Example**\n\n```javascript\nconst homeRouter = new Router({\n    baes: \"/\"\n})\n// add main route to admin base\nhomeRouter.addRoute({\n    url: \"/\",\n    method: \"get\",\n    handler: (req, res) =\u003e {\n        res.end(\"hello homepage\");\n    }\n});\n// add profile page route to admin base\nhomeRouter.addRoute({\n    url: \"/about\",\n    method: \"get\",\n    handler: (req, res) =\u003e {\n        res.end(\"hello aboutpage\");\n    }\n});\nhomeRouter.errorPage = (req, res) =\u003e {\n    res.end(\"error page\");\n}\n```\n\n**not** that if you didn't define error page for the router class it automatically call error page which you specified in setConfig function\n\n### Global middleWares\n\nGlobal middleware is a way to apply middlewares on a class which includes a group of routers\n\nglobalMiddleWares is an array inside the class you can define it inside the constructor and put inside it functions that you want to run when the client requests the base name of that class\n\n**Example**\n```javascript\nclass HomeRouter extends Router{\n    constructor(options) {\n        super(options);\n        // you can add one middleWare or more and it would be applied according to the arrangment\n        this.globalMiddleWares = [this.sendMessage]\n    }\n    sendMessage(req, res, next) {\n        res.write(\"message from middleWare\");\n        // continue to the next hanlders\n        next();\n    }\n    homePage() {\n        return {\n            url: \"/\",\n            method: \"get\",\n            handler: () =\u003e {\n                this.res.end(\"hello home page\");\n            }\n        }\n    }\n    aboutPage() {\n        return {\n            url: \"/about\",\n            method: \"get\",\n            handler: () =\u003e {\n                this.res.end(\"hello about page\");\n            }\n        }\n    }\n    // customize error page\n    errorPage() {\n        this.res.end(\"error page\")\n    }\n}\n```\n\n**not that the middlWares array can include many middleWare functions and the middleWares are applied according to the indexing inside the array**\n\nEvery middleWare has three parameters\n\n| parameter  | type  | description  |\n|---|---|---|\n| req  | object  | implies the coming request object contains all information about the request  |\n|res   | object  | represents the response object  |\n| next  | function  | is a function you can execute it to continue to the next middleware or to the final handler of the router  |\n\n### Router URL define params\n\nyou can add params to the URL of the router to make dynamic routes like the following:\n\n```javascript\nurl: \"/posts/:postId\"\n```\nto access the parameters inside the URL using [request.params property](#request-params)\n\n**Example**\n\n```javascript\nconst homePage = new Router({\n    baes: \"/\"\n})\nhome.addRoute({\n    url: \"/posts/:postId\",\n    method: \"get\",\n    handler: (req, res) =\u003e {\n        console.log(req.params);\n    }\n});\n```\n\u003c!-- \u003chr style=\"border:.5px solid black;height:0\"\u003e --\u003e\n\n#### Request Object\nthis is an object you can access on it inside the handler of the route\nand the object contains all information about the request which is coming\n\n|Property   |  type |  description |\n|---|---|---|\n| req.method  | string  | returns the method of the current request  |\n|  req.pathname |  string |  returns the requested URL without query string |\n|req.path  |  string | returns the requested URL with query string |\n|req.href  |  string | returns the requested URL with query string |\n| req.url  |  object | returns object contains the parsed URL  |\n|req.query   |  object | contains the query \u0026 search in the URL(it parsed as key and value)  |\n| req.params  |  object | returns the query parameters if it exists as key and value  |\n| req.validation  | object  | returns an object contains some helper functions to validate the email and string  |\n| req.data  | object  | returns an object contains the posted data if the method is \"post\"  |\n| req.body  | object  | returns an object contains the posted data if the method is \"post\"  |\n|  req.headers | object  | returns the headers of the coming request  |\n| req.flash  | object  |  this object enables you to set messages to send it to handlebars to show to the user |\n\n#### Request params\nreturns an object contains the parameters of the router URL and it's value if it exists\nif there are no params so it returns an empty object\n\n**Example**\n\n```javascript\nconst homePage = new Router({\n    baes: \"/\"\n})\nhome.addRoute({\n    url: \"/posts/:category\",\n    method: \"get\",\n    handler: (req, res) =\u003e {\n        // user requested http://localhost:300/posts/tech?postId=2\n        console.log(req.params); //output {category:\"tech\"};\n        console.log(req.query) //output {postId: 2}\n        console.log(req.pathname) //output /posts/tech\n        console.log(req.path) //output /posts/tech?postId=2\n        console.log(req.href) //output /posts/tech?postId=2\n        console.log(req.method) //output \"get\"\n        console.log(req.url)\n        console.log(req.body);\n        console.log(req.data);\n        /* output\n        Url {\n        protocol: null,\n        slashes: null,\n        auth: null,\n        host: null,\n        port: null,\n        hostname: null,\n        hash: null,\n        search: '?postId=2',\n        query: 'postId=2',\n        pathname: '/posts/tech',\n        path: '/posts/tech?postId=2',\n        href: '/posts/tech?postId=2' }\n        */\n    }\n});\n```\n\n\u003c!-- \u003chr style=\"border:.5px solid black;height:0\"\u003e --\u003e\n\n#### Handle post request\n\nGrandjs handles all types of post requests and submitted data and returns them as an object called ``req.data`` and another property `req.body` this object contains all the submitted data and you can access on it inside the handler function if the method of the router is post\n\n**Example**\n\n```javascript\npostAdminPage() {\n    return {\n        method: \"post\",\n        url: \"/admin/addinfo\",\n        handler: (req, res) =\u003e {\n            console.log(req.data || req.data) //output {} contains all submitted info\n        }\n    }\n}\n```\n\n\n#### Request Uploaded Files\n\nIn Grandjs You can upload files easily without any extra settings, all you should do is specifying Request header as `multipart/form-data`\n\nGrandjs Uses multiparty package for file uploading\n\nYou can access on the uploaded files via `files` property in the request object as the following:\n\n```javascript\npostAdminPage() {\n    return {\n        method: \"post\",\n        url: \"/admin/uploadInfo\",\n        handler: (req, res) =\u003e {\n            console.log(req.files) //output {} contains all uploaded files\n        }\n    }\n}\n```\n\n`req.files` property is an object which includes the uploaded files as properties, each property incarnates the uploaded file as an object, but if there are multiple files uploaded with the same filed name so they will be grouped together inside the property name as an array of objects\n\neach object has the following properties:\n\n```javascript\n{\n      name: 'images' // the name of the filed,\n      filename: 'download (1).jpeg' // original file name,\n      data: \u003cBuffer\u003e // the file content as buffer,\n      size: 14473 // size of file,\n      extension: '.jpg' // the extension type of file,\n      mimetype: 'image/jpeg' // mime type of file,\n      stream: [Duplex] // ability to use this file to stream it,\n       headers: [Object] // the sent headers with this file,\n      byteOffset: 147,\n      byteCount: 27975 // bytes count\n\n```\n**Note**\n\nFor Request Body parsing you have two options\n\n1- use native Grandjs request parser which will also parse request with formdata\n\n2- use `body-parser` package for parsing json requests and use `express-fileupload` for parsing `multipart/form-data` request body\n\n\n#### Response Object\n\nthis is an object you can access on it inside the handler of the route\nThis object contains all methods that you need to send a response or content to the coming request\n\n#### ``res.render`` function\n\nThis function you use it to render HTML content using JSX Stateless Components\n\n```javascript\nres.render()\n```\ntakes one parameter as an object, this object should contain the following properties\n\n| property  |  type | description |\n|---|---|---|\n|  Component |  Function | A functional Component written in JSX Syntax to be rendered as an HTML|\n| data  | object (optional)  | object contains the data you want to render inside the rendered component\n\n**Example**\n\nCreate App.jsx File\n```jsx\n// import View here (mandatory)\n// javascript\nconst {View} = require(\"grandjs\");\n\n// typescript\nimport {View} from \"grandjs\";\nconst App = (props) =\u003e {\n    return (\n        \u003cdiv\u003e\n            Hello world\n            \u003ch2\u003e{props.message}\u003c/h2\u003e\n        \u003c/div\u003e\n    )\n}\n// use native exporting method either for typescript or javascript\nmodule.exports = App\n```\n\n```javascript\n// javascript\nconst {Server, Router, View} = require(\"grandjs\");\n\n// typescript\nimport {Server, Router, View} from \"grandjs\";\n\n// load jsx file\nconst App = View.importJsx(\"./App.jsx\");\n    homePageRouter() {\n        return {\n            url: \"/\",\n            method: \"get\",\n            handler: () =\u003e {\n                // render jsx component\n                this.res.render(App, {message: \"Hello Grandjs\"})\n            }\n        }\n    }\n```\n\n#### ``res.write`` function\n\nthis function is like the native api of node.js, it allows you to send strings to the client\n\n```javascript\nres.write(\"hello world\");\n//end the response\nres.end(\"\");\n```\n\n#### ``res.end`` function\nthis function is like the native api of node.js, it allows you to send strings to the client\n\n```javascript\nres.end(\"hello world\");\n```\n\n\n#### ``res.sendFile`` function\n```javascript\nres.sendFile(path);\n```\nthis function takes on parameter\n\n|parameter   |  type | description  |\n|---|---|---|\n|  path |  String (required) | this parameter should specify the path of the file which you want to send |\n\nthis function uses promise to return a ``catch`` function if the file isn't exist\n\n**Example**\n\n```javascript\nres.sendFile(\"/views/pages/home.html\").catch((err) =\u003e {\n    console.log(err) //output no such file\n})\n```\n\n#### ``res.json`` function\n\nthis function sends json data, it accepts one parameter this parameter should be an object and Grandjs stringify this object automatically\n\n```javascript\nres.json({user: \"tarek\", email: \"test@gmail.com\", id: 1});\n```\n\n#### ``res.redirect`` function\nThis function is used to make redirect to another link\nIt accepts one parameter\n\n|parameter   |  type | description  |\n|---|---|---|\n|  url |  String (required) | this parameter should specify url that you want to redirect to |\n\n```javascript\nres.redirect(\"/anotherurl\");\n```\n\n### ``res.status`` function\nthis function sets the status of the response with http status code, it accepts one parameter which is the status code of the response\n\n```javascript\n\nres.status(200).json({user: \"tarek\", email: \"test@gmail.com\", id: 1});\n```\n\n#### MiddleWares\nmiddleWares is a group of functions used to run something before executing the final handler\n\nthe middWares property should be an array includes the functions\n\nEvery middleware should have three parameters\n\n| parameter  | type  | description  |\n|---|---|---|\n| req  | object  | implies the coming request object contains all information about the request  |\n|res   | object  | represents the response object  |\n| next  | function  | is a function you can execute it to continue to the next middleWare or to the final handler of the router  |\n\n**Example**\n\n```javascript\n//middle ware\nfunction writeWithMiddleware(req, res, next) {\n    // has three parameters\n    /*\n    1- req: the request object\n    2- res: the response object\n    3- next: a function you execute it to continue to the handler\n    */\n   res.write(\"from middleware\");\n   next();\n}\nhomePage() {\n    return {\n        url: \"/home\",\n        middleWares: [],\n        method: \"get\",\n        handler: (req, res) =\u003e {\n            res.end(\"hello home page\");\n\n            // final output on the browser:\n            //from middleware\n            //hello home page\n        }\n    }\n}\n```\n\n**note that the middlWares array can include many middleWare functions and the middleWares are applied according to the indexing inside the array**\n\n#### Use Router class inside another router class\nyou can build a router class and append another router class to its parent, This is designed for special use case as the following:\nsuggest you have parent router class has basename `/admin`\nand you want to group some of routes to manage products for example so the default way you can create another class with basename `/admin/products`\nso we came up with the solution to use router classes inside another routing classes which give you the flexibility to use child routes inside parent route as the following:\n\n```javascript\n// admin product routes\nclass ProductRoutes extends Router{\n    constructor(options) {\n        super(options);\n        // add post routers to the array\n        this.postRouters = [this.addProduct()]\n    }\n    addProduct() {\n        return {\n            url: \"/product\",\n            method: \"POST\",\n            handler: (req, res) =\u003e {\n                console.log(req.data);\n            }\n        }\n    }\n}\n\n// admin router\nclass AdminRoutes extends Router{\n    constructor(options) {\n        super(options)\n        this.getRouters = [this.homePage()];\n        // use child router class\n        this.useRouter(ProductRoutes)\n    }\n    homePaage() {\n        return {\n            url: \"/\",\n            method: \"GET\",\n            handler: (req, res) =\u003e {\n                res.end(\"home page!\");\n            }\n        }\n    }\n}\n```\n\n## TypeScript Decorators\nIf you are using typescript wit Grandjs, you can use decorators to decorate your route methods!\nCurrently grandjs supports the following decorators\n\n- `GET` (for get methods)\n- `POST` (for post methods)\n- `PATCH` (for patch methods)\n- `PUT` (for put methods)\n- `DELETE` (for delete methods)\n- `MiddleWare` (for methods that act as middleWares)\n\n**Example**\n```typescript\nimport {Router, Request, Response} from \"grandjs\"\nimport {GET, POST, PATCH, PUT, DELETE, MiddleWare} from \"grandjs\";\n\nclass UserRouter extends Router{\n  // get user page\n  @GET({url: \"/user\"})\n  getUserPage(req: Request, res: Response) {\n    return res.status(200).json({status: 200, message: \"hello world\"});\n  }\n  // middleware\n  @MiddleWare\n  userMiddleWare(req: Request, res: Response, next: Function) {\n    // check the user\n    if(req.user) {\n      // continue\n      return next();\n    } else {\n      return res.status(401).json({status: 401, message: \"user is not authorized\"});\n    }\n  }\n}\n```\n**Note**\nthe decorator function injects the method into the proper array of methods, so if you use `@GET` decorator it will be injected in `getRouters` array, the same thing for other routes, if you use `@MiddleWare` decorator, it will inject the method in `globalMiddleWares` array\n\n### Validation\n\nGrandjs includes awesome validation system to validate inputs and remove strip tags and check the correct email\n**you can access on validation using on of two ways**\n1- importing the module\n\n**Example**\n\n```javascript\n//javascript\nconst {validation} = require(\"grandjs\");\n\n// typescript\nimport {validation} from \"grandjs\";\n```\n\n2- as a property inside the request object\n\n```javascript\nconst handler = (req, res) =\u003e {\n    console.log(req.validation);\n}\n```\n\n#### ``validation.striphtmltags`` function\n\nthis function removes weird characters from the string to insure that there is no harmful characters inside the string\n```javascript\nlet str = \"h1hello worldh1\"\nGrandjs.helpers.validation.strip_html_tags(str) // output hello world\n```\n\n\u003c!-- \u003chr style=\"border:.5px solid black;height:0\"\u003e --\u003e\n\n#### ``validation.checkEmail`` function\nThis function checks if the string is emain or not\n\n\nthis function takes two parameters\n\n| parameter  | type  |  description |\n|---|---|---|\n| email  |  string (required) | this parameter is required and it should be a string that you want to test it as email or not |\n|  cb |  function (optional) |  this is a callback function you can call it and includes one parameter either be true or false  |\n\nThis function you can call it async with a callback function or sync without callback\n\n1- with callback function\n```javascript\nGrandjs.helpers.validation.checkEmail(\"test@gmail.com\", (email) =\u003e {\n    if(email) {\n        console.log(email) //output true if it email\n    } else {\n        console.log(email) // output false if itsn't email\n    }\n});\n```\n2- without callback\n```javascript\nlet email = Grandjs.helpers.validation.checkEmail(\"test@gmail\");\nconsole.log(email) // returns true if it email, if not,  returns false\n```\n\u003c!-- \u003chr style=\"border:.5px solid black;height:0\"\u003e --\u003e\n#### ``validation.notEmpty`` function\n\nThis function checks if the given string is empty or not\n\nit accepts two parameters\n\n| parameter  | type  |  description |\n|---|---|---|\n| string  |  string (required) | to test it is empty or not |\n|  cb |  function (optional) |  this is a callback function you can call it and includes one parameter either be true or false  |\n\nThis function you can call it async with a callback function or sync without callback\n\n1- with callback function\n\n```javascript\n\nGrandjs.helpers.validation.notEmpty(\"\", (notEmpty) =\u003e {\n    if(notEmpty) {\n        console.log(notEmpty) //output true if it is not empty\n    } else {\n        console.log(notEmpty) // output false if it is empty\n    }\n});\n```\n\n2- without callback\n\n```javascript\n\nlet notEmpty = Grandjs.helpers.validation.notEmpty(\"\");\nconsole.log(email) // returns true if it isn't empty, if it is empty,  returns false\n```\n\u003c!-- \u003chr style=\"border:.5px solid black;height:0\"\u003e --\u003e\n#### ``validation.checkContainsNumber`` function\n\nThis function checks if the given string contains numbers or not\n\nit accepts three parameters\n\n| parameter  | type  |  description |\n|---|---|---|\n| string  |  string (required) | to test it contains numbers or not |\n|  count | Number (required)  |  refers to the count of the number you want to test the string contains. if you specify it for example 5 so the function checks if the given string contains five numbers |\n|  cb |  function (optional) |  this is a callback function you can call it and includes one parameter either be true or false  |\n\nThis function you can call it async with a callback function or sync without callback\n\n1- with callback function\n\n```javascript\nGrandjs.helpers.validation.checkContainsNumber(\"Grandjs32test1\", 3, (containsNumbers) =\u003e {\n    if(containsNumbers) {\n        console.log(containsNumbers) //output true if it contains number\n    } else {\n        console.log(containsNumbers) // output false if it doesn't contain three numbers\n    }\n});\n```\n\n2- without callback\n\n```javascript\nlet containsNumbers =\nGrandjs.helpers.validation.checkContainsNumber(\"Grandjs32test1\", 3);\nconsole.log(containsNumbers) // returns true if it contains 3 numbers, returns false if not\n```\n\u003c!-- \u003chr style=\"border:.5px solid black;height:0\"\u003e --\u003e\n#### ``validation.checkIsNumber`` function\n\nThis function checks if the given parameter is a number or not\nyou can use this function to authenticate phone number and stuff like that\n\nit accepts two parameters\n\n| parameter  | type  |  description |\n|---|---|---|\n| value  |  any (required) | to test it is number or not |\n|  cb |  function (optional) |  this is a callback function you can call it and includes one parameter either be true or false  |\n\nThis function you can call it async with a callback function or sync without callback\n\n1- with callback function\n\n```javascript\nlet test = 1222;\nGrandjs.helpers.validation.checkIsNumber(test, (number) =\u003e {\n    if(number) {\n        console.log(number) //output true if it is number\n    } else {\n        console.log(number) // output false if it isn't number\n    }\n});\n```\n2- without callback\n```javascript\nlet test = 1222;\nlet number = Grandjs.helpers.validation.checkIsNumber(test);\nconsole.log(number) // returns true if it is number, returns false if not\n```\n\n\n### Cryption\nGrandjs gives you functionalities to crypt important info and cipher them and decrypt them\nencryption functions are inside helpers inside grandjs library\nThis helper uses the ``ENCRYPTION_KEY`` that you specify in ``setConfig`` function.\n\n**not that the length of ``ENCRYPTION_KEY`` should be 32 character**\n\n#### enCrypt\n```javascript\n\nGrandjs.helpers.enCrypt(text);\n\n```\n\nThis function takes one parameter which refers to the string you wanna encrypt or cipher it\n\n|parameter   | type  | description  |\n|---|---|---|\n| text  | string (required)  | implies the text that you wanna cipher it |\n\nThis function rreturns the string after cipher it\n\n```javascript\nconst {Cipher} = require(\"grandjs\");\n// encrypt password\nlet encryptedPassword = Cipher.enCrypt(\"passowrd\");\n```\n\n\n#### deCrypt\n\n```javascript\n\nconst {Cipher} = require(\"grandjs\");\nCipher.deCrypt(text);\n```\nThis function takes one parameter which refers to the string you wanna decrypt or decipher it\n\n|parameter   | type  | description  |\n|---|---|---|\n| text  | string (required)  | implies the text that you wanna decipher it |\n\nThis function rreturns the string after decipher it\n\n```javascript\n// encrypt password\nlet decryptedPassword = Grandjs.helpers.deCrypt(\"passowrd\");\n```\n\u003c!-- \u003chr style=\"border:.5px solid black;height:0\"\u003e --\u003e\n\n\n### Session\n\nThis Module is deprecated, you can use [Express session](https://www.npmjs.com/package/express-session) and [Cookie-parser](https://www.npmjs.com/package/cookie-parser) instead!\n\n### Flash Messages\n\nThis Module is deprecated, you can use [express flash messages](https://www.npmjs.com/package/express-flash) instead!\n\n**Example**\n\n```javascript\n// javascript\nconst {Server} = require(\"grandjs\");\n// typescript\nimport {Server} = from \"grandjs\";\n\nconst flash = require('express-flash'),\nconst session = require('express-session')\nconst cookieParser = require(\"cookie-parser\");\nServer.use(cookieParser('keyboard cat'));\nServer.use(session({ cookie: { maxAge: 60000 }}));\nServer.use(flash());\n```\n## Add MimeTypes\n\n\n\nif you want to serve more static files with another mimetype not exist in our built in mimetypes, so you can use the following function\n\n```javascript\n\nServer.addMimeTypes(extention, mimeType);\n```\n\nThis function takes two parameters\n\n|Parameter| type| description|\n|---|---|----|\n|   extention   |  string (required) | represents the extention of the file that you want to check  |\n|   mimeType   |  string (required) | The mime type that you want to set in the response header for the specific file  |\n\n**Exmple**\n\n```javascript\nServer.addMimeTypes(\".pdf\", \"application/pdf\");\n```\n\n\n### Grandjs File Upload\n\n\n\nGrandjs includes a small helpers for working with files and images specifically, you can use it  via calling it from grandjs:\n\n```javascript\n// javascript\nconst {FileUpload} = require(\"grandjs\");\n// typescript\nimport {FileUpload} from \"grandjs\"\n```\n\nfile upload has property called `uploadPath` which is the destination to save files in, you can change it anytime by calling `setUploadPath` method as the following:\n\n```javascript\nFileUpload.setUploadPath(\"./uploads\");\n```\n\nFileUpload has implementation to make a directory in a specific destination\n\n**Example**\n```javascript\nFileUpload.makeDirectory(\"./uploads/images\");\n```\n\n\n##### Save Base64 as image\nyou can save base 64 file as image using this function:\n```javascript\nFileUpload.saveImageBase64(data, uploadPath)\n/*\nuploadPth: // default is uploadPath of the class\n*/\n```\nthis function returns promise\n\n\n\n\n### Socket Io Support\nGrandjs is extendable to use with socket io for realtime applications, here is an example on using grandjs with socket io\n\n```javascript\nconst {Server} = require(\"grandjs\");\nconst socketIo = require(\"socket.io\");\nServer.setConfig({\n    //define the port\n    port: process.env.PORT || 3000,\n    // http is optional you can specify http or https, if you don't specify Grandjs automatically require HTTP module\n    http: http,\n    // if you specified https so you should ssl files in this object\n    httpsMode: {\n        key: fs.readFileSync('test/fixtures/keys/agent2-key.pem'),\n        cert: fs.readFileSync('test/fixtures/keys/agent2-cert.pem')\n    }\n    //set the encryption key, Grandjs uses encription key to cypher info\n    ENCRYPTION_KEY: \"ncryptiontestforencryptionproces\",\n\n    //set error page for global error pages\n    errorPage(req, res) {\n        res.end(\"error page\");\n    }\n});\n\n// init Grandjs\nServer.initServer();\n\n\nconst io = socketIo(Server.Server);\nio.on(\"connect\", () =\u003e {\n    console.log(\"connected successfully\")\n})\n```\n\nnow once you run the application you can connect on socket via port `3000`\n\n\n# JSX\n## Writing JSX in Grandjs\n### About\nGrandjs Depends on JSX for rendering dynamic/static HTML markups, it converts the jsx syntax to html string by native parser, also the rendered JSX markup is a stateless\n\nGrandjs loads JSX components and files on runtime fastly without a need to bable or any transpilers, Grandjs uses `import-jsx` package for requiring jsx files\n\n## Why ?\n\nActually there is many different template engines can be used, all these template engines are efficient and good to work with, but you will learn a new syntax of each template engine, also you will suffer from the hassle of searching helpers for this template engine to add new features like conditions, mathematical operations inside the html markup, however we have JSX!\nMost of developers now know JSX and know how can they render it, \"thanks React!\", so We see using JSX is good, efficient and fast in rendering and Friendly syntax that allow you to write the whole Application in just javascript, with getting the benefits if Javascript methods, helpers, functions inside the HTML markup\n### How ?\n\nGrandjs exports an object called `View`, this object includes some builtin methods and configuration for parsing, and caching jsx syntax and converting it to html strings and then send this HTML markup to the browser\n\n**Note**\nJSX syntax shouldn't be written in the entry point file, you should create a folder called `views` for example and put all JSX code there by dividing into functional components and requiring the component you wherever you want\n**Example**\n\nProject Structure\n### Directory Structure  \n\u003cpre\u003e\n ┬  \n ├ views\n    ┬\n    ├ App.jsx\n    ├ Home.jsx\n ├ index.js\n\u003c/pre\u003e\n\nin App.jsx\n\n```jsx\n// jsx\n// importing {View} is mandatory\nconst {View} = require(\"grandjs\");\n// typescript\nimport {View} from \"grandjs\";\nconst App = (props) =\u003e {\n    return (\n        \u003cdiv\u003e\n            \u003ch1\u003ehello App Component\u003c/h1\u003e\n        \u003c/div\u003e\n    )\n}\nmodule.exports = App;\n```\nin Home.jsx file\n```jsx\nconst {View} = require(\"grandjs\");\n// typescript\nimport {View} from \"grandjs\";\nconst App = View.importJsx(\"./App.jsx\");\nconst Home = (props) =\u003e {\n    return (\n        \u003cdiv\u003e\n            \u003ch1\u003eThis is home page\u003c/h1\u003e\n            \u003cApp/\u003e\n        \u003c/div\u003e\n    )\n}\nmodule.exports = Home;\n```\n\n**Note**\n\n\n1- Any Component you write you have to import `{View}` inside the file that you write the component in, to make grandjs recognize and compile that file\n\n2- The component should be a functional Component as the following:\n```jsx\nconst App = (props) =\u003e {\n    return (\n        \u003cdiv\u003e\n            \u003ch1\u003ehello App Component\u003c/h1\u003e\n        \u003c/div\u003e\n    )\n}\n```\n3- You have to export the component as a nodejs module in commonjs syntax like the following:\n\n```jsx\nmodule.exports = App;\n```\n\n4- Importing JSX Component Should be using `View.importJsx` function which will recognize that this file is jsx syntax\n\n```javascript\nconst Home = View.importJsx(\"./views/Home.jsx\");\n```\n\n\n```javascript\n// importing {View} is mandatory\nconst {Server, View, Router} = require(\"grandjs\");\n// typescript\nimport {Server, View, Router} from \"grandjs\";\n// import Home Page\nconst Home = View.importJsx(\"./views/Home.jsx\");\nconst router = new Router({base: \"/\"})\n\nrouter.addRoute({\n    url: \"/\",\n    method: \"GET\",\n    handler: (req, res) =\u003e {\n        return res.status(200).render(Home, {})\n    }\n})\nrouter.build();\nServer.setConfig({port: 3000});\nServer.initServer();\n```\n### View Define Styles\n\nGrandjs exposes to you a method called `View.createStyle` which is a method in `View` class that you can use to create a style as an object and use this style with defined classes inside your component as you can do in react\n\n**Example**\n\n```javascript\nconst {View} = require(\"grandjs\")\n\nconst Styles = View.createStyle({\n    title: {\n        backgroundColor: \"red\"\n    }\n    title2: {\n        color: \"green\"\n    }\n})\n\nconst App = () =\u003e {\n    const classes = Styles();\n    return (\n        \u003ch1 className={classes.title}\u003e\u003c/h1\u003e\n    )\n}\n```\n\n### View Render Component To HTML\n\nAlso View class exposes to you a method called `renderToHtml` which is can be used to render the component into raw html string, this can be useful if you want to send your components as mail templates!\n\n```javascript\nconst {View} = require(\"grandjs\");\nconst Home = View.importJsx(\"./views/Home.jsx\");\n\nconst template = View.renderToHtml(Home, {});\n```\n\n\n\n\n## Built With\n* [Tarek Salem](https://github.com/tareksalem)\n\n\n\n## Authors\n\n* **Tarek Salem** - *Initial work* - [github](https://github.com/tareksalem)\n\n\n## License\n\nThis project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details\n\n## Acknowledgments\n* url-pattern\n* Handlebars template engine\n* Hat tip to anyone whose code was used\n* Inspiration\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgrandjs%2Fgrandjs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgrandjs%2Fgrandjs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgrandjs%2Fgrandjs/lists"}