├── Logs └── systemLog.log ├── .gitignore ├── App ├── Model │ └── Model.txt ├── Service │ ├── Service.txt │ └── WebSocket.ts ├── Repository │ └── Repository.txt ├── Http │ ├── Requests │ │ ├── RequestValidation.txt │ │ ├── LoginValidation.ts │ │ └── RegisterValidation.ts │ ├── Middleware │ │ ├── RequestBodyValidator.ts │ │ ├── ConvertEmptyStringsToNull.ts │ │ ├── CheckForMaintenanceMode.ts │ │ └── Auth.ts │ ├── Controller │ │ ├── WS │ │ │ └── chatController.ts │ │ └── Auth │ │ │ ├── LoginController.ts │ │ │ └── RegisterController.ts │ └── Kernel.ts ├── Console │ └── Kernel.ts └── Providers │ ├── SocketServiceProvider.ts │ ├── RouteServiceProvider.ts │ ├── ShutDownProvider.ts │ └── AppServiceProvider.ts ├── Utils └── utility_files.txt ├── nodemon.json ├── tslint.json ├── Resources └── RouteDocumentation │ ├── index.ts │ └── index.ejs ├── jest.config.js ├── app.ts ├── Routes ├── sockets.ts └── api.ts ├── maker.ts ├── Database └── Migrations │ ├── migrationLayout.stub │ └── 20210414005825_users.ts ├── tsconfig.json ├── SchemaSetup.ts ├── example.env ├── Config ├── auth.ts ├── logging.ts ├── queue.ts ├── hashing.ts ├── socials.ts ├── cors.ts ├── filesystems.ts ├── socket.ts ├── app.ts ├── database.ts └── bodyParser.ts ├── package.json ├── Command └── index.ts ├── README.md └── .github └── CONTRIBUTION.md /Logs/systemLog.log: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .env 3 | build -------------------------------------------------------------------------------- /App/Model/Model.txt: -------------------------------------------------------------------------------- 1 | Manage your application models in the Model directory 2 | -------------------------------------------------------------------------------- /App/Service/Service.txt: -------------------------------------------------------------------------------- 1 | Manage your application services in the service directory -------------------------------------------------------------------------------- /Utils/utility_files.txt: -------------------------------------------------------------------------------- 1 | Manage your application utility fiiles in the Utils directory -------------------------------------------------------------------------------- /App/Repository/Repository.txt: -------------------------------------------------------------------------------- 1 | Manage your application repositories in the repository directory 2 | -------------------------------------------------------------------------------- /App/Http/Requests/RequestValidation.txt: -------------------------------------------------------------------------------- 1 | Manage your application request validation in the Request directory 2 | -------------------------------------------------------------------------------- /nodemon.json: -------------------------------------------------------------------------------- 1 | { 2 | "watch": ["./"], 3 | "ignore": ["./build/"], 4 | "exec": "node -r tsconfig-paths/register -r ts-node/register ./app.ts", 5 | "ext": "ts, json" 6 | } 7 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "defaultSeverity": "error", 4 | "extends": [ 5 | "tslint:recommended" 6 | ], 7 | "jsRules": {}, 8 | "rules": { 9 | "no-console":false 10 | }, 11 | "rulesDirectory": [] 12 | } 13 | -------------------------------------------------------------------------------- /Resources/RouteDocumentation/index.ts: -------------------------------------------------------------------------------- 1 | export default [ 2 | { 3 | api: "/", 4 | description: "ExpressWebJs Default Route", 5 | request: {}, 6 | response: { 7 | payload: { message: "object", status: "boolean" }, 8 | }, 9 | }, 10 | ]; 11 | -------------------------------------------------------------------------------- /App/Service/WebSocket.ts: -------------------------------------------------------------------------------- 1 | class WebSocket { 2 | protected io: any; 3 | 4 | server(ioServer: any) { 5 | this.io = ioServer; 6 | } 7 | 8 | channel(channelName: string) { 9 | this.io.emit("room", channelName); 10 | return this; 11 | } 12 | 13 | emit(listener: string, handler: any) { 14 | this.io.emit(listener, handler); 15 | } 16 | } 17 | 18 | export default new WebSocket(); 19 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | moduleNameMapper: { 3 | "^App/(.*)$": "/App/$1", 4 | "^Config/(.*)$": "/Config/$1", 5 | "^Database/(.*)$": "/Database/$1", 6 | "^Routes/(.*)$": "/Routes/$1", 7 | "^Utils/(.*)$": "/Utils/$1", 8 | "^Elucidate/(.*)$": "/node_modules/expresswebcorets/lib/$1", 9 | }, 10 | preset: "ts-jest", 11 | testEnvironment: "node", 12 | }; 13 | -------------------------------------------------------------------------------- /app.ts: -------------------------------------------------------------------------------- 1 | /* 2 | |--------------------------------------------------------------- 3 | | Http Server 4 | |--------------------------------------------------------------- 5 | | This file bootstraps ExpressWebJs to start the Http server. 6 | | Application Host, Port and Transfer Protocols are configured 7 | | in the .env file. You are free to configure them. 8 | | 9 | */ 10 | 11 | import app from "expresswebcorets/lib/App"; 12 | export default app.start(); 13 | -------------------------------------------------------------------------------- /App/Console/Kernel.ts: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | import scheduler from "expressweb-scheduler-ts"; 3 | 4 | class Kernel { 5 | /** 6 | * The Maker commands provided by your application. 7 | * @var array 8 | */ 9 | static commands() { 10 | return []; 11 | } 12 | 13 | /** 14 | * Define the application's schedule command. 15 | * @return void 16 | */ 17 | static schedule(): any { 18 | // 19 | } 20 | } 21 | 22 | export default Kernel; 23 | -------------------------------------------------------------------------------- /Routes/sockets.ts: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | import Ws from "Elucidate/Socket/WS"; 3 | /* 4 | |-------------------------------------------------------------------------- 5 | | socket.io 6 | |-------------------------------------------------------------------------- 7 | | 8 | | This file is used to register socket.io channels and start the Ws server. 9 | | 10 | */ 11 | 12 | export default (socket: any) => { 13 | Ws.connect(socket); 14 | // Web socket channel controllers 15 | Ws.channel("notification", "chatController"); 16 | }; 17 | -------------------------------------------------------------------------------- /App/Http/Middleware/RequestBodyValidator.ts: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | import FormRequest from "Elucidate/Validator/FormRequest"; 3 | import { Request, Response, NextFunction } from "Elucidate/HttpContext"; 4 | 5 | class RequestBodyValidator extends FormRequest { 6 | async handle(req: Request, res: Response, next: NextFunction) { 7 | req.validate = (data: T, rules: object) => { 8 | return FormRequest.make(data, rules); 9 | }; 10 | 11 | await next(); 12 | } 13 | } 14 | 15 | export default RequestBodyValidator; 16 | -------------------------------------------------------------------------------- /maker.ts: -------------------------------------------------------------------------------- 1 | import commands from "./Command/index"; 2 | import kernel from "./App/Console/Kernel"; 3 | import makerts from "maker-console-ts"; 4 | 5 | 6 | /* 7 | |-------------------------------------------------------------------------- 8 | | Run The Maker Application 9 | |-------------------------------------------------------------------------- 10 | | 11 | | When we run the console application, the current CLI command will be 12 | | executed in this console and the response sent back to a terminal 13 | | 14 | */ 15 | makerts.run(commands, kernel); -------------------------------------------------------------------------------- /Database/Migrations/migrationLayout.stub: -------------------------------------------------------------------------------- 1 | /** 2 | * Migration layout file. 3 | * Assign your table name to the tableName variable. 4 | * Remember, it's always in plural 5 | */ 6 | import { Migration } from "Elucidate/Database/Model"; 7 | 8 | let tableName = ""; 9 | exports.up = function (migration:Migration) { 10 | return migration.schema.createTable(tableName, (table) => { 11 | table.increments("id"); 12 | table.timestamps(true, true); 13 | }); 14 | }; 15 | 16 | exports.down = function (migration:Migration) { 17 | return migration.schema.dropTable(tableName); 18 | }; 19 | -------------------------------------------------------------------------------- /App/Http/Requests/LoginValidation.ts: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | import FormRequest from "Elucidate/Validator/FormRequest"; 3 | 4 | type dataType = { email: string; password: string }; 5 | 6 | class LoginValidation extends FormRequest { 7 | /** 8 | * Handle login request validation. 9 | * @param {*} data | e.g request body 10 | */ 11 | static async validate(data: any) { 12 | return await this.make(data, { 13 | email: "required|string|email|max:255", 14 | password: "required|string|min:8", 15 | }); 16 | } 17 | } 18 | 19 | export { LoginValidation, dataType }; 20 | -------------------------------------------------------------------------------- /App/Http/Middleware/ConvertEmptyStringsToNull.ts: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | import { Request, Response, NextFunction } from "Elucidate/HttpContext"; 4 | 5 | class ConvertEmptyStringsToNull { 6 | public async handle(req: Request, _res: Response, next: NextFunction) { 7 | if (Object.keys(req.body).length) { 8 | req.body = Object.assign({}, 9 | ...Object.keys(req.body).map((key) => ({ 10 | [key]: req.body[key] !== "" ? req.body[key] : null, 11 | })) 12 | ); 13 | } 14 | 15 | await next(); 16 | } 17 | } 18 | 19 | export default ConvertEmptyStringsToNull; 20 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./node_modules/expresswebjs-preset-ts/tsconfig.json", 3 | "compilerOptions": { 4 | "baseUrl": "./", 5 | "outDir": "./build", 6 | "rootDir": "./", 7 | "paths": { 8 | "App/*":["./App/*"], 9 | "Config/*":["./Config/*"], 10 | "Database/*":["./Database/*"], 11 | "Resources/*":["./Resources/*"], 12 | "Routes/*":["./Routes/*"], 13 | "Utils/*":["./Utils/*"], 14 | "Elucidate/*":["./node_modules/expresswebcorets/lib/*"], 15 | }, 16 | "declaration": false, 17 | "allowSyntheticDefaultImports": true, 18 | "esModuleInterop": true, 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /SchemaSetup.ts: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | import env from "expresswebcorets/lib/Env"; 3 | import config from "./Config/database"; 4 | 5 | class migration { 6 | constructor() { 7 | if (env("DB_CONNECTION") != "mongoose") { 8 | switch (env("DB_TENANT")) { 9 | case "tenant1": 10 | //return config.multitenant_tenants[0]; 11 | case "tenant2": 12 | //return config.multitenant_tenants[1]; 13 | case "null": 14 | return config[env("DB_CONNECTION")]; 15 | default: 16 | throw Error("DB_TENANT is not specified in .env file"); 17 | } 18 | } 19 | } 20 | } 21 | export default new migration(); 22 | -------------------------------------------------------------------------------- /App/Http/Requests/RegisterValidation.ts: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | import FormRequest from "Elucidate/Validator/FormRequest"; 3 | 4 | type dataType = { username: string; email: string; password: string }; 5 | 6 | class RegisterValidation extends FormRequest { 7 | /** 8 | * Handle registration request validation. 9 | * @param {*} data | e.g request body 10 | */ 11 | static async validate(data: any) { 12 | return await this.make(data, { 13 | username: "required|string|max:255", 14 | email: "required|string|email|max:255", 15 | password: "required|string|min:8", 16 | }); 17 | } 18 | } 19 | 20 | export { RegisterValidation, dataType }; 21 | -------------------------------------------------------------------------------- /App/Http/Middleware/CheckForMaintenanceMode.ts: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | import appShutDown from "Elucidate/App/shutdown"; 3 | import { Request, Response, NextFunction } from "Elucidate/HttpContext"; 4 | import HttpResponse from "Elucidate/HttpContext/ResponseType"; 5 | 6 | class CheckForMaintenanceMode { 7 | public async handle(req: Request, res: Response, next: NextFunction) { 8 | let mode = appShutDown.isDownForMaintenance(); 9 | if (mode.status) { 10 | if (appShutDown.inEndpointsArray(req.url, mode.endPoints) == false) { 11 | return HttpResponse.SERVICE_UNAVAILABLE(res,{ message: mode.message }) 12 | } 13 | } 14 | await next(); 15 | } 16 | } 17 | 18 | export default CheckForMaintenanceMode; 19 | -------------------------------------------------------------------------------- /Database/Migrations/20210414005825_users.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Migration layout file. 3 | * Assign your table name to the tableName variable. 4 | * Remember, it's always in plural 5 | */ 6 | import { Migration } from "Elucidate/Database/Model"; 7 | 8 | let tableName = "users"; 9 | 10 | exports.up = function (migration: Migration) { 11 | return migration.schema.createTable(tableName, (table) => { 12 | table.increments("id"); 13 | table.string("username").notNullable(); 14 | table.string("email").unique().notNullable(); 15 | table.string("password").notNullable(); 16 | table.timestamps(true, true); 17 | }); 18 | }; 19 | 20 | exports.down = function (migration: Migration) { 21 | return migration.schema.dropTable(tableName); 22 | }; 23 | -------------------------------------------------------------------------------- /Routes/api.ts: -------------------------------------------------------------------------------- 1 | import Route from "Elucidate/Route/manager"; 2 | import { Request, Response, NextFunction } from "Elucidate/HttpContext"; 3 | /* 4 | |-------------------------------------------------------------------------- 5 | | Api route 6 | |-------------------------------------------------------------------------- 7 | | 8 | | Here is where you can register your application routes. These 9 | | routes are loaded by the RouteProvider. Now create something great! 10 | | 11 | */ 12 | 13 | Route.get("/", (req: Request, res: Response) => { 14 | res.status(200).send("Welcome to ExpressWebJs Typescript Version"); 15 | }); 16 | 17 | //-------------------------------------------------------------------------- 18 | export default Route.exec; 19 | -------------------------------------------------------------------------------- /App/Http/Controller/WS/chatController.ts: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | class ChatController { 3 | protected socket: any; 4 | constructor(socket: any) { 5 | this.socket = socket; 6 | this.setMethodListeners(); 7 | } 8 | 9 | onMessage = (data: any) => { 10 | // same as: socket.on('message') 11 | this.socket.emit("message", data); 12 | console.log(data); 13 | }; 14 | 15 | onClose = () => { 16 | // same as: socket.on('close') 17 | }; 18 | 19 | onError = () => { 20 | // same as: socket.on('error') 21 | }; 22 | 23 | private setMethodListeners() { 24 | this.socket.on("message", this.onMessage); 25 | this.socket.on("close", this.onClose); 26 | this.socket.on("error", this.onError); 27 | } 28 | } 29 | 30 | export default ChatController; 31 | -------------------------------------------------------------------------------- /App/Http/Middleware/Auth.ts: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | import Authenticator from "Elucidate/Auth/Authenticator"; 3 | import { Request, Response, NextFunction } from "Elucidate/HttpContext"; 4 | import HttpResponse from "Elucidate/HttpContext/ResponseType"; 5 | 6 | class AuthMiddleware { 7 | Auth: Authenticator; 8 | constructor(Authenticator:Authenticator) { 9 | this.Auth = Authenticator 10 | } 11 | handle = async(req: Request, res: Response, next: NextFunction) =>{ 12 | let result = await this.Auth.processAuthMW(req.headers["authorization"]); 13 | if (result.type == "error") { 14 | return HttpResponse.UNAUTHORIZED(res, { auth: false, message: result.msg, payload: result.payload }); 15 | } 16 | 17 | req.user = result.payload; 18 | 19 | await next(); 20 | } 21 | } 22 | 23 | export default AuthMiddleware; 24 | -------------------------------------------------------------------------------- /App/Providers/SocketServiceProvider.ts: -------------------------------------------------------------------------------- 1 | import { Server } from "socket.io"; 2 | import config from "Config/socket"; 3 | import ServiceProvider from "Elucidate/Support/ServiceProvider"; 4 | 5 | class SocketServiceProvider extends ServiceProvider { 6 | /** 7 | * Load any service after application boot stage 8 | * @return void 9 | */ 10 | public async booted() { 11 | let socketConfig: any = config; 12 | let server = new Server(this.app.use("ApplicationInstance"), socketConfig); 13 | server.on("connection", (socket) => { 14 | console.log("Socket connected"); 15 | import("Routes/sockets").then((file) => { 16 | file.default(socket); 17 | }); 18 | import("App/Service/WebSocket").then((file) => { 19 | file.default.server(socket); 20 | }); 21 | }); 22 | } 23 | } 24 | 25 | export default SocketServiceProvider; 26 | -------------------------------------------------------------------------------- /App/Providers/RouteServiceProvider.ts: -------------------------------------------------------------------------------- 1 | import ServiceProvider from "Elucidate/Support/ServiceProvider"; 2 | import IRoute from "Elucidate/Route/IRoute"; 3 | import ApplicationConfig from "Config/app"; 4 | 5 | class RouteServiceProvider extends ServiceProvider { 6 | Route!: IRoute; 7 | /** 8 | * Define your route prefix binding and control route request limit. 9 | * Default base route prefix is 'api' 10 | */ 11 | boot() { 12 | this.Route = this.app.use("RouteConfigServiceProvider"); 13 | this.Route.routePrefix(ApplicationConfig.routePrefix); 14 | return this.configureRateLimiting(); 15 | } 16 | 17 | /** 18 | * Configure the rate limiters for the application. 19 | */ 20 | configureRateLimiting() { 21 | return this.Route.for(`/${ApplicationConfig.routePrefix}/`).perMinute(1000).errorMessage().httpStatusCode(429).save(); 22 | } 23 | } 24 | 25 | export default RouteServiceProvider; 26 | -------------------------------------------------------------------------------- /App/Providers/ShutDownProvider.ts: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | import ServiceProvider from "Elucidate/Support/ServiceProvider"; 3 | 4 | class ShutDownProvider extends ServiceProvider { 5 | /** 6 | * Bootstrap any application services. 7 | * @return void 8 | */ 9 | boot() { 10 | let application = this.app.use("ApplicationInstance"); 11 | process.on("SIGINT", (error) => { 12 | console.log("\n[server] Shutting down...", error); 13 | application.close(); 14 | process.exit(); 15 | }); 16 | 17 | process.on("SIGTERM", (error) => { 18 | console.log("\n[server] Shutting down...", error); 19 | application.close(); 20 | process.exit(); 21 | }); 22 | 23 | process.on("uncaughtException", (error) => { 24 | console.log("\n[server] Shutting down...", error); 25 | application.close(); 26 | process.exit(); 27 | }); 28 | } 29 | } 30 | 31 | export default ShutDownProvider; 32 | -------------------------------------------------------------------------------- /example.env: -------------------------------------------------------------------------------- 1 | APP_KEY=base64:M5rmpk9TtGvMu3Kfp9JtH5sI3VTx2MXTQjN/6CFBadI= 2 | APP_NAME=ExpressWebJs 3 | APP_ENV=local 4 | APP_HOST=127.0.0.1 5 | APP_PORT=5100 6 | APP_TRANSFER_PROTOCOL=http 7 | ROUTE_PREFIX=api 8 | 9 | LOG_CHANNEL=file 10 | 11 | DB_MULTITENANCE=false 12 | # Current migration tenant for migration and seed 13 | DB_TENANT=null 14 | 15 | DB_SHOULD_CONNECT=true 16 | DB_CONNECTION=mysql 17 | DB_HOST=localhost 18 | DB_PORT=3306 19 | DB_USER= 20 | DB_PASSWORD= 21 | DB_DATABASE=database_name 22 | DB_USENEWURLPARSER=true 23 | DB_USEUNIFIEDTOPOLOGY=true 24 | DB_USECREATEINDEX=true 25 | 26 | QUEUE_CONNECTION=rabbitmq 27 | RABBITMQ_QUEUE=myQueue 28 | RABBITMQ_HOST=amqp://localhost 29 | RABBIT_PORT=5672 30 | 31 | REDIS_CLIENT=default 32 | REDIS_HOST=127.0.0.1 33 | REDIS_PORT=6379 34 | REDIS_PASSWORD=null 35 | REDIS_DB=0 36 | 37 | FILESYSTEM_DRIVER=local 38 | FILESYSTEM_CLOUD=s3 39 | 40 | AWS_ACCESS_KEY_ID= 41 | AWS_SECRET_ACCESS_KEY= 42 | AWS_BUCKET_NAME= 43 | AWS_ACCESS_REGION= 44 | AWS_ACL_FILE_PERMISSIONS= -------------------------------------------------------------------------------- /App/Providers/AppServiceProvider.ts: -------------------------------------------------------------------------------- 1 | import ServiceProvider from "Elucidate/Support/ServiceProvider"; 2 | import Authenticator from "Elucidate/Auth/Authenticator"; 3 | import DOCUMENTATION from "Elucidate/Documentation/DocumentationServiceProvider"; 4 | import routeDocumentation from "Resources/RouteDocumentation"; 5 | 6 | class AppServiceProvicer extends ServiceProvider { 7 | /** 8 | * Register any application services. 9 | * @return void 10 | */ 11 | public register() { 12 | this.app.singleton("Authenticator", Authenticator, "class"); 13 | } 14 | 15 | /** 16 | * Bootstrap any application services. 17 | * @return void 18 | */ 19 | public async boot() { 20 | // 21 | } 22 | 23 | /** 24 | * Load any service after application boot stage 25 | * @return void 26 | */ 27 | public async booted() { 28 | // Documentation endpoint is '/documentationView' for JSON response '/documentationJson' 29 | DOCUMENTATION.autoDocumentEndPoints("./Resources", routeDocumentation); 30 | } 31 | } 32 | 33 | export default AppServiceProvicer; 34 | -------------------------------------------------------------------------------- /Config/auth.ts: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | import env from "Elucidate/Env"; 3 | export default { 4 | /* 5 | |-------------------------------------------------------------------------- 6 | | Authenticator 7 | |-------------------------------------------------------------------------- 8 | | 9 | | ExpressWebJs does not support session state, incoming requests that 10 | | you wish to authenticate must be authenticated via a stateless mechanism such as API tokens. 11 | | 12 | */ 13 | authenticator: "jwt", 14 | 15 | /* 16 | |-------------------------------------------------------------------------- 17 | | Jwt 18 | |-------------------------------------------------------------------------- 19 | | 20 | | The jwt authenticator works by passing a jwt token on each HTTP request 21 | | via HTTP `Authorization` header. 22 | | 23 | */ 24 | jwt: { 25 | model: "User_model", 26 | driver: "jwt", 27 | uid: "email", 28 | password: "password", 29 | secret: env("APP_KEY"), 30 | options: { 31 | expiresIn: 86400, //default is 86400 (24 hrs) 32 | }, 33 | }, 34 | }; 35 | -------------------------------------------------------------------------------- /App/Http/Kernel.ts: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | export default { 4 | /* 5 | |-------------------------------------------------------------------------- 6 | | Application level Middleware 7 | |-------------------------------------------------------------------------- 8 | | 9 | | The application's global HTTP middleware stack. 10 | | 11 | | These middlewares are run during every request to your application. 12 | | 13 | */ 14 | applicationLevelMiddleware: ["App/Http/Middleware/CheckForMaintenanceMode", "App/Http/Middleware/ConvertEmptyStringsToNull", "App/Http/Middleware/RequestBodyValidator"], 15 | 16 | /* 17 | |-------------------------------------------------------------------------- 18 | | Route Middleware 19 | |-------------------------------------------------------------------------- 20 | | 21 | | Route middleware is key/value object to conditionally add middleware on 22 | | specific routes or assigned to group of routes. 23 | | 24 | | // define 25 | | { 26 | | auth: 'App/Http/Middleware/Auth' 27 | | } 28 | | 29 | | // in your route add [auth] 30 | | 31 | */ 32 | routeMiddleware: { 33 | auth: "App/Http/Middleware/Auth", 34 | }, 35 | }; 36 | -------------------------------------------------------------------------------- /Config/logging.ts: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | import env from "expresswebcorets/lib/Env"; 3 | 4 | export default { 5 | /* 6 | |-------------------------------------------------------------------------- 7 | | Default Log Channel 8 | |-------------------------------------------------------------------------- 9 | | 10 | | This option defines the default log channel that gets used when writing 11 | | messages to the logs. The name specified in this option should match 12 | | one of the channels defined in the "channels" configuration array. 13 | | 14 | */ 15 | 16 | default: env("LOG_CHANNEL", "console"), 17 | 18 | /* 19 | |-------------------------------------------------------------------------- 20 | | Log Channels 21 | |-------------------------------------------------------------------------- 22 | | 23 | | Here you may configure the log channels for your application. Out of 24 | | the box, ExpressWebJs supports Console and file 25 | | 26 | */ 27 | 28 | logLevel: "debug", 29 | 30 | channels: { 31 | console: { 32 | type: "console", 33 | category: "console", 34 | }, 35 | 36 | file: { 37 | category: "system-log", 38 | type: "file", 39 | filename: "Logs/systemLog.log", 40 | maxLogSize: 10240, 41 | backups: 3, 42 | flag: "w", 43 | pattern: "yyyy-MM-dd", 44 | }, 45 | }, 46 | }; 47 | -------------------------------------------------------------------------------- /Config/queue.ts: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | import env from "expresswebcorets/lib/Env"; 3 | 4 | export default { 5 | /* 6 | |-------------------------------------------------------------------------- 7 | | Default Queue Connection Name 8 | |-------------------------------------------------------------------------- 9 | | 10 | | ExpressWebJs queue API supports an assortment of back-ends via a single 11 | | API, giving you convenient access to each back-end using the same 12 | | syntax for every one. Here you may define a default connection. 13 | | 14 | | `run npm install amqplib` to get started 15 | */ 16 | 17 | default: env("QUEUE_CONNECTION", null), 18 | 19 | /* 20 | |-------------------------------------------------------------------------- 21 | | Queue Connections 22 | |-------------------------------------------------------------------------- 23 | | 24 | | Here you may configure the connection information for rabbitmq server that 25 | | is used by your application. A default configuration has been added. 26 | | ExpressWebJs currently supports rabbitmq for now. 27 | | 28 | | Driver: "rabbitmq" 29 | | 30 | */ 31 | 32 | connections: { 33 | rabbitmq: { 34 | driver: "rabbitmq", 35 | connection: "default", 36 | queue: env("RABBITMQ_QUEUE", "default"), 37 | retry_after: 90, 38 | block_for: null, 39 | host: env("RABBITMQ_HOST"), 40 | port: env("RABBIT_PORT"), 41 | }, 42 | }, 43 | }; 44 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "expresswebjs-ts-version", 3 | "version": "3.3.0", 4 | "description": "ExpressWebJs Framework Typescript Version", 5 | "main": "build/app.js", 6 | "scripts": { 7 | "test": "jest", 8 | "dev": "ts-node maker run-dev", 9 | "start": "node ./build/maker run-start", 10 | "build": "ts-node maker run-build" 11 | }, 12 | "keywords": [ 13 | "framework", 14 | "expresswebjs" 15 | ], 16 | "_moduleAliases": { 17 | "Elucidate": "./node_modules/expresswebcorets/lib" 18 | }, 19 | "author": "Alex Igbokwe", 20 | "license": "ISC", 21 | "devDependencies": { 22 | "@types/express": "^4.17.11", 23 | "@types/jest": "^26.0.22", 24 | "@types/mongoose-paginate": "^5.0.8", 25 | "@types/node": "^14.14.17", 26 | "nodemon": "^2.0.6", 27 | "ts-node": "^9.1.1", 28 | "tsconfig-paths": "^3.9.0", 29 | "tslint": "^6.1.3", 30 | "typescript": "^4.2.3", 31 | "typescript-transform-paths": "^2.2.3" 32 | }, 33 | "dependencies": { 34 | "amqp-ts": "^1.8.0", 35 | "aws-sdk": "^2.933.0", 36 | "bcryptjs": "^2.4.3", 37 | "expressweb-scheduler-ts": "^1.0.4", 38 | "expresswebcorets": "1.1.35", 39 | "expresswebjs-preset-ts": "^1.0.4", 40 | "log4js": "^6.3.0", 41 | "maker-console-ts": "^1.0.57", 42 | "module-alias": "^2.2.2", 43 | "mongoose": "^5.11.9", 44 | "mysql": "^2.18.1", 45 | "mysql2": "^2.2.5", 46 | "recursive-copy": "^2.0.13", 47 | "set-value": "^4.1.0", 48 | "socket.io": "^3.1.0" 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Command/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | |-------------------------------------------------------------------------- 3 | | Maker Commands 4 | |-------------------------------------------------------------------------- 5 | | 6 | | When we run the console application, the current CLI command will be 7 | | executed in the console and the response sent back to the terminal. 8 | | Register Maker Commands using their unique namespace. 9 | | 10 | */ 11 | const commands = [ 12 | "ExpressWebJs/commands/make-auth", 13 | "ExpressWebJs/commands/make-controller", 14 | "ExpressWebJs/commands/make-event", 15 | "ExpressWebJs/commands/make-listener", 16 | "ExpressWebJs/commands/make-sql-model", 17 | "ExpressWebJs/commands/make-nosql-model", 18 | "ExpressWebJs/commands/make-route", 19 | "ExpressWebJs/commands/make-middleware", 20 | "ExpressWebJs/commands/make-request", 21 | "ExpressWebJs/commands/make-sql-migration", 22 | "ExpressWebJs/commands/make-ws-controller", 23 | "ExpressWebJs/commands/run-sql-migration", 24 | "ExpressWebJs/commands/show-sql-list", 25 | "ExpressWebJs/commands/sql-rollback", 26 | "ExpressWebJs/commands/sql-rollup", 27 | "ExpressWebJs/commands/sql-rolldown", 28 | "ExpressWebJs/commands/make-command", 29 | "ExpressWebJs/commands/run-schedule", 30 | "ExpressWebJs/commands/queue-work", 31 | "ExpressWebJs/commands/make-identity", 32 | "ExpressWebJs/commands/make-service", 33 | "ExpressWebJs/commands/make-job", 34 | "ExpressWebJs/commands/make-provider", 35 | "ExpressWebJs/commands/run-dev", 36 | "ExpressWebJs/commands/make-rule", 37 | "ExpressWebJs/commands/run-build", 38 | "ExpressWebJs/commands/run-start", 39 | ]; 40 | 41 | export default commands; 42 | -------------------------------------------------------------------------------- /App/Http/Controller/Auth/LoginController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from "Elucidate/HttpContext"; 2 | import HttpResponse from "Elucidate/HttpContext/ResponseType"; 3 | import Authenticator from "Elucidate/Auth/Authenticator"; 4 | import { LoginValidation, dataType } from "App/Http/Requests/LoginValidation"; 5 | 6 | class LoginController { 7 | protected Auth: Authenticator; 8 | 9 | constructor(Authenticator: Authenticator) { 10 | this.Auth = Authenticator; 11 | } 12 | /* 13 | |-------------------------------------------------------------------------- 14 | | Login Controller 15 | |-------------------------------------------------------------------------- 16 | | 17 | | This controller handles authenticating users for the application and 18 | | sends the response with generated token back to the caller. 19 | | 20 | */ 21 | login = async (req: Request, res: Response) => { 22 | let validation = await LoginValidation.validate(req.body); 23 | if (validation.success) { 24 | return await this.processLogin(validation.data, res); 25 | } else { 26 | return HttpResponse.BAD_REQUEST(res, validation); 27 | } 28 | }; 29 | 30 | /** 31 | * Process incoming login data. 32 | * @param {object} data 33 | * @param {Response} res 34 | * @return User 35 | */ 36 | private processLogin = async (data: object, res: Response) => { 37 | return await this.Auth.processLogin(data) 38 | .then(async (user: object) => { 39 | let token = await this.Auth.generateToken(user); 40 | return HttpResponse.OK(res, { auth: true, token: token }); 41 | }) 42 | .catch((err: { msg: any; payload: any }) => { 43 | return HttpResponse.UNAUTHORIZED(res, { 44 | auth: false, 45 | msg: err.msg, 46 | error: err.payload, 47 | }); 48 | }); 49 | }; 50 | } 51 | 52 | export default LoginController; 53 | -------------------------------------------------------------------------------- /Config/hashing.ts: -------------------------------------------------------------------------------- 1 | import env from "Elucidate/Env"; 2 | export default { 3 | /* 4 | |-------------------------------------------------------------------------- 5 | | Default Hash Driver 6 | |-------------------------------------------------------------------------- 7 | | 8 | | This option controls the default hash driver that will be used to hash 9 | | passwords for your application. By default, the bcrypt algorithm is 10 | | used; however, you remain free to modify this option if you wish. 11 | | 12 | | Supported: "bcrypt", "argon". 13 | | 14 | */ 15 | 16 | driver: "bcrypt", 17 | 18 | /* 19 | |-------------------------------------------------------------------------- 20 | | Bcrypt Options 21 | |-------------------------------------------------------------------------- 22 | | npm install bcrypt 23 | |-------------------------------------------------------------------------- 24 | | Here you may specify the configuration options that should be used when 25 | | passwords are hashed using the Bcrypt algorithm. This will allow you 26 | | to control the amount of time it takes to hash the given password. 27 | | 28 | */ 29 | 30 | bcrypt: { 31 | rounds: env("BCRYPT_ROUNDS", 10), 32 | }, 33 | 34 | /* 35 | |-------------------------------------------------------------------------- 36 | | Argon Options 37 | |-------------------------------------------------------------------------- 38 | | npm install argon 39 | |-------------------------------------------------------------------------- 40 | | Here you may specify the configuration options that should be used when 41 | | passwords are hashed using the Argon algorithm. These will allow you 42 | | to control the amount of time it takes to hash the given password. 43 | | 44 | */ 45 | 46 | argon: { 47 | hashLength: 32, 48 | timeCost: 3, 49 | memory: 4096, 50 | parallelism: 1, 51 | type: "argon2i", 52 | }, 53 | }; 54 | -------------------------------------------------------------------------------- /App/Http/Controller/Auth/RegisterController.ts: -------------------------------------------------------------------------------- 1 | import Hash from "Elucidate/Hashing/Hash"; 2 | import { Request, Response } from "Elucidate/HttpContext"; 3 | import HttpResponse from "Elucidate/HttpContext/ResponseType"; 4 | import Authenticator from "Elucidate/Auth/Authenticator"; 5 | import { dataType, RegisterValidation } from "App/Http/Requests/RegisterValidation"; 6 | 7 | class RegisterController { 8 | protected Auth: Authenticator; 9 | 10 | constructor(Authenticator: Authenticator) { 11 | this.Auth = Authenticator; 12 | } 13 | 14 | /* 15 | |-------------------------------------------------------------------------- 16 | | Register Controller 17 | |-------------------------------------------------------------------------- 18 | | 19 | | This controller handles the registration of new users as well as their 20 | | validation and creation of their token. 21 | | 22 | */ 23 | register = async (req: Request, res: Response) => { 24 | let validation = await RegisterValidation.validate(req.body); 25 | if (validation.success) { 26 | return await this.create(validation.data, res); 27 | } else { 28 | return HttpResponse.BAD_REQUEST(res, validation); 29 | } 30 | }; 31 | 32 | /** 33 | * Create a new user instance after a valid registration. 34 | * @param {object} data 35 | * @param {Response} res 36 | * @return User 37 | */ 38 | private create = async (data: object, res: Response) => { 39 | data["password"] = await Hash.make(data["password"]); 40 | return await this.Auth.createUser(data) 41 | .then(async (user: any) => { 42 | let token = await this.Auth.generateToken(user); 43 | return HttpResponse.OK(res, { auth: true, token: token }); 44 | }) 45 | .catch((err: { msg: any; payload: any }) => { 46 | return HttpResponse.UNAUTHORIZED(res, { 47 | auth: false, 48 | msg: err.msg, 49 | error: err.payload, 50 | }); 51 | }); 52 | }; 53 | } 54 | 55 | export default RegisterController; 56 | -------------------------------------------------------------------------------- /Config/socials.ts: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | import env from "expresswebcorets/lib/Env"; 3 | 4 | export default { 5 | /* 6 | |-------------------------------------------------------------------------- 7 | | Social Connection Drivers 8 | |-------------------------------------------------------------------------- 9 | | 10 | | ExpressWebJs social API supports so many authenication services, 11 | | giving you the flexibility to use single sign-on using an OAuth provider such as 12 | | Facebook,Twitter,LinkedIn,Google, Microsoft. 13 | | 14 | | You can set up social connection drivers like so: 15 | | social_connections: ["facebook","twitter","linkedIn"] 16 | | 17 | */ 18 | 19 | social_connections: ["facebook"], // ["facebook","twitter","linkedIn"] 20 | 21 | /* 22 | |-------------------------------------------------------------------------- 23 | | Social connections 24 | |-------------------------------------------------------------------------- 25 | | 26 | | Here you can configure your social connection information 27 | | for any of the drivers you choose. 28 | | 29 | */ 30 | 31 | connections: { 32 | facebook: { 33 | driver: "facebook", 34 | clientID: env("FACEBOOK_CLIENT_ID"), 35 | clientSecret: env("FACEBOOK_CLIENT_SECRET"), 36 | callbackURL: "http://localhost:5000/api/facebook/secrets", 37 | }, 38 | google: { 39 | driver: "google", 40 | clientID: env("GOOGLE_CLIENT_ID"), 41 | clientSecret: env("GOOGLE_CLIENT_SECRET"), 42 | callbackURL: "http://localhost:5000/api/auth/google/callback", 43 | }, 44 | twitter: { 45 | driver: "twitter", 46 | consumerKey: env("TWITTER_CONSUMER_KEY"), 47 | consumerSecret: env("TWITTER_CONSUMER_SECRET"), 48 | callbackURL: "http://localhost:5000/api/auth/twitter/callback", 49 | }, 50 | linkedin: { 51 | driver: "linkedin", 52 | clientID: env("LINKEDIN_CLIENT_ID"), 53 | clientSecret: env("LINKEDIN_CLIENT_SECRET"), 54 | callbackURL: "http://localhost:5000/api/auth/linkedin/callback", 55 | scope: ["r_emailaddress", "r_liteprofile"], 56 | }, 57 | microsoft: { 58 | driver: "microsoft", 59 | clientID: env("MICROSOFT_CLIENT_ID"), 60 | clientSecret: env("MICROSOFT_CLIENT_SECRET"), 61 | callbackURL: "http://localhost:5000/api/auth/microsoft/callback", 62 | scope: ["user.read"], 63 | }, 64 | }, 65 | }; 66 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |

4 | 5 | # 6 | 7 | ExpressWebJs is a **Node FrameWork** with expressive and organised syntax that runs on all 8 | major operating systems. It provides the starting point for creating your node project, allowing 9 | you to focus more on developing your amazing solution. 10 | 11 | ExpressWebJs focuses on providing developer experience and powerful features such as 12 | **dependency injection,database abstraction layer for both SQL and NOSQL, robust routing, code structure, application configuration, testing and more.** 13 | 14 | ExpressWebJs is designed for building professional web applications. 15 | 16 | # Features 17 | 18 | ## ExpressWebJS Features 19 | 20 | - Robust routing 21 | - Focus on high performance 22 | - Super-high test coverage 23 | - HTTP helpers (redirection, caching, etc) 24 | - Support for both SQL and NOSQL database 25 | - Well organised and structured. 26 | - Supports Use Of Dependency Injection 27 | - Supports websocket 28 | - Highly scalable 29 | - Authentication and Authorisation 30 | - Model & JsonSchema 31 | - Middlewares 32 | - Providers 33 | - Upload files 34 | - Logger 35 | - Validation 36 | - Queues 37 | - Task Scheduling 38 | - Multi-tenancy 39 | 40 | ## Follow us on twitter @expresswebjs 41 | 42 | ## Join ExpressWebJs Community on [Discord](https://discord.com/invite/vrPGZCgJuj) to chat with other engineers using using ExpressWebJs 43 | 44 | Our Github discussion page is available for questions and discussions 45 | 46 | [https://github.com/Alexigbokwe/ExpressWebJs/discussions](https://github.com/Alexigbokwe/ExpressWebJs/discussions) 47 | 48 | # Contributing Guide 49 | 50 | Hi! I'm really excited that you are interested in contributing to ExpressWebjs. Before submitting your contribution, please make sure to take a moment and read through our contribution guidelines: 51 | 52 | - [Contribution Guildline](https://github.com/Alexigbokwe/expresswebTS-Version/blob/master/.github/CONTRIBUTION.md) 53 | 54 | ## Security Vulnerabilities 55 | 56 | If you discover any security vulnerability within ExpressWebJs, please send an e-mail to Chukwuemeka Igbokwe via chukwuemekaigbokwe80@gmail.com. All security vulnerabilities will be promptly addressed. 57 | 58 | ## License 59 | 60 | The ExpressWebJs framework is open-sourced software licensed under the [MIT License](https://opensource.org/licenses/MIT). 61 | -------------------------------------------------------------------------------- /Config/cors.ts: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | export default { 4 | /* 5 | |-------------------------------------------------------------------------- 6 | | Origin 7 | |-------------------------------------------------------------------------- 8 | | 9 | | Set a list of origins to be allowed. The value can be one of the following 10 | | 11 | | Boolean: true - Allow current request origin 12 | | Boolean: false - Disallow all 13 | | String - Comma seperated list of allowed origins 14 | | Array - An array of allowed origins 15 | | String: * - A wildcard to allow current request origin 16 | | Function - Receives the current origin and should return one of the above values. 17 | | 18 | */ 19 | origin: true, 20 | 21 | /* 22 | |-------------------------------------------------------------------------- 23 | | Methods 24 | |-------------------------------------------------------------------------- 25 | | 26 | | HTTP methods to be allowed. The value can be one of the following 27 | | 28 | | String - Comma seperated list of allowed methods 29 | | Array - An array of allowed methods 30 | | 31 | */ 32 | methods: ["GET", "PUT", "PATCH", "POST", "DELETE"], 33 | 34 | /* 35 | |-------------------------------------------------------------------------- 36 | | Headers 37 | |-------------------------------------------------------------------------- 38 | | 39 | | List of headers to be allowed via Access-Control-Request-Headers header. 40 | | The value can be on of the following. 41 | | 42 | | Boolean: true - Allow current request headers 43 | | Boolean: false - Disallow all 44 | | String - Comma seperated list of allowed headers 45 | | Array - An array of allowed headers 46 | | String: * - A wildcard to allow current request headers 47 | | Function - Receives the current header and should return one of the above values. 48 | | 49 | */ 50 | headers: true, 51 | 52 | /* 53 | |-------------------------------------------------------------------------- 54 | | Expose Headers 55 | |-------------------------------------------------------------------------- 56 | | 57 | | A list of headers to be exposed via `Access-Control-Expose-Headers` 58 | | header. The value can be on of the following. 59 | | 60 | | Boolean: false - Disallow all 61 | | String: Comma seperated list of allowed headers 62 | | Array - An array of allowed headers 63 | | 64 | */ 65 | exposeHeaders: false, 66 | 67 | /* 68 | |-------------------------------------------------------------------------- 69 | | Credentials 70 | |-------------------------------------------------------------------------- 71 | | 72 | | Define Access-Control-Allow-Credentials header. It should always be a 73 | | boolean. 74 | | 75 | */ 76 | credentials: false, 77 | 78 | /* 79 | |-------------------------------------------------------------------------- 80 | | MaxAge 81 | |-------------------------------------------------------------------------- 82 | | 83 | | Define Access-Control-Allow-Max-Age 84 | | 85 | */ 86 | maxAge: 90, 87 | }; 88 | -------------------------------------------------------------------------------- /Config/filesystems.ts: -------------------------------------------------------------------------------- 1 | import env from "Elucidate/Env"; 2 | import path from "path"; 3 | export default { 4 | /* 5 | |-------------------------------------------------------------------------- 6 | | Default Filesystem Disk 7 | |-------------------------------------------------------------------------- 8 | | 9 | | Here you may specify the default filesystem disk that should be used 10 | | by ExpressWebJs. The "local" disk, as well as a variety of cloud 11 | | based disks are available to your application. 12 | | 13 | */ 14 | 15 | default: env("FILESYSTEM_DRIVER", "local"), 16 | 17 | /* 18 | |-------------------------------------------------------------------------- 19 | | Default Cloud Filesystem Disk 20 | |-------------------------------------------------------------------------- 21 | | 22 | | Many applications store files both locally and in the cloud. For this 23 | | reason, you may specify a default "cloud" driver here. This driver 24 | | will be bound as the Cloud disk implementation in the container. 25 | | 26 | */ 27 | 28 | cloud: env("FILESYSTEM_CLOUD", "s3"), 29 | 30 | /* 31 | |-------------------------------------------------------------------------- 32 | | Filesystem Disks 33 | |-------------------------------------------------------------------------- 34 | | 35 | | Here you may configure as many filesystem "disks" as you wish, and you 36 | | may even configure multiple disks of the same driver. Defaults have 37 | | been setup for each driver as an example of the required options. 38 | | 39 | | Supported Drivers: "local", "s3", "azure", "gridfs","postgreSQL","openstack" 40 | | 41 | */ 42 | 43 | disks: { 44 | local: { 45 | driver: "local", 46 | directory: path.join(__dirname, "../Storage/"), 47 | }, 48 | 49 | // Stream file uploads directly to Amazon S3 50 | s3: { 51 | driver: "s3", 52 | key: env("AWS_ACCESS_KEY"), 53 | secret: env("AWS_SECRET_ACCESS_KEY"), 54 | bucket: env("AWS_BUCKET_NAME"), 55 | region: env("AWS_ACCESS_REGION"), 56 | headers: { 57 | "x-amz-acl": env("AWS_ACL_FILE_PERMISSIONS"), 58 | }, 59 | }, 60 | 61 | // Stream file uploads directly to Azure blob storage. 62 | azure: { 63 | driver: "azure", 64 | key: "YOUR_AZURE_STORAGE_ACCOUNT", 65 | secret: "YOUR_AZURE_API_SECRET", 66 | container: "YOUR_AZURE_CONTAINER", 67 | }, 68 | 69 | // Stream file uploads directly to MongoDB's GridFS. 70 | gridfs: { 71 | driver: "gridfs", 72 | uri: "YOUR_S3_API_KEY", 73 | }, 74 | 75 | // Stream file uploads directly to PostgreSQL database. 76 | postgreSQL: { 77 | driver: "postgreSQL", 78 | uri: "YOUR_S3_API_KEY", 79 | }, 80 | 81 | // Stream file uploads directly to openstack blob. 82 | openstack: { 83 | driver: "openstack", 84 | credentials: { 85 | region: "YOUR_REGION", 86 | userId: "YOUR_USER_ID", 87 | password: "YOUR_PASSWORD", 88 | auth_url: "YOUR_AUTH_URL", 89 | projectId: "YOUR_TENANT_ID", 90 | }, 91 | container: "YOUR_CONTAINER_NAME", 92 | }, 93 | }, 94 | }; 95 | -------------------------------------------------------------------------------- /Config/socket.ts: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | /* 4 | |-------------------------------------------------------------------------- 5 | | Socket.io Config 6 | |-------------------------------------------------------------------------- 7 | | npm i --save socket.io 8 | */ 9 | export default { 10 | /* 11 | |-------------------------------------------------------------------------- 12 | | Path 13 | |-------------------------------------------------------------------------- 14 | | 15 | | The base path on which the socket.io server will accept connections. 16 | | Type {String} 17 | */ 18 | path: "/expressweb-ws", 19 | 20 | /* 21 | |-------------------------------------------------------------------------- 22 | | Serve Client 23 | |-------------------------------------------------------------------------- 24 | | 25 | | Whether to serve the client files 26 | | Type {Boolean} 27 | */ 28 | serveClient: true, 29 | 30 | /* 31 | |-------------------------------------------------------------------------- 32 | | Ping Timeout 33 | |-------------------------------------------------------------------------- 34 | | 35 | | How many ms without a pong packet to consider the connection closed 36 | | Type {Number} 37 | */ 38 | pingTimeout: 5000, 39 | 40 | /* 41 | |-------------------------------------------------------------------------- 42 | | Ping Interval 43 | |-------------------------------------------------------------------------- 44 | | 45 | | How many ms before sending a new ping packet 46 | | 47 | */ 48 | pingInterval: 25000, 49 | 50 | /* 51 | |-------------------------------------------------------------------------- 52 | | Upgrade Timeout 53 | |-------------------------------------------------------------------------- 54 | | 55 | | How many ms before an uncompleted transport upgrade is cancelled 56 | | 57 | */ 58 | upgradeTimeout: 10000, 59 | 60 | /* 61 | |-------------------------------------------------------------------------- 62 | | MaxHttpBufferSize 63 | |-------------------------------------------------------------------------- 64 | | 65 | | How many bytes or characters a message can be, before closing the session (to avoid DoS). 66 | | 67 | */ 68 | maxHttpBufferSize: 10e7, 69 | 70 | /* 71 | |-------------------------------------------------------------------------- 72 | | Transports 73 | |-------------------------------------------------------------------------- 74 | | 75 | | Transports to allow connections to 76 | | 77 | */ 78 | transports: ["polling", "websocket"], 79 | 80 | /* 81 | |-------------------------------------------------------------------------- 82 | | AllowUpgrades 83 | |-------------------------------------------------------------------------- 84 | | 85 | | Whether to allow transport upgrades 86 | | 87 | */ 88 | allowUpgrades: true, 89 | 90 | /* 91 | |-------------------------------------------------------------------------- 92 | | Socket Cors 93 | |-------------------------------------------------------------------------- 94 | | 95 | | Whether to allow transport upgrades 96 | | 97 | */ 98 | cors: { 99 | origin: "*", 100 | methods: ["GET", "POST"], 101 | allowedHeaders: ["Origin", "Content-Type", "Content-Length", "Authorization", "Accept", "X-Requested-With"], 102 | credentials: true, 103 | }, 104 | }; 105 | -------------------------------------------------------------------------------- /Config/app.ts: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | import env from "expresswebcorets/lib/Env"; 3 | export default { 4 | /* 5 | |-------------------------------------------------------------------------- 6 | | Application Name 7 | |-------------------------------------------------------------------------- 8 | | 9 | | This value is the name of your application. This value is used when the 10 | | framework needs to place the application's name in a notification or 11 | | any other location as required by the application or its packages. 12 | | 13 | */ 14 | 15 | name: env("APP_NAME", "ExpressWebJs"), 16 | 17 | /* 18 | |-------------------------------------------------------------------------- 19 | | Application Environment 20 | |-------------------------------------------------------------------------- 21 | | 22 | | This value determines the "environment" your application is currently 23 | | running in. This may determine how you prefer to configure various 24 | | services the application utilizes. Set this in your ".env" file. 25 | | 26 | */ 27 | 28 | env: env("APP_ENV", "production"), 29 | 30 | /* 31 | |-------------------------------------------------------------------------- 32 | | Application Route Prefix 33 | |-------------------------------------------------------------------------- 34 | | 35 | | Define your route prefix binding. Default base route prefix is 'api' 36 | | This will run your project with '/api'. Example: http://127.0.0.1:5100/api 37 | | 38 | */ 39 | 40 | routePrefix: env("ROUTE_PREFIX", "api"), 41 | 42 | /* 43 | |-------------------------------------------------------------------------- 44 | | Application Timezone 45 | |-------------------------------------------------------------------------- 46 | | 47 | | Here you may specify the default timezone for your application, which 48 | | will be used by the Javascript date and date-time functions. We have gone 49 | | ahead and set this to a sensible default for you out of the box. 50 | | 51 | */ 52 | 53 | timezone: "Africa/Lagos", 54 | 55 | /* 56 | |-------------------------------------------------------------------------- 57 | | Application maintenance mode 58 | |-------------------------------------------------------------------------- 59 | | Mode ==> Determine if application is in maintenance mode or not. Default value is false 60 | | Message ==> The message to render while in maintenance mode. 61 | | Retry ==> The number of seconds after which the request may be retried 62 | | Endpoints ==> The endPoints that should be reachable while maintenance mode is enabled. 63 | | endpoints example: ['api/users','api/accounts'] 64 | | 65 | */ 66 | maintenanceMode: { 67 | mode: false, 68 | message: "Application is in maintenance mode.", 69 | retry: 50, 70 | endPoints: ["/api/details/3"], 71 | }, 72 | 73 | /* 74 | |-------------------------------------------------------------------------- 75 | | Autoloaded Service Providers 76 | |-------------------------------------------------------------------------- 77 | | 78 | | The service providers listed here will be automatically loaded on the 79 | | request to your application. Feel free to add your own services to 80 | | this array to grant expanded functionality to your applications. 81 | | 82 | */ 83 | 84 | providers: [ 85 | /* 86 | * ExpressWebJS Framework Service Providers... 87 | */ 88 | "Elucidate/Route/RouteConfigServiceProvider::class", 89 | "Elucidate/Database/DatabaseServiceProvider::class", 90 | /* 91 | * Application Service Providers... 92 | */ 93 | "App/Providers/AppServiceProvider::class", 94 | "App/Providers/RouteServiceProvider::class", 95 | "App/Providers/ShutDownProvider::class", 96 | //"App/Providers/SocketServiceProvider::class", 97 | ], 98 | 99 | /* 100 | |-------------------------------------------------------------------------- 101 | | Static Directories 102 | |-------------------------------------------------------------------------- 103 | | 104 | | Here you may specify the static directories that will be copied to build 105 | | folder during build process. 106 | | 107 | */ 108 | 109 | static_directories: [ 110 | { source: "Logs", destination: "build/Logs" }, 111 | { source: "Resources", destination: "build/Resources" }, 112 | ], 113 | }; 114 | -------------------------------------------------------------------------------- /.github/CONTRIBUTION.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | When contributing to this repository, please first discuss the change you wish to make via issue, 4 | email, or any other method with the owners of this repository before making a change. 5 | 6 | Please note we have a code of conduct, please follow it in all your interactions with the project. 7 | 8 | ## Pull Request Process 9 | 1. The `master` branch is just a snapshot of the latest stable release. All development should be done in dedicated branches. **Do not submit PRs against the `master` branch.** 10 | 2. Checkout a topic branch from the relevant branch, e.g. `dev`, and merge back against that branch. 11 | 3. Ensure any install or build dependencies are removed. 12 | 4. Update the README.md with details of changes to the interface, this includes new environment 13 | variables, exposed ports, useful file locations and container parameters. 14 | 5. Increase the version numbers in any examples files and the README.md to the new version that this 15 | Pull Request would represent. The versioning scheme we use is [SemVer](http://semver.org/). 16 | 17 | 18 | 19 | ## Code of Conduct 20 | 21 | ### Our Pledge 22 | 23 | In the interest of fostering an open and welcoming environment, we as 24 | contributors and maintainers pledge to making participation in our project and 25 | our community a harassment-free experience for everyone, regardless of age, body 26 | size, disability, ethnicity, gender identity and expression, level of experience, 27 | nationality, personal appearance, race, religion, or sexual identity and 28 | orientation. 29 | 30 | ### Our Standards 31 | 32 | Examples of behavior that contributes to creating a positive environment 33 | include: 34 | 35 | * Using welcoming and inclusive language 36 | * Being respectful of differing viewpoints and experiences 37 | * Gracefully accepting constructive criticism 38 | * Focusing on what is best for the community 39 | * Showing empathy towards other community members 40 | 41 | Examples of unacceptable behavior by participants include: 42 | 43 | * The use of sexualized language or imagery and unwelcome sexual attention or 44 | advances 45 | * Trolling, insulting/derogatory comments, and personal or political attacks 46 | * Public or private harassment 47 | * Publishing others' private information, such as a physical or electronic 48 | address, without explicit permission 49 | * Other conduct which could reasonably be considered inappropriate in a 50 | professional setting 51 | 52 | ### Our Responsibilities 53 | 54 | Project maintainers are responsible for clarifying the standards of acceptable 55 | behavior and are expected to take appropriate and fair corrective action in 56 | response to any instances of unacceptable behavior. 57 | 58 | Project maintainers have the right and responsibility to remove, edit, or 59 | reject comments, commits, code, wiki edits, issues, and other contributions 60 | that are not aligned to this Code of Conduct, or to ban temporarily or 61 | permanently any contributor for other behaviors that they deem inappropriate, 62 | threatening, offensive, or harmful. 63 | 64 | ### Scope 65 | 66 | This Code of Conduct applies both within project spaces and in public spaces 67 | when an individual is representing the project or its community. Examples of 68 | representing a project or community include using an official project e-mail 69 | address, posting via an official social media account, or acting as an appointed 70 | representative at an online or offline event. Representation of a project may be 71 | further defined and clarified by project maintainers. 72 | 73 | ### Enforcement 74 | 75 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 76 | reported by contacting the project team at. All 77 | complaints will be reviewed and investigated and will result in a response that 78 | is deemed necessary and appropriate to the circumstances. The project team is 79 | obligated to maintain confidentiality with regard to the reporter of an incident. 80 | Further details of specific enforcement policies may be posted separately. 81 | 82 | Project maintainers who do not follow or enforce the Code of Conduct in good 83 | faith may face temporary or permanent repercussions as determined by other 84 | members of the project's leadership. 85 | 86 | ### Attribution 87 | 88 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 89 | available at [http://contributor-covenant.org/version/1/4][version] 90 | 91 | [homepage]: http://contributor-covenant.org 92 | [version]: http://contributor-covenant.org/version/1/4/ -------------------------------------------------------------------------------- /Config/database.ts: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | import env from "expresswebcorets/lib/Env"; 3 | import path from "path"; 4 | export default { 5 | /* 6 | |-------------------------------------------------------------------------- 7 | | Database Multitenance 8 | |-------------------------------------------------------------------------- 9 | | 10 | | Database multitenace can be activated by switching the value to true and can 11 | | be deactivated by switching it to false. 12 | | 13 | */ 14 | database_multitenance: env("DB_MULTITENANCE", false), 15 | /* 16 | |-------------------------------------------------------------------------- 17 | | Multitenance Connections 18 | |-------------------------------------------------------------------------- 19 | | 20 | | Database multitenace connection enables interaction with multiple 21 | | SQL databases where each database is a tenant in your system. 22 | | The tenant array accepts an object of database connections (tenants). 23 | | 24 | */ 25 | multitenant_tenants: [], 26 | /* 27 | |-------------------------------------------------------------------------- 28 | | MySQL Database 29 | |-------------------------------------------------------------------------- 30 | | 31 | | Here we define connection settings for MySQL database. 32 | | 33 | | npm i --save mysql mysql2 34 | | 35 | */ 36 | mysql: { 37 | client: "mysql", 38 | connection: { 39 | host: env("DB_HOST"), 40 | port: env("DB_PORT"), 41 | user: env("DB_USER"), 42 | password: env("DB_PASSWORD"), 43 | database: env("DB_DATABASE"), 44 | }, 45 | migrations: { 46 | directory: path.join(__dirname, "../Database/Migrations/"), 47 | tableName: "migrations", 48 | stub: path.join(__dirname, "../Database/Migrations/migrationLayout.stub"), 49 | extension: "ts", 50 | }, 51 | seeds: { 52 | directory: path.join(__dirname, "../Database/Seeds/"), 53 | }, 54 | }, 55 | /* 56 | |-------------------------------------------------------------------------- 57 | | PostgreSQL Database 58 | |-------------------------------------------------------------------------- 59 | | 60 | | Here we define connection settings for PostgreSQL database. 61 | | 62 | | npm i --save pg 63 | | 64 | | npm install --save pg pg-hstore 65 | | 66 | */ 67 | pg: { 68 | client: "pg", 69 | connection: { 70 | host: env("DB_HOST"), 71 | port: env("DB_PORT"), 72 | user: env("DB_USER"), 73 | password: env("DB_PASSWORD"), 74 | database: env("DB_DATABASE"), 75 | }, 76 | migrations: { 77 | directory: path.join(__dirname, "../Database/Migrations/"), 78 | tableName: "migrations", 79 | stub: path.join(__dirname, "../Database/Migrations/migrationLayout.stub"), 80 | extension: "ts", 81 | }, 82 | seeds: { 83 | directory: path.join(__dirname, "../Database/Seeds/"), 84 | }, 85 | }, 86 | /* 87 | |-------------------------------------------------------------------------- 88 | | MongoDB Database 89 | |-------------------------------------------------------------------------- 90 | | 91 | | Here we define connection settings for MongoDB database. 92 | | 93 | | npm i --save mongoose 94 | | 95 | */ 96 | mongoose: { 97 | client: "mongoose", 98 | host: env("DB_HOST"), 99 | port: env("DB_PORT"), 100 | user: env("DB_USER"), 101 | password: env("DB_PASSWORD"), 102 | database: env("DB_DATABASE"), 103 | useCreateIndex: env("DB_USECREATEINDEX"), 104 | useNewUrlParser: env("DB_USENEWURLPARSER"), 105 | useUnifiedTopology: env("DB_USEUNIFIEDTOPOLOGY"), 106 | connection: { 107 | connection_link: `mongodb://${env("DB_USER")}:${env("DB_PASSWORD")}@${env("DB_HOST")}:${env("DB_PORT")}/${env("DB_DATABASE")}`, 108 | }, 109 | }, 110 | 111 | /* 112 | |-------------------------------------------------------------------------- 113 | | Redis Database 114 | |-------------------------------------------------------------------------- 115 | | 116 | | Here we define connection settings for Redis database. 117 | | 118 | | npm i --save ioredis 119 | | 120 | */ 121 | redis: { 122 | client: env("REDIS_CLIENT", "default"), 123 | 124 | default: { 125 | host: env("REDIS_HOST", "127.0.0.1"), 126 | port: env("REDIS_PORT", 6379), 127 | password: env("REDIS_PASSWORD", null), 128 | database: env("REDIS_DB", 0), 129 | }, 130 | 131 | cache: { 132 | host: env("REDIS_HOST", "127.0.0.1"), 133 | port: env("REDIS_PORT", 6379), 134 | password: env("REDIS_PASSWORD", null), 135 | database: env("REDIS_DB", 0), 136 | }, 137 | }, 138 | 139 | /* 140 | |-------------------------------------------------------------------------- 141 | | Default Connection 142 | |-------------------------------------------------------------------------- 143 | | 144 | | Connection defines the default connection settings to be used while 145 | | interacting with databases. 146 | | list of connections : mysql, mongoose 147 | | 148 | */ 149 | Default_connection: env("DB_CONNECTION"), 150 | }; 151 | -------------------------------------------------------------------------------- /Config/bodyParser.ts: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | export default { 4 | /* 5 | |-------------------------------------------------------------------------- 6 | | JSON Parser 7 | |-------------------------------------------------------------------------- 8 | | 9 | | Below settings are applied when the request body contains a JSON payload. 10 | | If you want body parser to ignore JSON payloads, then simply set `types` 11 | | to an empty array. 12 | */ 13 | json: { 14 | /* 15 | |-------------------------------------------------------------------------- 16 | | limit 17 | |-------------------------------------------------------------------------- 18 | | 19 | | Defines the limit of JSON that can be sent by the client. If payload 20 | | is over 1mb it will not be processed. 21 | | 22 | */ 23 | limit: "1mb", 24 | 25 | /* 26 | |-------------------------------------------------------------------------- 27 | | strict 28 | |-------------------------------------------------------------------------- 29 | | 30 | | When `strict` is set to true, body parser will only parse Arrays and 31 | | Object. Otherwise everything parseable by `JSON.parse` is parsed. 32 | | 33 | */ 34 | strict: true, 35 | 36 | /* 37 | |-------------------------------------------------------------------------- 38 | | types 39 | |-------------------------------------------------------------------------- 40 | | 41 | | Which content types are processed as JSON payloads. You are free to 42 | | add your own types here, but the request body should be parseable 43 | | by `JSON.parse` method. 44 | | 45 | */ 46 | types: [ 47 | "application/json", 48 | "application/json-patch+json", 49 | "application/vnd.api+json", 50 | "application/csp-report", 51 | ], 52 | }, 53 | 54 | /* 55 | |-------------------------------------------------------------------------- 56 | | Raw Parser 57 | |-------------------------------------------------------------------------- 58 | | 59 | | 60 | | 61 | */ 62 | raw: { 63 | types: ["text/*"], 64 | }, 65 | 66 | /* 67 | |-------------------------------------------------------------------------- 68 | | Form Parser 69 | |-------------------------------------------------------------------------- 70 | | 71 | | 72 | | 73 | */ 74 | form: { 75 | types: ["application/x-www-form-urlencoded"], 76 | }, 77 | 78 | /* 79 | |-------------------------------------------------------------------------- 80 | | Files Parser 81 | |-------------------------------------------------------------------------- 82 | | 83 | | 84 | | 85 | */ 86 | files: { 87 | types: ["multipart/form-data"], 88 | 89 | /* 90 | |-------------------------------------------------------------------------- 91 | | Max Size 92 | |-------------------------------------------------------------------------- 93 | | 94 | | Below value is the max size of all the files uploaded to the server. It 95 | | is validated even before files have been processed and hard exception 96 | | is thrown. 97 | | 98 | | Consider setting a reasonable value here, otherwise people may upload GB's 99 | | of files which will keep your server busy. 100 | | 101 | | Also this value is considered when `autoProcess` is set to true. 102 | | 103 | */ 104 | maxSize: "20mb", 105 | 106 | /* 107 | |-------------------------------------------------------------------------- 108 | | Auto Process 109 | |-------------------------------------------------------------------------- 110 | | 111 | | Whether or not to auto-process files. Since HTTP servers handle files via 112 | | couple of specific endpoints. It is better to set this value off and 113 | | manually process the files when required. 114 | | 115 | | This value can contain a boolean or an array of route patterns 116 | | to be autoprocessed. 117 | */ 118 | autoProcess: true, 119 | 120 | /* 121 | |-------------------------------------------------------------------------- 122 | | Process Manually 123 | |-------------------------------------------------------------------------- 124 | | 125 | | The list of routes that should not process files and instead rely on 126 | | manual process. This list should only contain routes when autoProcess 127 | | is to true. Otherwise everything is processed manually. 128 | | 129 | */ 130 | processManually: [], 131 | 132 | /* 133 | |-------------------------------------------------------------------------- 134 | | Temporary file name 135 | |-------------------------------------------------------------------------- 136 | | 137 | | Define a function, which should return a string to be used as the 138 | | tmp file name. 139 | | 140 | | If not defined, Bodyparser will use `uuid` as the tmp file name. 141 | | 142 | | To be defined as. If you are defining the function, then do make sure 143 | | to return a value from it. 144 | | 145 | | tmpFileName () { 146 | | return 'some-unique-value' 147 | | } 148 | | 149 | */ 150 | }, 151 | }; 152 | -------------------------------------------------------------------------------- /Resources/RouteDocumentation/index.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ExpressWebjs API Documentation Page 6 | 7 | 9 | 10 | 11 | 12 |
13 |

14 | 16 | ExpressWebjs, the Nodejs Framework for you. 17 |

18 |
Project API Documentation Page
19 | 20 | 21 |
22 | <% endPoints.forEach( function(endPoint, key) { %> 23 |
24 |

25 | 28 |

29 |
30 |
31 |
32 |

Description: 33 | <%= endPoint.description%> 34 |

35 |

Method: 36 | <% if(endPoint.method == "delete"){ %> 37 | 38 | <% } else if(endPoint.method == "patch"){ %> 39 | 40 | <% } else if(endPoint.method == "get"){ %> 41 | 42 | <% } else if(endPoint.method == "post"){ %> 43 | 44 | <% } else{ %> 45 | 46 | <% } %> 47 |

48 |

Middlewares: 49 | <%= endPoint.middleware%> 50 |

51 |

Request: 52 |

53 | { 54 |
55 | <% for(param in endPoint.request) { %> 56 |
<%- JSON.stringify(param)%>:<%- JSON.stringify(endPoint.request[param],undefined, 4)%>
57 | <% } %> 58 |
59 | } 60 |
61 |

62 |

Response: 63 |

64 | { 65 |
66 | <% for(param in endPoint.response) { %> 67 |
<%- JSON.stringify(param)%>:<%- JSON.stringify(endPoint.response[param],undefined, 4)%>
68 | <% } %> 69 |
70 | } 71 |
72 |

73 |
74 |
75 |
76 |
77 | <% }) %> 78 |
79 |
80 | 81 |
82 |
83 | Open-source MIT Licensed | Copyright © 2021 ExpressWeb Js 84 |
85 |

86 | 88 |

89 |
90 | 91 | 92 | 93 | 98 | 99 | --------------------------------------------------------------------------------