├── .DS_Store ├── .dockerignore ├── .env.example ├── .eslintrc.json ├── .github ├── FUNDING.yml └── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── .gitignore ├── .husky └── pre-commit ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── Dockerfile ├── LICENSE ├── README.md ├── SECURITY.md ├── app ├── controllers │ └── index.controller.js ├── helpers │ └── methods.js ├── middlewares │ ├── error.middleware.js │ ├── logger.middleware.js │ └── validators │ │ └── index.validations.js ├── routes │ └── api.route.js ├── server.js └── tests │ ├── index.fail.validation.test.js │ ├── index.get.test.js │ └── index.post.test.js ├── bin ├── files │ ├── .sequelizerc │ ├── mongodb.connection.js │ ├── mysql.config.js │ ├── package.json │ └── sqlite.config.js ├── installer.js ├── methods.js ├── publish.js └── setup.js ├── http ├── http-client.env.json └── index.http ├── log ├── .DS_Store ├── access │ ├── 1-10-2024.log │ ├── 7-26-2023.log │ ├── 8-1-2023.log │ ├── 8-2-2023.log │ ├── 9-5-2023.log │ └── 9-6-2023.log └── error │ ├── 1-10-2024.log │ ├── 8-1-2023.log │ ├── 8-2-2023.log │ ├── 9-5-2023.log │ └── 9-6-2023.log ├── package.json └── x /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3rd-planet/framework-x/b181063241a7f0a4799b5f9f7114279f30a23ba1/.DS_Store -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | .gitignore 3 | .gitattributes 4 | LICENSE 5 | README.md -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | APP_URL=http://localhost:5000 2 | APP_NAME=FrameworkX 3 | 4 | NODE_ENV=development 5 | HOST=127.0.0.1 6 | PORT=5000 7 | 8 | MONGO_URI= 9 | 10 | VALIDATION_FAIL_CODE=406 11 | EXCEPTION_CODE=400 12 | 13 | # DB config 14 | DB_DIALECT=mysql 15 | DB_PORT=3306 16 | DB_HOST=127.0.0.1 17 | DB_USERNAME=root 18 | DB_PASSWORD=root 19 | DB_NAME=xapi 20 | 21 | # Cache config 22 | CACHE_ENABLED=false 23 | CACHE_UPDATE_INTERVAL=10000 24 | CACHE_EXPIRE_TIME=60000 25 | 26 | REDIS_HOST= 27 | REDIS_PORT=6379 28 | REDIS_USERNAME= 29 | REDIS_PASSWORD= 30 | REDIS_DB=0 31 | 32 | # mail config 33 | MAILER_HOST="sandbox.smtp.mailtrap.io" 34 | # 25 or 465 or 587 or 2525 35 | MAILER_PORT=2525 36 | MAILER_USER= 37 | MAILER_PASS= 38 | # true for 465, false for other ports 39 | MAILER_SECURE=false 40 | MAILER_FROM='"Fred Foo 👻" ' -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "commonjs": true, 5 | "es2021": true, 6 | "node": true, 7 | "jest": true 8 | }, 9 | "extends": "eslint:recommended", 10 | "parserOptions": { 11 | "ecmaVersion": 2020 12 | }, 13 | "rules": { 14 | "semi": [2, "never"], 15 | "no-case-declarations": "off" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: msamgan 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry 13 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 14 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: "" 5 | labels: "" 6 | assignees: "" 7 | --- 8 | 9 | **Describe the bug** 10 | A clear and concise description of what the bug is. 11 | 12 | **To Reproduce** 13 | Steps to reproduce the behavior: 14 | 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | 28 | - OS: [e.g. iOS] 29 | - Browser [e.g. chrome, safari] 30 | - Version [e.g. 22] 31 | 32 | **Smartphone (please complete the following information):** 33 | 34 | - Device: [e.g. iPhone6] 35 | - OS: [e.g. iOS8.1] 36 | - Browser [e.g. stock browser, safari] 37 | - Version [e.g. 22] 38 | 39 | **Additional context** 40 | Add any other context about the problem here. 41 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: "" 5 | labels: "" 6 | assignees: "" 7 | --- 8 | 9 | **Is your feature request related to a problem? Please describe.** 10 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 11 | 12 | **Describe the solution you'd like** 13 | A clear and concise description of what you want to happen. 14 | 15 | **Describe alternatives you've considered** 16 | A clear and concise description of any alternative solutions or features you've considered. 17 | 18 | **Additional context** 19 | Add any other context or screenshots about the feature request here. 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .env 2 | node_modules 3 | .idea 4 | site 5 | dist 6 | 7 | pnpm-lock.yaml 8 | package-lock.json 9 | yarn.lock -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | npm test 5 | prettier --write . 6 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, religion, or sexual identity 10 | and orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | - Demonstrating empathy and kindness toward other people 21 | - Being respectful of differing opinions, viewpoints, and experiences 22 | - Giving and gracefully accepting constructive feedback 23 | - Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | - Focusing on what is best not just for us as individuals, but for the 26 | overall community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | - The use of sexualized language or imagery, and sexual attention or 31 | advances of any kind 32 | - Trolling, insulting or derogatory comments, and personal or political attacks 33 | - Public or private harassment 34 | - Publishing others' private information, such as a physical or email 35 | address, without their explicit permission 36 | - Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards of 42 | acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies when 54 | an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail address, 56 | posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement at 63 | mohdsamgankhan@gmail.com. 64 | All complaints will be reviewed and investigated promptly and fairly. 65 | 66 | All community leaders are obligated to respect the privacy and security of the 67 | reporter of any incident. 68 | 69 | ## Enforcement Guidelines 70 | 71 | Community leaders will follow these Community Impact Guidelines in determining 72 | the consequences for any action they deem in violation of this Code of Conduct: 73 | 74 | ### 1. Correction 75 | 76 | **Community Impact**: Use of inappropriate language or other behavior deemed 77 | unprofessional or unwelcome in the community. 78 | 79 | **Consequence**: A private, written warning from community leaders, providing 80 | clarity around the nature of the violation and an explanation of why the 81 | behavior was inappropriate. A public apology may be requested. 82 | 83 | ### 2. Warning 84 | 85 | **Community Impact**: A violation through a single incident or series 86 | of actions. 87 | 88 | **Consequence**: A warning with consequences for continued behavior. No 89 | interaction with the people involved, including unsolicited interaction with 90 | those enforcing the Code of Conduct, for a specified period of time. This 91 | includes avoiding interactions in community spaces as well as external channels 92 | like social media. Violating these terms may lead to a temporary or 93 | permanent ban. 94 | 95 | ### 3. Temporary Ban 96 | 97 | **Community Impact**: A serious violation of community standards, including 98 | sustained inappropriate behavior. 99 | 100 | **Consequence**: A temporary ban from any sort of interaction or public 101 | communication with the community for a specified period of time. No public or 102 | private interaction with the people involved, including unsolicited interaction 103 | with those enforcing the Code of Conduct, is allowed during this period. 104 | Violating these terms may lead to a permanent ban. 105 | 106 | ### 4. Permanent Ban 107 | 108 | **Community Impact**: Demonstrating a pattern of violation of community 109 | standards, including sustained inappropriate behavior, harassment of an 110 | individual, or aggression toward or disparagement of classes of individuals. 111 | 112 | **Consequence**: A permanent ban from any sort of public interaction within 113 | the community. 114 | 115 | ## Attribution 116 | 117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 118 | version 2.0, available at 119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. 120 | 121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct 122 | enforcement ladder](https://github.com/mozilla/diversity). 123 | 124 | [homepage]: https://www.contributor-covenant.org 125 | 126 | For answers to common questions about this code of conduct, see the FAQ at 127 | https://www.contributor-covenant.org/faq. Translations are available at 128 | https://www.contributor-covenant.org/translations. 129 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Transcriptase 2 | 3 | We love your input! We want to make contributing to this project as easy and transparent as possible, whether it's: 4 | 5 | - Reporting a bug 6 | - Discussing the current state of the code 7 | - Submitting a fix 8 | - Proposing new features 9 | - Becoming a maintainer 10 | 11 | ## We Develop with Github 12 | 13 | We use github to host code, to track issues and feature requests, as well as accept pull requests. 14 | 15 | ## We Use [Github Flow](https://docs.github.com/en), So All Code Changes Happen Through Pull Requests 16 | 17 | Pull requests are the best way to propose changes to the codebase (we use [Github Flow](https://docs.github.com/en)). We actively welcome your pull requests: 18 | 19 | 1. Fork the repo and create your branch from `main`. 20 | 2. If you've added code that should be tested, add tests. 21 | 3. If you've changed APIs, update the documentation. 22 | 4. Ensure the test suite passes. 23 | 5. Make sure your code lints. 24 | 6. Issue that pull request! 25 | 26 | ## Any contributions you make will be under the MIT Software License 27 | 28 | In short, when you submit code changes, your submissions are understood to be under the same [MIT License](http://choosealicense.com/licenses/mit/) that covers the project. Feel free to contact the maintainers if that's a concern. 29 | 30 | ## Report bugs using Github's [issues](https://github.com/3rd-planet/framework-x/issues/new/choose) 31 | 32 | We use GitHub issues to track public bugs. Report a bug by [opening a new issue](); it's that easy! 33 | 34 | ## Write bug reports with detail, background, and sample code 35 | 36 | [This is an example](http://stackoverflow.com/q/12488905/180626) of a bug report I wrote, and I think it's not a bad model. Here's [another example from Craig Hockenberry](http://www.openradar.me/11905408), an app developer whom I greatly respect. 37 | 38 | **Great Bug Reports** tend to have: 39 | 40 | - A quick summary and/or background 41 | - Steps to reproduce 42 | - Be specific! 43 | - Give sample code if you can. [My stackoverflow question](http://stackoverflow.com/q/12488905/180626) includes sample code that _anyone_ with a base R setup can run to reproduce what I was seeing 44 | - What you expected would happen 45 | - What actually happens 46 | - Notes (possibly including why you think this might be happening, or stuff you tried that didn't work) 47 | 48 | People _love_ thorough bug reports. I'm not even kidding. 49 | 50 | ## Use a Consistent Coding Style 51 | 52 | I'm again borrowing these from [Facebook's Guidelines](https://github.com/facebook/draft-js/blob/a9316a723f9e918afde44dea68b5f9f39b7d9b00/CONTRIBUTING.md) 53 | 54 | - 4 spaces for indentation rather than tabs 55 | 56 | ## License 57 | 58 | By contributing, you agree that your contributions will be licensed under its MIT License. 59 | 60 | ## References 61 | 62 | This document was adapted from the open-source contribution guidelines for [Facebook's Draft](https://github.com/facebook/draft-js/blob/a9316a723f9e918afde44dea68b5f9f39b7d9b00/CONTRIBUTING.md) 63 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:18.16 2 | WORKDIR /app 3 | COPY package*.json ./ 4 | RUN pnpm i 5 | COPY . . 6 | EXPOSE 5000 7 | CMD [ "npm", "start" ] 8 | 9 | # sudo docker build --tag node-docker . 10 | # sudo docker run -p 5000:5000 node-docker -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Mohd Samgan Khan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![GitHub Release Date - Published_At](https://img.shields.io/github/release-date/3rd-planet/framework-x) 2 | ![GitHub](https://img.shields.io/github/license/3rd-planet/framework-x) 3 | ![GitHub package.json version (branch)](https://img.shields.io/github/package-json/v/3rd-planet/framework-x/main) 4 | ![GitHub top language](https://img.shields.io/github/languages/top/3rd-planet/framework-x) 5 | ![GitHub language count](https://img.shields.io/github/languages/count/3rd-planet/framework-x) 6 | 7 | ![GitHub Repo stars](https://img.shields.io/github/stars/3rd-planet/framework-x?style=social) 8 | ![GitHub forks](https://img.shields.io/github/forks/3rd-planet/framework-x?style=social) 9 | ![GitHub watchers](https://img.shields.io/github/watchers/3rd-planet/framework-x?style=social) 10 | 11 |

12 | 13 |

14 | 15 | > Your Accelerated Path to API Creation 16 | 17 | ## Installation 18 | 19 | ```JS 20 | npx @3rdplanet/framework-x 21 | ``` 22 | 23 | ```JS 24 | npm start 25 | ``` 26 | 27 | ## Features 28 | 29 | Framework X comprises a number of features that are designed to make it easy to build and maintain complex web applications. These features include: 30 | 31 | - An **MVC based architecture** for building scalable applications 32 | - A **routing solution** that lets you build single-page applications with ease 33 | - **Inbuilt testing Architecture** that lets you test your application's code with ease 34 | - A **CLI** that lets you create, build, test, and run your application with ease 35 | - **ORM support** (sequelize, mongoose) out of the box 36 | - **Multiple Package Manager support** (npm, yarn, pnpm, bun) out of the box 37 | - **Inbuilt support for multiple databases** via ORM 38 | - **Inbuilt support for multiple templating engines** (ejs, pug, handlebars, mustache, nunjucks, twig, vash, and more) via Express 39 | - **Docker support** out of the box 40 | - **Inbuilt Repository Pattern** for building scalable applications 41 | - **Logging support** out of the box using Simple Node Logger 42 | - **Inbuilt support for Super Charged Cache** With Redis. See [Cache documentation](https://www.frameworkx.info/docs/overview/cache) for more details 43 | - **Inbuilt support for Nodemailer with MJML** for sending emails. See [Mailer documentation](https://www.frameworkx.info/docs/overview/mail) for more details 44 | 45 | ## Features in the pipeline 46 | 47 | - **Authentication Module** - We're working on a new authentication module that will allow you to create and manage users. This will be a great addition to the framework, and will be available as a separate package. 48 | - **Role and Permissions Module** - We're also working on role and permissions module that will allow you to create and manage roles and permissions as per the needs of your application. This will be available as a separate package. 49 | - **Social Login** - We're working on a social login module that will allow you to integrate social login into your application. This will be available as a separate package. 50 | - **Notification Module** - We're working on a notification module that will allow you to create and manage notification.Notification email, sms, push, in-app, etc. This will be available as a separate package. 51 | - **UI Layer** - We're working on a new UI for the framework. Which will be available with the Authentication Module. You will be able to choose form a number of platforms like React, Vue, Angular, etc. 52 | 53 | ## Documentation 54 | 55 | [Click Here](https://www.frameworkx.info/) for the documentation 56 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | All Versions are supported for Security Updates. 6 | 7 | ## Reporting a Vulnerability 8 | 9 | Please report any security concern on **mohdsamgankhan@gmail.com** 10 | -------------------------------------------------------------------------------- /app/controllers/index.controller.js: -------------------------------------------------------------------------------- 1 | const { successResponse } = require("../helpers/methods") 2 | 3 | /** 4 | * 5 | * @param req 6 | * @param res 7 | * @returns {Promise} 8 | */ 9 | exports.index = async (req, res) => { 10 | return res.send( 11 | successResponse("framework-x is working like a charm...", { 12 | data: "here comes you payload..." 13 | }) 14 | ) 15 | } 16 | 17 | /** 18 | * 19 | * @param req 20 | * @param res 21 | * @returns {Promise} 22 | */ 23 | exports.indexPost = async (req, res) => { 24 | return res.send( 25 | successResponse("framework-x post api is working like a charm...", { 26 | data: "here comes you payload...", 27 | request: req.body 28 | }) 29 | ) 30 | } 31 | -------------------------------------------------------------------------------- /app/helpers/methods.js: -------------------------------------------------------------------------------- 1 | const { validationResult } = require("express-validator") 2 | 3 | /** 4 | * 5 | * @param message 6 | * @param payload 7 | * @param statusCode 8 | * @returns { 9 | * { 10 | * message: *, 11 | * status: boolean, 12 | * status_code: number, 13 | * package: * 14 | * } 15 | * } 16 | * @example 17 | * const { successResponse } = require("../helpers/methods") 18 | * res.status(200).json(successResponse("User created successfully", user, 200)) 19 | */ 20 | exports.successResponse = (message, payload, statusCode = 200) => { 21 | return { 22 | status: true, 23 | status_code: statusCode, 24 | message: message, 25 | package: payload 26 | } 27 | } 28 | 29 | /** 30 | * 31 | * @param message 32 | * @param payload 33 | * @param statusCode 34 | * @returns { 35 | * { 36 | * message: *, 37 | * status: boolean, 38 | * status_code: number, 39 | * package: * 40 | * } 41 | * } 42 | * @example 43 | * const { failResponse } = require("../helpers/methods") 44 | * res.status(400).json(failResponse("Validation failed", errors.array(), 400)) 45 | * 46 | * */ 47 | exports.failResponse = (message, payload = null, statusCode = 400) => { 48 | let response = { 49 | status: false, 50 | status_code: statusCode, 51 | message: message 52 | } 53 | 54 | if (payload) { 55 | response.payload = payload 56 | } 57 | 58 | return response 59 | } 60 | -------------------------------------------------------------------------------- /app/middlewares/error.middleware.js: -------------------------------------------------------------------------------- 1 | const methods = require("../helpers/methods") 2 | const errorLog = require("simple-node-logger").createSimpleLogger({ 3 | logFilePath: "./log/error/" + new Date().toLocaleDateString().split("/").join("-") + ".log", 4 | timestampFormat: "YYYY-MM-DD HH:mm:ss" 5 | }) 6 | /** 7 | * 8 | * @param error 9 | * @param req 10 | * @param res 11 | * @param next 12 | * @returns {*} 13 | */ 14 | // eslint-disable-next-line no-unused-vars 15 | module.exports = (error, req, res, next) => { 16 | errorLog.error(error.message) 17 | return res.status(process.env.EXCEPTION_CODE).send(methods.failResponse(error.message)) 18 | } 19 | -------------------------------------------------------------------------------- /app/middlewares/logger.middleware.js: -------------------------------------------------------------------------------- 1 | const accessLog = require("simple-node-logger").createSimpleLogger({ 2 | logFilePath: "./log/access/" + new Date().toLocaleDateString().split("/").join("-") + ".log", 3 | timestampFormat: "YYYY-MM-DD HH:mm:ss" 4 | }) 5 | 6 | /** 7 | * 8 | * @param req 9 | * @param res 10 | * @param next 11 | * @returns {*} 12 | */ 13 | module.exports = (req, res, next) => { 14 | let reqObject = { 15 | method: req.method, 16 | path: req.path, 17 | param: req.params, 18 | body: req.body 19 | } 20 | 21 | let resObject = { 22 | statusCode: res.statusCode 23 | } 24 | 25 | accessLog.info( 26 | JSON.stringify({ 27 | reqObject, 28 | resObject 29 | }) 30 | ) 31 | 32 | next() 33 | } 34 | -------------------------------------------------------------------------------- /app/middlewares/validators/index.validations.js: -------------------------------------------------------------------------------- 1 | const { body } = require("express-validator") 2 | 3 | /** 4 | * @type {ValidationChain[]} 5 | * @example 6 | * const { indexValidator } = require("../middlewares/validators/index.validations") 7 | * router.post("/", validate(indexValidator), IndexController.indexPost) 8 | * 9 | */ 10 | exports.indexValidator = [body("key").exists().withMessage("key is required")] 11 | -------------------------------------------------------------------------------- /app/routes/api.route.js: -------------------------------------------------------------------------------- 1 | const express = require("express") 2 | const router = express.Router() 3 | 4 | const IndexController = require("../controllers/index.controller") 5 | const { validate } = require("@3rdplanet/x-core/helpers/methods") 6 | const { indexValidator } = require("../middlewares/validators/index.validations") 7 | 8 | router.get("/", IndexController.index) 9 | router.post("/", validate(indexValidator), IndexController.indexPost) 10 | 11 | module.exports = router 12 | -------------------------------------------------------------------------------- /app/server.js: -------------------------------------------------------------------------------- 1 | const app = require("@3rdplanet/x-core/app") 2 | const port = process.env.PORT 3 | const errorMiddleware = require("./middlewares/error.middleware") 4 | const accessLogMiddleware = require("./middlewares/logger.middleware") 5 | 6 | console.log(`Node environment: ${process.env.NODE_ENV}`) 7 | app.listen(port, () => { 8 | console.log(`Example app listening at port http://localhost:${port}`) 9 | }) 10 | 11 | app.use(errorMiddleware) 12 | app.use(accessLogMiddleware) 13 | -------------------------------------------------------------------------------- /app/tests/index.fail.validation.test.js: -------------------------------------------------------------------------------- 1 | const app = require("@3rdplanet/x-core/app") 2 | const supertest = require("supertest") 3 | 4 | describe("Test the root post path with fail validation", () => { 5 | test("It should response the POST method with failed validation", async () => { 6 | await supertest(app) 7 | .post("/") 8 | .send({ 9 | ky: "value" //key is requited in validation... 10 | }) 11 | .expect(406) 12 | .then((response) => { 13 | expect(response.body.status).toBe(false) 14 | }) 15 | }) 16 | }) 17 | -------------------------------------------------------------------------------- /app/tests/index.get.test.js: -------------------------------------------------------------------------------- 1 | const app = require("@3rdplanet/x-core/app") 2 | const supertest = require("supertest") 3 | 4 | describe("Test the root path", () => { 5 | test("It should response the GET method", async () => { 6 | await supertest(app) 7 | .get("/") 8 | .expect(200) 9 | .then((response) => { 10 | expect(response.body.status).toBe(true) 11 | }) 12 | }) 13 | }) 14 | -------------------------------------------------------------------------------- /app/tests/index.post.test.js: -------------------------------------------------------------------------------- 1 | const app = require("@3rdplanet/x-core/app") 2 | const supertest = require("supertest") 3 | 4 | describe("Test the root post path", () => { 5 | test("It should response the POST method", async () => { 6 | await supertest(app) 7 | .post("/") 8 | .send({ 9 | key: "value" 10 | }) 11 | .expect(200) 12 | .then((response) => { 13 | expect(response.body.status).toBe(true) 14 | }) 15 | }) 16 | }) 17 | -------------------------------------------------------------------------------- /bin/files/.sequelizerc: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | module.exports = { 4 | 'config': path.resolve('.', 'db.config.js'), 5 | 'models-path': path.resolve('app', 'models'), 6 | 'seeders-path': path.resolve('database', 'seeders'), 7 | 'migrations-path': path.resolve('database', 'migrations') 8 | }; -------------------------------------------------------------------------------- /bin/files/mongodb.connection.js: -------------------------------------------------------------------------------- 1 | const moongose = require("mongoose") 2 | 3 | const connectDB = async () => { 4 | try { 5 | const conn = await moongose.connect(process.env.MONGO_URI, { 6 | useNewUrlParser: true, 7 | useUnifiedTopology: true, 8 | useCreateIndex: true, 9 | useFindAndModify: false 10 | }) 11 | 12 | console.log(`DB connected: ${conn.connection.host}`) 13 | } catch (err) { 14 | console.log(`Error: ${err.message}`) 15 | //Exit with failure. 16 | process.exit(1) 17 | } 18 | } 19 | 20 | module.exports = { connectDB } 21 | -------------------------------------------------------------------------------- /bin/files/mysql.config.js: -------------------------------------------------------------------------------- 1 | const dotenv = require("dotenv").config().parsed 2 | 3 | let config = { 4 | username: dotenv.DB_USERNAME, 5 | password: dotenv.DB_PASSWORD, 6 | database: dotenv.DB_NAME, 7 | host: dotenv.DB_HOST, 8 | port: dotenv.DB_PORT, 9 | dialect: dotenv.DB_DIALECT, 10 | migrationStorageTableName: "sequelize_migrations", 11 | seederStorageTableName: "sequelize_seeds" 12 | } 13 | 14 | module.exports = { 15 | development: config, 16 | test: config, 17 | production: config 18 | } 19 | -------------------------------------------------------------------------------- /bin/files/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "framework-x-app", 3 | "version": "0.0.1", 4 | "description": "some cool description of my awesome app", 5 | "main": "app/server.js", 6 | "scripts": { 7 | "start": "nodemon", 8 | "test": "jest", 9 | "prepare": "husky install" 10 | }, 11 | "xconfig": {}, 12 | "prettier": { 13 | "trailingComma": "none", 14 | "tabWidth": 4, 15 | "semi": false, 16 | "singleQuote": false, 17 | "printWidth": 112 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /bin/files/sqlite.config.js: -------------------------------------------------------------------------------- 1 | const dotenv = require("dotenv").config().parsed 2 | 3 | let config = { 4 | dialect: dotenv.DB_DIALECT, 5 | storage: "./" + dotenv.DB_NAME + ".sqlite3" 6 | } 7 | 8 | module.exports = { 9 | development: config, 10 | test: config, 11 | production: config 12 | } 13 | -------------------------------------------------------------------------------- /bin/installer.js: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env node 2 | 3 | "use strict" 4 | 5 | const path = require("path") 6 | const figlet = require("figlet") 7 | const inquirer = require("inquirer") 8 | const { checkDirExist } = require("./methods") 9 | const { setup } = require("./setup") 10 | const packageJson = require("../package.json") 11 | const loading = require("loading-cli") 12 | const chalk = require("chalk") 13 | 14 | const ownPath = process.cwd() 15 | 16 | const repoUrl = "https://github.com/3rd-planet/framework-x.git" 17 | const version = packageJson.version 18 | 19 | const questions = [ 20 | { 21 | type: "input", 22 | name: "app_name", 23 | message: "You have to provide name to your app", 24 | default() { 25 | return "x-api" 26 | } 27 | }, 28 | { 29 | type: "list", 30 | name: "app_orm", 31 | message: "ORM support?", 32 | choices: ["sequelize", "mongoose", "none"], 33 | filter(val) { 34 | return val.toLowerCase() 35 | } 36 | }, 37 | { 38 | type: "list", 39 | name: "app_db", 40 | message: "Database support for?", 41 | choices: ["mysql", "sqlite", "postgres", "mariadb", "tedious", "oracledb"], 42 | filter(val) { 43 | return val.toLowerCase() 44 | }, 45 | when(answers) { 46 | return answers.app_orm === "sequelize" 47 | } 48 | }, 49 | { 50 | type: "list", 51 | name: "app_db", 52 | message: "Database support for?", 53 | choices: ["mongodb"], 54 | filter(val) { 55 | return val.toLowerCase() 56 | }, 57 | when(answers) { 58 | return answers.app_orm === "mongoose" 59 | } 60 | }, 61 | { 62 | type: "confirm", 63 | name: "docker_support", 64 | message: "Docker support?", 65 | default: false 66 | }, 67 | { 68 | type: "list", 69 | name: "app_package_manager", 70 | message: "Package Manager?", 71 | choices: ["pnpm", "npm", "yarn", "bun"], 72 | filter(val) { 73 | return val.toLowerCase() 74 | } 75 | } 76 | ] 77 | 78 | console.log( 79 | chalk.green( 80 | figlet.textSync("Framework X", { 81 | horizontalLayout: "default", 82 | verticalLayout: "default" 83 | }) 84 | ) 85 | ) 86 | 87 | inquirer.prompt(questions).then(async (answers) => { 88 | const load = loading("Installing awesome Framework, Framework X ...").start() 89 | 90 | answers.clone_command = "git clone -b v" + version + " " + repoUrl + " " + answers.app_name 91 | answers.app_path = path.join(ownPath, answers.app_name) 92 | await checkDirExist(answers.app_path) 93 | await setup(answers) 94 | 95 | load.stop() 96 | 97 | console.log(chalk.blue("Get started...")) 98 | console.log(chalk.blue(` cd ${answers.app_name}`)) 99 | console.log(chalk.blue(" npm start")) 100 | console.log() 101 | console.log(chalk.green("Check documentation (https://www.frameworkx.info/) for more information")) 102 | }) 103 | -------------------------------------------------------------------------------- /bin/methods.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs") 2 | const util = require("util") 3 | const exec = util.promisify(require("child_process").exec) 4 | const chalk = require("chalk") 5 | 6 | /** 7 | * 8 | * @param command 9 | * @returns {Promise} 10 | */ 11 | exports.runCmd = async (command) => { 12 | try { 13 | // eslint-disable-next-line no-unused-vars 14 | const { stdout, stderr } = await exec(command) 15 | } catch (error) { 16 | console.log(chalk.red(error.message)) 17 | } 18 | } 19 | 20 | /** 21 | * 22 | * @param appPath 23 | * @returns {Promise} 24 | */ 25 | exports.checkDirExist = async (appPath) => { 26 | try { 27 | fs.mkdirSync(appPath) 28 | } catch (err) { 29 | if (err.code.toString() === "EEXIST") { 30 | console.log(chalk.red(`The directory ${appPath} already exist in the current directory.`)) 31 | } else { 32 | console.log(err) 33 | } 34 | 35 | process.exit(1) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /bin/publish.js: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env node 2 | 3 | const { runCmd } = require("./methods") 4 | const packageJson = require("../package.json") 5 | 6 | const publish = async () => { 7 | let v = "v" + packageJson.version 8 | console.log(v) 9 | 10 | let gitAdd = 'git add . && git commit -m "' + v + '"' 11 | console.log(gitAdd) 12 | await runCmd(gitAdd) 13 | 14 | let gitTag = "git tag -a " + v + ' -m "' + v + '"' 15 | console.log(gitTag) 16 | await runCmd(gitTag) 17 | 18 | let gitPush = "git push" 19 | console.log(gitPush) 20 | await runCmd(gitPush) 21 | 22 | let gitPushTag = "git push origin --tag" 23 | console.log(gitPushTag) 24 | await runCmd(gitPushTag) 25 | 26 | let npmPublish = "npm publish" 27 | console.log(npmPublish) 28 | await runCmd(npmPublish) 29 | } 30 | 31 | publish().then(() => { 32 | console.log("published....") 33 | }) 34 | -------------------------------------------------------------------------------- /bin/setup.js: -------------------------------------------------------------------------------- 1 | const { runCmd } = require("./methods") 2 | const fs = require("fs") 3 | const path = require("path") 4 | 5 | /** 6 | * 7 | * @type {string[]} 8 | */ 9 | const dependencies = [ 10 | "commander", 11 | "cors", 12 | "dotenv", 13 | "express", 14 | "express-async-errors", 15 | "express-validator", 16 | "simple-node-logger", 17 | "loading-cli", 18 | "redis", 19 | "nodemailer", 20 | "mjml", 21 | "@3rdplanet/x-core", 22 | "helmet" 23 | ] 24 | 25 | /** 26 | * 27 | * @type {string[]} 28 | */ 29 | const devDependencies = ["jest", "nodemon", "supertest", "husky", "prettier"] 30 | 31 | /** 32 | * 33 | * @returns {Promise} 34 | */ 35 | const dependenciesInstall = async (app_package_manager) => { 36 | for (const dependency of dependencies) { 37 | await runCmd(app_package_manager + " install --save " + dependency) 38 | } 39 | 40 | for (const dependency of devDependencies) { 41 | await runCmd(app_package_manager + " install --save-dev " + dependency) 42 | } 43 | } 44 | 45 | /** 46 | * 47 | * @param app_orm 48 | * @param app_db 49 | * @param app_package_manager 50 | * @returns {Promise} 51 | */ 52 | const dbInstall = async (app_orm, app_db, app_package_manager) => { 53 | let appPath = path.join(process.cwd()) 54 | 55 | if (app_orm === "mongoose") { 56 | await runCmd(app_package_manager + " install --save mongoose") 57 | 58 | if (!fs.existsSync(appPath + "/config")) { 59 | await fs.mkdirSync(appPath + "/config") 60 | } 61 | 62 | fs.copyFileSync(appPath + "/bin/files/mongodb.connection.js", appPath + "/config/db.connection.js") 63 | 64 | return 65 | } 66 | 67 | if (app_orm === "sequelize") { 68 | await runCmd(app_package_manager + " install --save sequelize") 69 | 70 | fs.copyFileSync(appPath + "/bin/files/.sequelizerc", appPath + "/.sequelizerc") 71 | 72 | if (app_db === "mysql") { 73 | await runCmd(app_package_manager + " install --save mysql2") 74 | await runCmd("npx sequelize-cli init --force") 75 | await fs.copyFileSync("./bin/files/mysql.config.js", "./db.config.js") 76 | 77 | return 78 | } 79 | 80 | if (app_db === "sqlite") { 81 | await runCmd(app_package_manager + " install --save sqlite3") 82 | await runCmd("npx sequelize-cli init --force") 83 | await fs.copyFileSync("./bin/files/sqlite.config.js", "./db.config.js") 84 | 85 | return 86 | } 87 | 88 | if (app_db === "postgres") { 89 | await runCmd(app_package_manager + " install --save pg pg-hstore") 90 | 91 | return 92 | } 93 | 94 | if (app_db === "mariadb") { 95 | await runCmd(app_package_manager + " install --save mariadb") 96 | 97 | return 98 | } 99 | 100 | if (app_db === "tedious") { 101 | await runCmd(app_package_manager + " install --save tedious") 102 | 103 | return 104 | } 105 | 106 | if (app_db === "oracledb") { 107 | await runCmd(app_package_manager + " install --save oracledb") 108 | } 109 | } 110 | } 111 | 112 | /** 113 | * 114 | * @param app_orm 115 | * @param app_db 116 | * @param app_package_manager 117 | * @returns {Promise} 118 | */ 119 | const updatePackageJson = async (app_orm, app_db, app_package_manager) => { 120 | let packageJson = JSON.parse(fs.readFileSync("./package.json", "utf8")) 121 | packageJson.xconfig = { 122 | orm: app_orm, 123 | db: app_db, 124 | package_manager: app_package_manager 125 | } 126 | 127 | fs.writeFileSync("./package.json", JSON.stringify(packageJson, null, 4)) 128 | } 129 | 130 | /** 131 | * Set up the application 132 | * @param app_path 133 | * @param app_mode 134 | * @param app_orm 135 | * @param app_db 136 | * @param app_package_manager 137 | * @param clone_command 138 | * @param docker_support 139 | * @returns {Promise} 140 | */ 141 | exports.setup = async ({ app_path, app_orm, app_db, app_package_manager, clone_command, docker_support }) => { 142 | try { 143 | await runCmd(clone_command) 144 | process.chdir(app_path) 145 | await fs.copyFileSync("./.env.example", ".env") 146 | await fs.copyFileSync("./bin/files/package.json", "./package.json") 147 | 148 | await updatePackageJson(app_orm, app_db, app_package_manager) 149 | await dependenciesInstall(app_package_manager) 150 | 151 | if (app_orm !== "none") { 152 | await dbInstall(app_orm, app_db, app_package_manager) 153 | } 154 | 155 | let dirToRemove = [".git", ".github", "bin"] 156 | 157 | let filesToRemove = ["README.md", "CODE_OF_CONDUCT.md", "CONTRIBUTING.md", "SECURITY.md", "LICENSE"] 158 | 159 | if (!docker_support) { 160 | filesToRemove.push(".dockerignore") 161 | filesToRemove.push("Dockerfile") 162 | } 163 | 164 | for (const dir of dirToRemove) { 165 | await fs.rmSync(path.join(app_path, dir), { 166 | recursive: true 167 | }) 168 | } 169 | 170 | for (const file of filesToRemove) { 171 | await fs.unlinkSync(path.join(app_path, file)) 172 | } 173 | 174 | /** 175 | * introducing Husky to the system... 176 | */ 177 | await runCmd("git init") 178 | await runCmd("npx husky-init") 179 | await runCmd(app_package_manager + " install") 180 | } catch (error) { 181 | console.log(error) 182 | 183 | process.exit(1) 184 | } 185 | } 186 | -------------------------------------------------------------------------------- /http/http-client.env.json: -------------------------------------------------------------------------------- 1 | { 2 | "development": { 3 | "host": "localhost", 4 | "port": "5000" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /http/index.http: -------------------------------------------------------------------------------- 1 | GET http://{{host}}:{{port}} 2 | 3 | ### 4 | 5 | POST http://{{host}}:{{port}} 6 | Content-Type: application/json 7 | 8 | { 9 | "key": "value" 10 | } -------------------------------------------------------------------------------- /log/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3rd-planet/framework-x/b181063241a7f0a4799b5f9f7114279f30a23ba1/log/.DS_Store -------------------------------------------------------------------------------- /log/access/1-10-2024.log: -------------------------------------------------------------------------------- 1 | 2024-01-10 12:23:34 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 2 | 2024-01-10 12:23:35 INFO {"reqObject":{"method":"GET","path":"/favicon.ico","param":{},"body":{}},"resObject":{"statusCode":200}} 3 | 2024-01-10 13:08:13 INFO {"reqObject":{"method":"GET","path":"/favicon.ico","param":{},"body":{}},"resObject":{"statusCode":200}} 4 | -------------------------------------------------------------------------------- /log/access/7-26-2023.log: -------------------------------------------------------------------------------- 1 | 2023-07-26 01:16:04 INFO {"reqObject":{"method":"POST","path":"/","param":{},"body":{"key":"value"}},"resObject":{"statusCode":200}} 2 | -------------------------------------------------------------------------------- /log/access/8-1-2023.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3rd-planet/framework-x/b181063241a7f0a4799b5f9f7114279f30a23ba1/log/access/8-1-2023.log -------------------------------------------------------------------------------- /log/access/8-2-2023.log: -------------------------------------------------------------------------------- 1 | 2023-08-02 14:25:21 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 2 | 2023-08-02 14:25:21 INFO {"reqObject":{"method":"POST","path":"/","param":{},"body":{"key":"value"}},"resObject":{"statusCode":200}} 3 | 2023-08-02 14:25:21 INFO {"reqObject":{"method":"POST","path":"/","param":{},"body":{"ky":"value"}},"resObject":{"statusCode":200}} 4 | 2023-08-02 14:25:43 INFO {"reqObject":{"method":"POST","path":"/","param":{},"body":{"ky":"value"}},"resObject":{"statusCode":200}} 5 | 2023-08-02 14:25:43 INFO {"reqObject":{"method":"POST","path":"/","param":{},"body":{"keyy":"value"}},"resObject":{"statusCode":200}} 6 | 2023-08-02 14:25:44 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 7 | 2023-08-02 14:26:38 INFO {"reqObject":{"method":"POST","path":"/","param":{},"body":{"keyy":"value"}},"resObject":{"statusCode":200}} 8 | 2023-08-02 14:26:38 INFO {"reqObject":{"method":"POST","path":"/","param":{},"body":{"ky":"value"}},"resObject":{"statusCode":200}} 9 | 2023-08-02 14:26:38 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 10 | 2023-08-02 14:26:56 INFO {"reqObject":{"method":"POST","path":"/","param":{},"body":{"key":"value"}},"resObject":{"statusCode":200}} 11 | 2023-08-02 14:26:56 INFO {"reqObject":{"method":"POST","path":"/","param":{},"body":{"ky":"value"}},"resObject":{"statusCode":200}} 12 | 2023-08-02 14:26:56 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 13 | 2023-08-02 14:29:11 INFO {"reqObject":{"method":"POST","path":"/","param":{},"body":{"key":"value"}},"resObject":{"statusCode":200}} 14 | 2023-08-02 14:29:20 INFO {"reqObject":{"method":"POST","path":"/","param":{},"body":{"keyy":"value"}},"resObject":{"statusCode":200}} 15 | 2023-08-02 14:31:15 INFO {"reqObject":{"method":"POST","path":"/","param":{},"body":{"key":"value"}},"resObject":{"statusCode":200}} 16 | -------------------------------------------------------------------------------- /log/access/9-5-2023.log: -------------------------------------------------------------------------------- 1 | 2023-09-05 10:54:14 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 2 | 2023-09-05 10:54:14 INFO {"reqObject":{"method":"GET","path":"/favicon.ico","param":{},"body":{}},"resObject":{"statusCode":200}} 3 | 2023-09-05 10:55:04 INFO {"reqObject":{"method":"GET","path":"/user","param":{},"body":{}},"resObject":{"statusCode":200}} 4 | 2023-09-05 10:55:16 INFO {"reqObject":{"method":"GET","path":"/user","param":{},"body":{}},"resObject":{"statusCode":200}} 5 | 2023-09-05 10:55:16 INFO {"reqObject":{"method":"GET","path":"/favicon.ico","param":{},"body":{}},"resObject":{"statusCode":200}} 6 | 2023-09-05 11:01:24 INFO {"reqObject":{"method":"GET","path":"/favicon.ico","param":{},"body":{}},"resObject":{"statusCode":200}} 7 | 2023-09-05 11:01:26 INFO {"reqObject":{"method":"GET","path":"/favicon.ico","param":{},"body":{}},"resObject":{"statusCode":200}} 8 | 2023-09-05 11:01:27 INFO {"reqObject":{"method":"GET","path":"/favicon.ico","param":{},"body":{}},"resObject":{"statusCode":200}} 9 | 2023-09-05 11:01:28 INFO {"reqObject":{"method":"GET","path":"/favicon.ico","param":{},"body":{}},"resObject":{"statusCode":200}} 10 | 2023-09-05 11:01:44 INFO {"reqObject":{"method":"GET","path":"/favicon.ico","param":{},"body":{}},"resObject":{"statusCode":200}} 11 | 2023-09-05 11:01:44 INFO {"reqObject":{"method":"GET","path":"/favicon.ico","param":{},"body":{}},"resObject":{"statusCode":200}} 12 | 2023-09-05 11:02:21 INFO {"reqObject":{"method":"GET","path":"/user","param":{},"body":{}},"resObject":{"statusCode":200}} 13 | 2023-09-05 11:02:21 INFO {"reqObject":{"method":"GET","path":"/favicon.ico","param":{},"body":{}},"resObject":{"statusCode":200}} 14 | 2023-09-05 11:02:22 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 15 | 2023-09-05 11:02:22 INFO {"reqObject":{"method":"GET","path":"/favicon.ico","param":{},"body":{}},"resObject":{"statusCode":200}} 16 | 2023-09-05 11:02:23 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 17 | 2023-09-05 11:02:23 INFO {"reqObject":{"method":"GET","path":"/favicon.ico","param":{},"body":{}},"resObject":{"statusCode":200}} 18 | 2023-09-05 11:02:24 INFO {"reqObject":{"method":"GET","path":"/user","param":{},"body":{}},"resObject":{"statusCode":200}} 19 | 2023-09-05 11:02:24 INFO {"reqObject":{"method":"GET","path":"/favicon.ico","param":{},"body":{}},"resObject":{"statusCode":200}} 20 | 2023-09-05 11:02:25 INFO {"reqObject":{"method":"GET","path":"/user","param":{},"body":{}},"resObject":{"statusCode":200}} 21 | 2023-09-05 11:02:25 INFO {"reqObject":{"method":"GET","path":"/favicon.ico","param":{},"body":{}},"resObject":{"statusCode":200}} 22 | 2023-09-05 11:02:25 INFO {"reqObject":{"method":"GET","path":"/user","param":{},"body":{}},"resObject":{"statusCode":200}} 23 | 2023-09-05 11:02:25 INFO {"reqObject":{"method":"GET","path":"/favicon.ico","param":{},"body":{}},"resObject":{"statusCode":200}} 24 | 2023-09-05 11:02:25 INFO {"reqObject":{"method":"GET","path":"/user","param":{},"body":{}},"resObject":{"statusCode":200}} 25 | 2023-09-05 11:02:25 INFO {"reqObject":{"method":"GET","path":"/favicon.ico","param":{},"body":{}},"resObject":{"statusCode":200}} 26 | 2023-09-05 11:02:27 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 27 | 2023-09-05 11:02:27 INFO {"reqObject":{"method":"GET","path":"/favicon.ico","param":{},"body":{}},"resObject":{"statusCode":200}} 28 | 2023-09-05 11:02:27 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 29 | 2023-09-05 11:02:27 INFO {"reqObject":{"method":"GET","path":"/favicon.ico","param":{},"body":{}},"resObject":{"statusCode":200}} 30 | 2023-09-05 11:27:33 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 31 | 2023-09-05 11:27:33 INFO {"reqObject":{"method":"GET","path":"/favicon.ico","param":{},"body":{}},"resObject":{"statusCode":200}} 32 | 2023-09-05 14:10:27 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 33 | 2023-09-05 14:10:27 INFO {"reqObject":{"method":"GET","path":"/favicon.ico","param":{},"body":{}},"resObject":{"statusCode":200}} 34 | 2023-09-05 16:55:27 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 35 | 2023-09-05 16:55:27 INFO {"reqObject":{"method":"GET","path":"/favicon.ico","param":{},"body":{}},"resObject":{"statusCode":200}} 36 | 2023-09-05 17:01:40 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 37 | 2023-09-05 17:01:40 INFO {"reqObject":{"method":"GET","path":"/favicon.ico","param":{},"body":{}},"resObject":{"statusCode":200}} 38 | 2023-09-05 17:01:56 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 39 | 2023-09-05 17:01:56 INFO {"reqObject":{"method":"GET","path":"/favicon.ico","param":{},"body":{}},"resObject":{"statusCode":200}} 40 | 2023-09-05 17:02:11 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 41 | 2023-09-05 17:02:11 INFO {"reqObject":{"method":"GET","path":"/favicon.ico","param":{},"body":{}},"resObject":{"statusCode":200}} 42 | 2023-09-05 17:02:26 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 43 | 2023-09-05 17:04:09 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 44 | 2023-09-05 17:04:20 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 45 | 2023-09-05 17:05:21 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 46 | 2023-09-05 17:06:14 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 47 | 2023-09-05 17:06:26 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 48 | 2023-09-05 17:06:27 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 49 | 2023-09-05 17:06:27 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 50 | 2023-09-05 17:06:27 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 51 | 2023-09-05 17:06:27 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 52 | 2023-09-05 17:06:27 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 53 | 2023-09-05 17:07:49 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 54 | 2023-09-05 17:08:48 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 55 | 2023-09-05 17:08:50 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 56 | 2023-09-05 17:08:50 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 57 | 2023-09-05 17:09:09 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 58 | 2023-09-05 17:13:40 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 59 | 2023-09-05 17:13:40 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 60 | 2023-09-05 17:13:41 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 61 | 2023-09-05 17:14:48 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 62 | 2023-09-05 17:14:49 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 63 | 2023-09-05 17:14:49 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 64 | 2023-09-05 17:17:48 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 65 | 2023-09-05 17:17:49 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 66 | 2023-09-05 17:17:49 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 67 | 2023-09-05 17:17:49 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 68 | 2023-09-05 17:17:49 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 69 | 2023-09-05 17:18:32 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 70 | 2023-09-05 17:19:06 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 71 | 2023-09-05 17:21:47 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 72 | 2023-09-05 17:21:48 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 73 | 2023-09-05 17:21:48 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 74 | 2023-09-05 17:21:48 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 75 | 2023-09-05 17:21:48 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 76 | 2023-09-05 17:22:19 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 77 | 2023-09-05 17:22:19 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 78 | 2023-09-05 17:22:19 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 79 | 2023-09-05 17:22:19 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 80 | 2023-09-05 17:22:19 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 81 | 2023-09-05 17:22:19 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 82 | 2023-09-05 17:22:20 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 83 | 2023-09-05 17:22:20 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 84 | 2023-09-05 17:22:28 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 85 | 2023-09-05 17:22:28 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 86 | 2023-09-05 17:22:28 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 87 | 2023-09-05 17:22:28 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 88 | 2023-09-05 17:25:07 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 89 | 2023-09-05 17:25:07 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 90 | 2023-09-05 17:27:52 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 91 | 2023-09-05 17:27:53 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 92 | 2023-09-05 17:27:53 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 93 | 2023-09-05 17:27:53 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 94 | 2023-09-05 17:27:53 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 95 | 2023-09-05 17:27:53 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 96 | 2023-09-05 17:38:54 INFO {"reqObject":{"method":"POST","path":"/","param":{},"body":{"ky":"value"}},"resObject":{"statusCode":200}} 97 | 2023-09-05 17:39:29 INFO {"reqObject":{"method":"POST","path":"/","param":{},"body":{"ky":"value"}},"resObject":{"statusCode":200}} 98 | 2023-09-05 17:40:52 INFO {"reqObject":{"method":"POST","path":"/","param":{},"body":{"key":"value"}},"resObject":{"statusCode":200}} 99 | -------------------------------------------------------------------------------- /log/access/9-6-2023.log: -------------------------------------------------------------------------------- 1 | 2023-09-06 11:25:04 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 2 | 2023-09-06 11:25:04 INFO {"reqObject":{"method":"GET","path":"/favicon.ico","param":{},"body":{}},"resObject":{"statusCode":200}} 3 | 2023-09-06 11:25:06 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 4 | 2023-09-06 11:25:06 INFO {"reqObject":{"method":"GET","path":"/favicon.ico","param":{},"body":{}},"resObject":{"statusCode":200}} 5 | 2023-09-06 11:51:28 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 6 | 2023-09-06 11:51:29 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 7 | 2023-09-06 11:51:29 INFO {"reqObject":{"method":"GET","path":"/favicon.ico","param":{},"body":{}},"resObject":{"statusCode":200}} 8 | 2023-09-06 11:51:30 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 9 | 2023-09-06 11:51:30 INFO {"reqObject":{"method":"GET","path":"/favicon.ico","param":{},"body":{}},"resObject":{"statusCode":200}} 10 | 2023-09-06 11:51:30 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 11 | 2023-09-06 11:51:30 INFO {"reqObject":{"method":"GET","path":"/favicon.ico","param":{},"body":{}},"resObject":{"statusCode":200}} 12 | 2023-09-06 11:51:30 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 13 | 2023-09-06 11:51:30 INFO {"reqObject":{"method":"GET","path":"/favicon.ico","param":{},"body":{}},"resObject":{"statusCode":200}} 14 | 2023-09-06 11:51:30 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 15 | 2023-09-06 11:51:30 INFO {"reqObject":{"method":"GET","path":"/favicon.ico","param":{},"body":{}},"resObject":{"statusCode":200}} 16 | 2023-09-06 11:52:59 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 17 | 2023-09-06 11:52:59 INFO {"reqObject":{"method":"GET","path":"/favicon.ico","param":{},"body":{}},"resObject":{"statusCode":200}} 18 | 2023-09-06 12:11:22 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 19 | 2023-09-06 12:11:22 INFO {"reqObject":{"method":"POST","path":"/","param":{},"body":{"key":"value"}},"resObject":{"statusCode":200}} 20 | 2023-09-06 12:11:22 INFO {"reqObject":{"method":"POST","path":"/","param":{},"body":{"ky":"value"}},"resObject":{"statusCode":200}} 21 | 2023-09-06 12:12:12 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 22 | 2023-09-06 12:12:12 INFO {"reqObject":{"method":"POST","path":"/","param":{},"body":{"ky":"value"}},"resObject":{"statusCode":200}} 23 | 2023-09-06 12:12:12 INFO {"reqObject":{"method":"POST","path":"/","param":{},"body":{"key":"value"}},"resObject":{"statusCode":200}} 24 | 2023-09-06 12:13:23 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 25 | 2023-09-06 12:13:23 INFO {"reqObject":{"method":"POST","path":"/","param":{},"body":{"ky":"value"}},"resObject":{"statusCode":200}} 26 | 2023-09-06 12:13:23 INFO {"reqObject":{"method":"POST","path":"/","param":{},"body":{"key":"value"}},"resObject":{"statusCode":200}} 27 | 2023-09-06 12:14:34 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 28 | 2023-09-06 12:14:34 INFO {"reqObject":{"method":"POST","path":"/","param":{},"body":{"ky":"value"}},"resObject":{"statusCode":200}} 29 | 2023-09-06 12:14:34 INFO {"reqObject":{"method":"POST","path":"/","param":{},"body":{"key":"value"}},"resObject":{"statusCode":200}} 30 | 2023-09-06 12:14:58 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 31 | 2023-09-06 12:14:58 INFO {"reqObject":{"method":"POST","path":"/","param":{},"body":{"key":"value"}},"resObject":{"statusCode":200}} 32 | 2023-09-06 12:14:58 INFO {"reqObject":{"method":"POST","path":"/","param":{},"body":{"ky":"value"}},"resObject":{"statusCode":200}} 33 | 2023-09-06 12:15:30 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 34 | 2023-09-06 12:15:30 INFO {"reqObject":{"method":"POST","path":"/","param":{},"body":{"ky":"value"}},"resObject":{"statusCode":200}} 35 | 2023-09-06 12:15:30 INFO {"reqObject":{"method":"POST","path":"/","param":{},"body":{"key":"value"}},"resObject":{"statusCode":200}} 36 | 2023-09-06 12:17:09 INFO {"reqObject":{"method":"POST","path":"/","param":{},"body":{"key":"value"}},"resObject":{"statusCode":200}} 37 | 2023-09-06 12:17:09 INFO {"reqObject":{"method":"POST","path":"/","param":{},"body":{"ky":"value"}},"resObject":{"statusCode":200}} 38 | 2023-09-06 12:17:09 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 39 | 2023-09-06 12:19:20 INFO {"reqObject":{"method":"POST","path":"/","param":{},"body":{"key":"value"}},"resObject":{"statusCode":200}} 40 | 2023-09-06 12:19:20 INFO {"reqObject":{"method":"POST","path":"/","param":{},"body":{"ky":"value"}},"resObject":{"statusCode":200}} 41 | 2023-09-06 12:19:20 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 42 | 2023-09-06 12:21:05 INFO {"reqObject":{"method":"POST","path":"/","param":{},"body":{"key":"value"}},"resObject":{"statusCode":200}} 43 | 2023-09-06 12:21:05 INFO {"reqObject":{"method":"POST","path":"/","param":{},"body":{"ky":"value"}},"resObject":{"statusCode":200}} 44 | 2023-09-06 12:21:05 INFO {"reqObject":{"method":"GET","path":"/","param":{},"body":{}},"resObject":{"statusCode":200}} 45 | -------------------------------------------------------------------------------- /log/error/1-10-2024.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3rd-planet/framework-x/b181063241a7f0a4799b5f9f7114279f30a23ba1/log/error/1-10-2024.log -------------------------------------------------------------------------------- /log/error/8-1-2023.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3rd-planet/framework-x/b181063241a7f0a4799b5f9f7114279f30a23ba1/log/error/8-1-2023.log -------------------------------------------------------------------------------- /log/error/8-2-2023.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3rd-planet/framework-x/b181063241a7f0a4799b5f9f7114279f30a23ba1/log/error/8-2-2023.log -------------------------------------------------------------------------------- /log/error/9-5-2023.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3rd-planet/framework-x/b181063241a7f0a4799b5f9f7114279f30a23ba1/log/error/9-5-2023.log -------------------------------------------------------------------------------- /log/error/9-6-2023.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3rd-planet/framework-x/b181063241a7f0a4799b5f9f7114279f30a23ba1/log/error/9-6-2023.log -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@3rdplanet/framework-x", 3 | "version": "4.5.1", 4 | "description": "Your Accelerated Path to API Creation", 5 | "main": "app/server.js", 6 | "scripts": { 7 | "start": "nodemon", 8 | "test": "jest", 9 | "prepare": "husky install", 10 | "lint": "prettier --write ." 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "https://github.com/3rd-planet/framework-x.git" 15 | }, 16 | "homepage": "https://www.frameworkx.info/", 17 | "author": "msamgan", 18 | "license": "ISC", 19 | "dependencies": { 20 | "@3rdplanet/x-core": "/Users/msamgan/Projects/boilerplate/x-core", 21 | "chalk": "^4.1.2", 22 | "commander": "^9.5.0", 23 | "cors": "^2.8.5", 24 | "dotenv": "^8.6.0", 25 | "express": "^4.18.2", 26 | "express-async-errors": "^3.1.1", 27 | "express-validator": "^6.15.0", 28 | "figlet": "^1.6.0", 29 | "inquirer": "^8.2.6", 30 | "loading-cli": "^1.1.0", 31 | "simple-node-logger": "^21.8.12" 32 | }, 33 | "devDependencies": { 34 | "husky": "^7.0.4", 35 | "jest": "^27.5.1", 36 | "nodemon": "^2.0.22", 37 | "prettier": "^3.0.3", 38 | "supertest": "^6.3.3" 39 | }, 40 | "keywords": [ 41 | "api", 42 | "expressjs", 43 | "nodejs", 44 | "backend", 45 | "server", 46 | "node server" 47 | ], 48 | "bin": { 49 | "@3rdplanet/framework-x": "bin/installer.js" 50 | }, 51 | "prettier": { 52 | "trailingComma": "none", 53 | "tabWidth": 4, 54 | "semi": false, 55 | "singleQuote": false, 56 | "printWidth": 112 57 | } 58 | } -------------------------------------------------------------------------------- /x: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const { Command } = require("commander") 4 | const program = new Command() 5 | require("@3rdplanet/x-core").init(program) 6 | 7 | program.parse(process.argv) 8 | --------------------------------------------------------------------------------