diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..1700fb7 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,37 @@ +# .editorconfig + +# top-most EditorConfig file +root = true + +# Unix-style newlines with a newline ending every file +[*] +end_of_line = lf +insert_final_newline = false + +# Matches multiple files with brace expansion notation +# Set default charset +[*.{js,ts,css,html}] +charset = utf-8 + +# Space indentation +[*.{js,ts,css,html,json}] +indent_style = space +indent_size = 4 + +# Matches the exact files either package.json or .travis.yml +[{package.json,.travis.yml}] +indent_style = space + +# Indentation override for all JS under lib directory +[*.js] +indent_style = space +indent_size = 4 + +# Matches the exact file .editorconfig +[.editorconfig] +indent_style = space +indent_size = 4 + +# Markdown files often use trailing whitespace to indicate line breaks +[*.md] +trim_trailing_whitespace = false \ No newline at end of file diff --git a/.gitignore b/.gitignore index cd45e76..64518ba 100644 --- a/.gitignore +++ b/.gitignore @@ -1,136 +1,200 @@ -# .gitignore for a Python-based script project +# Created by https://www.gitignore.io/api/git,node,macos,windows,visualstudiocode +# Edit at https://www.gitignore.io/?templates=git,node,macos,windows,visualstudiocode + +### Git ### +# Created by git for backups. To disable backups in Git: +# $ git config --global mergetool.keepBackup false +*.orig + +# Created by git when using merge tools for conflicts +*.BACKUP.* +*.BASE.* +*.LOCAL.* +*.REMOTE.* +*_BACKUP_*.txt +*_BASE_*.txt +*_LOCAL_*.txt +*_REMOTE_*.txt + +### macOS ### +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +### Node ### +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* -# Byte-compiled / optimized / DLL files -__pycache__/ -*.py[cod] -*$py.class +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json -# C extensions -*.so +# Runtime data +pids +*.pid +*.seed +*.pid.lock -# Distribution / packaging -.Python -build/ -develop-eggs/ -dist/ -downloads/ -eggs/ -.eggs/ -lib/ -lib64/ -parts/ -sdist/ -var/ -wheels/ -pip-wheel-metadata/ -share/python-wheels/ -*.egg-info/ -.installed.cfg -*.egg -MANIFEST - -# PyInstaller -# Usually these files are written by a python script from a template -# before PyInstaller builds the exe, so as to inject date/other infos into it. -*.manifest -*.spec - -# Installer logs -pip-log.txt -pip-delete-this-directory.txt - -# Unit test / coverage reports -htmlcov/ -.tox/ -.nox/ -.coverage -.coverage.* +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# TypeScript v1 declaration files +typings/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +#.env +#.env.test + +# parcel-bundler cache (https://parceljs.org/) .cache -nosetests.xml -coverage.xml -*.cover -.hypothesis/ -.pytest_cache/ -# Translations -*.mo -*.pot +# next.js build output +.next -# Django stuff: -*.log -local_settings.py -db.sqlite3 -db.sqlite3-journal +# nuxt.js build output +.nuxt + +# rollup.js default build output +dist/ -# Flask stuff: -instance/ -.webassets-cache +# Uncomment the public line if your project uses Gatsby +# https://nextjs.org/blog/next-9-1#public-directory-support +# https://create-react-app.dev/docs/using-the-public-folder/#docsNav +# public -# Scrapy stuff: -.scrapy +# Storybook build outputs +.out +.storybook-out -# Sphinx documentation -docs/_build/ +# vuepress build output +.vuepress/dist -# PyBuilder -target/ +# Serverless directories +.serverless/ -# Jupyter Notebook -.ipynb_checkpoints +# FuseBox cache +.fusebox/ -# IPython -profile_default/ -ipython_config.py +# DynamoDB Local files +.dynamodb/ -# pyenv -.python-version +# Temporary folders +tmp/ +temp/ -# pipenv -# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. -# However, in case of collaboration, if having platform-specific dependencies or dependencies -# having no cross-platform support, pipenv may install dependencies that don't work, or not -# install all needed dependencies. -#Pipfile.lock +### VisualStudioCode ### +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json -# PEP 582; used by e.g. github.com/David-OConnor/pyflow -__pypackages__/ +### VisualStudioCode Patch ### +# Ignore all local history of files +.history -# Celery stuff -celerybeat-schedule -celerybeat.pid +### Windows ### +# Windows thumbnail cache files +Thumbs.db +Thumbs.db:encryptable +ehthumbs.db +ehthumbs_vista.db -# SageMath parsed files -*.sage.py +# Dump file +*.stackdump -# Environments -.env -.venv -env/ -venv/ -ENV/ -env.bak/ -venv.bak/ +# Folder config file +[Dd]esktop.ini -# Spyder project settings -.spyderproject -.spyproject +# Recycle Bin used on file shares +$RECYCLE.BIN/ -# Rope project settings -.ropeproject +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp -# mkdocs documentation -/site +# Windows shortcuts +*.lnk -# mypy -.mypy_cache/ -.dmypy.json -dmypy.json +# Enviorment variables +.env.* -# Pyre type checker -.pyre/ +# Test data +*.csv +test-data.json -# pytype static type analyzer -.pytype/ +# SSL certificates +ssl -# Cython debug symbols -cython_debug/ \ No newline at end of file +# End of https://www.gitignore.io/api/git,node,macos,windows,visualstudiocode \ No newline at end of file diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..a01256e --- /dev/null +++ b/.prettierrc @@ -0,0 +1,11 @@ +{ + "semi": true, + "trailingComma": "all", + "singleQuote": true, + "printWidth": 80, + "tabWidth": 4, + "useTabs": false, + "bracketSpacing": true, + "arrowParens": "avoid", + "endOfLine": "lf" +} diff --git a/.vscode/extensions.json b/.vscode/extensions.json index c19f93d..a25827d 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,10 +1,8 @@ { - "recommendations": [ - "ms-python.autopep8", - "ms-python.vscode-pylance", - "ms-python.pylint", - "ms-python.python", - "ms-vscode.powershell", - "timonwong.shellcheck" - ] + "recommendations": [ + "biomejs.biome", + "esbenp.prettier-vscode", + "editorconfig.editorconfig", + "dbaeumer.vscode-eslint" + ] } diff --git a/README.md b/README.md index 8a2cd66..e69de29 100644 --- a/README.md +++ b/README.md @@ -1,107 +0,0 @@ -# Introduction - -

- Express-Nitro Logo -

- -This repo holds a **NOS** tank for your **`express.js`** project which will increase your speed of setting up an **express** project. - -The **NOS** mentioned above is basically a set of python scripts and they will create an **`express.js`** project based on this [template](https://github.com/Shivansh-Khunger/template-express-nitro). - -This template includes the following key components: - -- **[Express.js](https://www.npmjs.com/package/express)**: A fast and flexible Node.js web application framework. - -- **[Pino](https://www.npmjs.com/package/pino)**: A low-overhead, high-speed Node.js logger. It also has sister packages, [pino-pretty](https://www.npmjs.com/package/pino-pretty) for pretty-printing logs, and [pino-http](https://www.npmjs.com/package/pino-http) for HTTP logging. - -- **[TypeScript](https://www.npmjs.com/package/typescript)**: A strongly typed superset of JavaScript. - -- **[Dotenvx](https://github.com/dotenvx/dotenvx)**: An enhanced version of `dotenv` that supports multiple `.env` files and runtime variable replacement. It provides a flexible way to manage environment variables. - -- **[tsx](https://www.npmjs.com/package/tsx)**: A tool that restarts your TypeScript application when source files change. - -This Project follows the saying follows the saying - - -
- ‘If you can't buy something you want, build it.’ -
- -# Usage - -If you want an Express project set up for you in a matter of seconds, copy and paste the following command into your terminal: - -```bash -curl -sL https://raw.githubusercontent.com/Shivansh-Khunger/express-nitro/main/with_args.py | python - --dir 'name of the directory' -``` - -
- Tip for Windows users: If you're using a Windows system and the curl command isn't working, try using curl.exe instead. Read why is that? -
- -So the command for Windows users would be: - -```powershell -curl.exe -sL https://raw.githubusercontent.com/Shivansh-Khunger/express-nitro/main/with_args.py | python - --dir 'name of the directory' -``` - -### Options - -- `--biome`: Use biome.js as linter & formatter. If you haven't heard of it, visit [biomejs.dev](https://biomejs.dev/). This is set to **false** by default. -- `--git`: Initialize a git repo in the new project. This is set to **true** by default. -- `--dir`: Specify a name for the new project directory. The default is 'template-express-nitro'. -- `--alias`: Add alias **'mkexp'** to run this script from any location in your command line interface. This is set to **true** by default. -- `--shell`: Specify the shell (bash [Default], zsh, ksh [Korn], csh [C-Shell], or fish). - - - Only needed if multiple shell configuration files are present. - - If no shell is specified, the script will use the bash configuration file by default. - - However, if other shell configuration files are found, it will follow the order: - 1. [zsh (oh my zsh)](https://ohmyz.sh/) - 2. [ksh (Korn-Shell)](http://kornshell.com/) - 3. [csh (C-Shell)](https://codedocs.org/what-is/c-shell) - 4. [fish (Fish-Shell)](https://fishshell.com/) - - For example, if configuration files for both 'zsh' and 'ksh' are found, 'zsh' will be preferred. - - ### Accepted Inputs for `--shell` Argument - - The `--shell` argument accepts the following inputs: - - - Bash: You can specify this shell using any of the following inputs: `BASH`, `Bash`, `bash`. - - Zsh: You can specify this shell using any of the following inputs: `ZSH`, `Zsh`, `zsh`. - - Ksh (Korn-Shell): You can specify this shell using any of the following inputs: `KSH`, `KORN`, `Korn`, `korn`, `ksh`. - - Csh (C-Shell): You can specify this shell using any of the following inputs: `CSH`, `C`, `c`, `csh`. - - Fish: You can specify this shell using any of the following inputs: `FSH`, `FISH`, `Fish`, `fish`, `fsh`. - - Please note that the input is case-insensitive. - -Here's an example of how to use these options: - -```bash -curl -sL https://raw.githubusercontent.com/Shivansh-Khunger/express-nitro/main/with_args.py | python - --dir 'my_project' --biome --git --shell 'zsh' -``` - -
- Note: The command above will initialize biome as linter & formatter, but it will not initialize a git repository. This command will add the alias to the default config of oh-my-zsh. -
- -# Additional Usage - -After the initial use of this script, you can simply type `mkexp` in your command line interface to invoke a sister script. This script will interactively take input from you to set up your project. This makes it even easier to quickly set up new Express projects based on the template. - -
- Note for Unix-based system users: The mkexp alias will only work if you invoke Python by typing python and not python3. Please ensure you have the correct Python alias set up in your system. - -
- Another workaround is you can just edit the alias set up by the script from python to python3. -
- -# Contributing - -

- Note: A detailed contribution guide will be added soon. Until then, if you want to make changes to this repository, please use your skills and common sense. - -
- -

- TIP: Feel free to raise an issue or submit a pull request. -
-
diff --git a/biome.json b/biome.json new file mode 100644 index 0000000..8550827 --- /dev/null +++ b/biome.json @@ -0,0 +1,26 @@ +{ + "$schema": "https://biomejs.dev/schemas/1.6.0/schema.json", + "organizeImports": { + "enabled": true + }, + "linter": { + "enabled": true, + "rules": { + "recommended": true + } + }, + "vcs": { + "enabled": true, + "clientKind": "git", + "useIgnoreFile": true + }, + "formatter": { + "enabled": true, + "formatWithErrors": false, + "indentStyle": "space", + "indentWidth": 4, + "lineWidth": 80, + "lineEnding": "lf", + "ignore": [] + } +} diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/deprecated/.github/ISSUE_TEMPLATE/bug_report.md similarity index 100% rename from .github/ISSUE_TEMPLATE/bug_report.md rename to deprecated/.github/ISSUE_TEMPLATE/bug_report.md diff --git a/.github/ISSUE_TEMPLATE/enhancement_request.md b/deprecated/.github/ISSUE_TEMPLATE/enhancement_request.md similarity index 100% rename from .github/ISSUE_TEMPLATE/enhancement_request.md rename to deprecated/.github/ISSUE_TEMPLATE/enhancement_request.md diff --git a/.github/ISSUE_TEMPLATE/inconsistency_report.md b/deprecated/.github/ISSUE_TEMPLATE/inconsistency_report.md similarity index 100% rename from .github/ISSUE_TEMPLATE/inconsistency_report.md rename to deprecated/.github/ISSUE_TEMPLATE/inconsistency_report.md diff --git a/.github/pull_request_template.md b/deprecated/.github/pull_request_template.md similarity index 100% rename from .github/pull_request_template.md rename to deprecated/.github/pull_request_template.md diff --git a/deprecated/.gitignore b/deprecated/.gitignore new file mode 100644 index 0000000..cd45e76 --- /dev/null +++ b/deprecated/.gitignore @@ -0,0 +1,136 @@ +# .gitignore for a Python-based script project + +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +pip-wheel-metadata/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +.hypothesis/ +.pytest_cache/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +.python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ \ No newline at end of file diff --git a/.pylintrc b/deprecated/.pylintrc similarity index 100% rename from .pylintrc rename to deprecated/.pylintrc diff --git a/deprecated/.vscode/extensions.json b/deprecated/.vscode/extensions.json new file mode 100644 index 0000000..c19f93d --- /dev/null +++ b/deprecated/.vscode/extensions.json @@ -0,0 +1,10 @@ +{ + "recommendations": [ + "ms-python.autopep8", + "ms-python.vscode-pylance", + "ms-python.pylint", + "ms-python.python", + "ms-vscode.powershell", + "timonwong.shellcheck" + ] +} diff --git a/.vscode/settings.json b/deprecated/.vscode/settings.json similarity index 100% rename from .vscode/settings.json rename to deprecated/.vscode/settings.json diff --git a/LICENCE b/deprecated/LICENCE similarity index 100% rename from LICENCE rename to deprecated/LICENCE diff --git a/deprecated/README.md b/deprecated/README.md new file mode 100644 index 0000000..8a2cd66 --- /dev/null +++ b/deprecated/README.md @@ -0,0 +1,107 @@ +# Introduction + +

+ Express-Nitro Logo +

+ +This repo holds a **NOS** tank for your **`express.js`** project which will increase your speed of setting up an **express** project. + +The **NOS** mentioned above is basically a set of python scripts and they will create an **`express.js`** project based on this [template](https://github.com/Shivansh-Khunger/template-express-nitro). + +This template includes the following key components: + +- **[Express.js](https://www.npmjs.com/package/express)**: A fast and flexible Node.js web application framework. + +- **[Pino](https://www.npmjs.com/package/pino)**: A low-overhead, high-speed Node.js logger. It also has sister packages, [pino-pretty](https://www.npmjs.com/package/pino-pretty) for pretty-printing logs, and [pino-http](https://www.npmjs.com/package/pino-http) for HTTP logging. + +- **[TypeScript](https://www.npmjs.com/package/typescript)**: A strongly typed superset of JavaScript. + +- **[Dotenvx](https://github.com/dotenvx/dotenvx)**: An enhanced version of `dotenv` that supports multiple `.env` files and runtime variable replacement. It provides a flexible way to manage environment variables. + +- **[tsx](https://www.npmjs.com/package/tsx)**: A tool that restarts your TypeScript application when source files change. + +This Project follows the saying follows the saying - + +
+ ‘If you can't buy something you want, build it.’ +
+ +# Usage + +If you want an Express project set up for you in a matter of seconds, copy and paste the following command into your terminal: + +```bash +curl -sL https://raw.githubusercontent.com/Shivansh-Khunger/express-nitro/main/with_args.py | python - --dir 'name of the directory' +``` + +
+ Tip for Windows users: If you're using a Windows system and the curl command isn't working, try using curl.exe instead. Read why is that? +
+ +So the command for Windows users would be: + +```powershell +curl.exe -sL https://raw.githubusercontent.com/Shivansh-Khunger/express-nitro/main/with_args.py | python - --dir 'name of the directory' +``` + +### Options + +- `--biome`: Use biome.js as linter & formatter. If you haven't heard of it, visit [biomejs.dev](https://biomejs.dev/). This is set to **false** by default. +- `--git`: Initialize a git repo in the new project. This is set to **true** by default. +- `--dir`: Specify a name for the new project directory. The default is 'template-express-nitro'. +- `--alias`: Add alias **'mkexp'** to run this script from any location in your command line interface. This is set to **true** by default. +- `--shell`: Specify the shell (bash [Default], zsh, ksh [Korn], csh [C-Shell], or fish). + + - Only needed if multiple shell configuration files are present. + - If no shell is specified, the script will use the bash configuration file by default. + - However, if other shell configuration files are found, it will follow the order: + 1. [zsh (oh my zsh)](https://ohmyz.sh/) + 2. [ksh (Korn-Shell)](http://kornshell.com/) + 3. [csh (C-Shell)](https://codedocs.org/what-is/c-shell) + 4. [fish (Fish-Shell)](https://fishshell.com/) + - For example, if configuration files for both 'zsh' and 'ksh' are found, 'zsh' will be preferred. + + ### Accepted Inputs for `--shell` Argument + + The `--shell` argument accepts the following inputs: + + - Bash: You can specify this shell using any of the following inputs: `BASH`, `Bash`, `bash`. + - Zsh: You can specify this shell using any of the following inputs: `ZSH`, `Zsh`, `zsh`. + - Ksh (Korn-Shell): You can specify this shell using any of the following inputs: `KSH`, `KORN`, `Korn`, `korn`, `ksh`. + - Csh (C-Shell): You can specify this shell using any of the following inputs: `CSH`, `C`, `c`, `csh`. + - Fish: You can specify this shell using any of the following inputs: `FSH`, `FISH`, `Fish`, `fish`, `fsh`. + + Please note that the input is case-insensitive. + +Here's an example of how to use these options: + +```bash +curl -sL https://raw.githubusercontent.com/Shivansh-Khunger/express-nitro/main/with_args.py | python - --dir 'my_project' --biome --git --shell 'zsh' +``` + +
+ Note: The command above will initialize biome as linter & formatter, but it will not initialize a git repository. This command will add the alias to the default config of oh-my-zsh. +
+ +# Additional Usage + +After the initial use of this script, you can simply type `mkexp` in your command line interface to invoke a sister script. This script will interactively take input from you to set up your project. This makes it even easier to quickly set up new Express projects based on the template. + +
+ Note for Unix-based system users: The mkexp alias will only work if you invoke Python by typing python and not python3. Please ensure you have the correct Python alias set up in your system. + +
+ Another workaround is you can just edit the alias set up by the script from python to python3. +
+ +# Contributing + +

+ Note: A detailed contribution guide will be added soon. Until then, if you want to make changes to this repository, please use your skills and common sense. + +
+ +

+ TIP: Feel free to raise an issue or submit a pull request. +
+
diff --git a/pyproject.toml b/deprecated/pyproject.toml similarity index 100% rename from pyproject.toml rename to deprecated/pyproject.toml diff --git a/setup.cfg b/deprecated/setup.cfg similarity index 100% rename from setup.cfg rename to deprecated/setup.cfg diff --git a/unix_update_profile.sh b/deprecated/unix_update_profile.sh similarity index 100% rename from unix_update_profile.sh rename to deprecated/unix_update_profile.sh diff --git a/win_update_profile.ps1 b/deprecated/win_update_profile.ps1 similarity index 100% rename from win_update_profile.ps1 rename to deprecated/win_update_profile.ps1 diff --git a/with_args.py b/deprecated/with_args.py similarity index 100% rename from with_args.py rename to deprecated/with_args.py diff --git a/without_args.py b/deprecated/without_args.py similarity index 100% rename from without_args.py rename to deprecated/without_args.py diff --git a/index.js b/index.js new file mode 100644 index 0000000..ad84ca5 --- /dev/null +++ b/index.js @@ -0,0 +1,3 @@ +#!/usr/bin/env node + +import './dist/index.js'; diff --git a/options/biome-prettier/biome.json b/options/biome-prettier/biome.json new file mode 100644 index 0000000..8550827 --- /dev/null +++ b/options/biome-prettier/biome.json @@ -0,0 +1,26 @@ +{ + "$schema": "https://biomejs.dev/schemas/1.6.0/schema.json", + "organizeImports": { + "enabled": true + }, + "linter": { + "enabled": true, + "rules": { + "recommended": true + } + }, + "vcs": { + "enabled": true, + "clientKind": "git", + "useIgnoreFile": true + }, + "formatter": { + "enabled": true, + "formatWithErrors": false, + "indentStyle": "space", + "indentWidth": 4, + "lineWidth": 80, + "lineEnding": "lf", + "ignore": [] + } +} diff --git a/options/biome-prettier/extensions.json b/options/biome-prettier/extensions.json new file mode 100644 index 0000000..5f44864 --- /dev/null +++ b/options/biome-prettier/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["biomejs.biome"] +} diff --git a/options/eslint-prettier/eslint.config.js b/options/eslint-prettier/eslint.config.js new file mode 100644 index 0000000..204f9ee --- /dev/null +++ b/options/eslint-prettier/eslint.config.js @@ -0,0 +1,30 @@ +import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended'; + +module.exports = [ + eslintPluginPrettierRecommended, + { + env: { + browser: true, + es2021: true, + }, + extends: 'eslint:recommended', + parserOptions: { + ecmaVersion: 12, + sourceType: 'module', + }, + rules: {}, + ignorePatterns: [], + overrides: [ + { + files: ['**/*.ts', '**/*.tsx'], + parser: '@typescript-eslint/parser', + extends: [ + 'eslint:recommended', + 'plugin:@typescript-eslint/recommended', + 'plugin:prettier/recommended', + ], + rules: {}, + }, + ], + }, +]; diff --git a/options/eslint-prettier/extensions.json b/options/eslint-prettier/extensions.json new file mode 100644 index 0000000..8ccf0e7 --- /dev/null +++ b/options/eslint-prettier/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["dbaeumer.vscode-eslint"] +} diff --git a/options/mongoose/js/db.js b/options/mongoose/js/db.js new file mode 100644 index 0000000..e4b1db1 --- /dev/null +++ b/options/mongoose/js/db.js @@ -0,0 +1,22 @@ +import { logger } from '../logger.js'; + +import mongoose from 'mongoose'; + +async function connectToDb() { + await mongoose + .connect(process.env.MONGO_URI) + .then(() => { + logger.info('db connected !'); + }) + .catch(err => { + logger.error( + err, + '-> an error has occured while connecting to the db!', + ); + + logger.fatal('server is closing... :['); + process.exit(1); + }); +} + +export default connectToDb; diff --git a/options/mongoose/js/index.js b/options/mongoose/js/index.js new file mode 100644 index 0000000..7504490 --- /dev/null +++ b/options/mongoose/js/index.js @@ -0,0 +1,25 @@ +import connectToDb from './config/db.js'; +import setHeaders from './config/headers.js'; +import { httpLogger, logger } from './logger.js'; + +import express from 'express'; + +const PORT = process.env.PORT || 3001; +const app = express(); + +(async () => { + await connectToDb(); +})(); + +app.use(express.json()); +app.use(express.urlencoded({ extended: true })); +app.use(setHeaders); +app.use(httpLogger); + +app.get('/', (req, res) => { + res.send('Welcome to api set up by node-nitro ^_+'); +}); + +app.listen(PORT, () => { + logger.info(`-> now listening at http://localhost:${PORT}/`); +}); diff --git a/options/mongoose/ts/db.ts b/options/mongoose/ts/db.ts new file mode 100644 index 0000000..ae2d386 --- /dev/null +++ b/options/mongoose/ts/db.ts @@ -0,0 +1,22 @@ +import { logger } from "@logger"; + +import mongoose from "mongoose"; + +async function connectToDb() { + await mongoose + .connect(process.env.MONGO_URI as string) + .then(() => { + logger.info("db connected !"); + }) + .catch((err) => { + logger.error( + err, + "-> an error has occured while connecting to the db!", + ); + + logger.fatal("server is closing... :["); + process.exit(1); + }); +} + +export default connectToDb; diff --git a/options/mongoose/ts/index.ts b/options/mongoose/ts/index.ts new file mode 100644 index 0000000..678cdd4 --- /dev/null +++ b/options/mongoose/ts/index.ts @@ -0,0 +1,27 @@ +import connectToDb from "./config/db"; +import setHeaders from "./config/headers"; +import { httpLogger, logger } from "./logger"; + +import express from "express"; + +const PORT = process.env.PORT || 3001; +const app = express(); + +app.use(express.json()); +app.use(express.urlencoded({ extended: true })); +app.use(setHeaders); +app.use(httpLogger); + +(async () => { + await connectToDb(); +})(); + +if (process.env.NODE_ENV === "development") { + app.get("/", (req, res) => { + res.send("Welcome to api set up by node-nitro ^_+"); + }); +} + +app.listen(PORT, () => { + logger.info(`-> now listening at http://localhost:${PORT}/`); +}); diff --git a/options/prisma/js/index.js b/options/prisma/js/index.js new file mode 100644 index 0000000..377ac4e --- /dev/null +++ b/options/prisma/js/index.js @@ -0,0 +1,36 @@ +import setHeaders from './config/headers.js'; +import { httpLogger, logger } from './logger.js'; + +import express from 'express'; +const prisma = new PrismaClient(); + +const PORT = process.env.PORT || 3001; +const app = express(); + +(async () => { + try { + await prisma.$connect(); + logger.info('db connected !'); + } catch (err) { + logger.error( + err, + '-> an error has occured while connecting to the db!', + ); + + logger.fatal('server is closing... :['); + process.exit(1); + } +})(); + +app.use(express.json()); +app.use(express.urlencoded({ extended: true })); +app.use(setHeaders); +app.use(httpLogger); + +app.get('/', (req, res) => { + res.send('Welcome to api set up by node-nitro ^_+'); +}); + +app.listen(PORT, () => { + logger.info(`-> now listening at http://localhost:${PORT}/`); +}); diff --git a/options/prisma/ts/index.ts b/options/prisma/ts/index.ts new file mode 100644 index 0000000..b106d5a --- /dev/null +++ b/options/prisma/ts/index.ts @@ -0,0 +1,40 @@ +import setHeaders from "./config/headers"; +import { httpLogger, logger } from "./logger"; + +import { PrismaClient } from "@prisma/client"; +import express from "express"; + +const PORT = process.env.PORT || 3001; +const app = express(); + +const prisma = new PrismaClient(); + +app.use(express.json()); +app.use(express.urlencoded({ extended: true })); +app.use(setHeaders); +app.use(httpLogger); + +(async () => { + try { + await prisma.$connect(); + logger.info("db connected !"); + } catch (err) { + logger.error( + err, + "-> an error has occured while connecting to the db!", + ); + + logger.fatal("server is closing... :["); + process.exit(1); + } +})(); + +if (process.env.NODE_ENV === "development") { + app.get("/", (req, res) => { + res.send("Welcome to api set up by node-nitro ^_+"); + }); +} + +app.listen(PORT, () => { + logger.info(`-> now listening at http://localhost:${PORT}/`); +}); diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..ff597ff --- /dev/null +++ b/package-lock.json @@ -0,0 +1,1007 @@ +{ + "name": "node-nitro", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "node-nitro", + "version": "0.1.0", + "dependencies": { + "commander": "^12.1.0", + "kolorist": "^1.8.0", + "prompts": "^2.4.2" + }, + "devDependencies": { + "@biomejs/biome": "^1.7.3", + "@types/prompts": "^2.4.9", + "ts-patch": "^3.1.2", + "tsx": "^4.7.1", + "typescript": "^5.4.3", + "typescript-transform-paths": "^3.4.7" + } + }, + "node_modules/@biomejs/biome": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-1.7.3.tgz", + "integrity": "sha512-ogFQI+fpXftr+tiahA6bIXwZ7CSikygASdqMtH07J2cUzrpjyTMVc9Y97v23c7/tL1xCZhM+W9k4hYIBm7Q6cQ==", + "dev": true, + "hasInstallScript": true, + "bin": { + "biome": "bin/biome" + }, + "engines": { + "node": ">=14.21.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/biome" + }, + "optionalDependencies": { + "@biomejs/cli-darwin-arm64": "1.7.3", + "@biomejs/cli-darwin-x64": "1.7.3", + "@biomejs/cli-linux-arm64": "1.7.3", + "@biomejs/cli-linux-arm64-musl": "1.7.3", + "@biomejs/cli-linux-x64": "1.7.3", + "@biomejs/cli-linux-x64-musl": "1.7.3", + "@biomejs/cli-win32-arm64": "1.7.3", + "@biomejs/cli-win32-x64": "1.7.3" + } + }, + "node_modules/@biomejs/cli-darwin-arm64": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-1.7.3.tgz", + "integrity": "sha512-eDvLQWmGRqrPIRY7AIrkPHkQ3visEItJKkPYSHCscSDdGvKzYjmBJwG1Gu8+QC5ed6R7eiU63LEC0APFBobmfQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-darwin-x64": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-1.7.3.tgz", + "integrity": "sha512-JXCaIseKRER7dIURsVlAJacnm8SG5I0RpxZ4ya3dudASYUc68WGl4+FEN03ABY3KMIq7hcK1tzsJiWlmXyosZg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-arm64": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-1.7.3.tgz", + "integrity": "sha512-phNTBpo7joDFastnmZsFjYcDYobLTx4qR4oPvc9tJ486Bd1SfEVPHEvJdNJrMwUQK56T+TRClOQd/8X1nnjA9w==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-arm64-musl": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.7.3.tgz", + "integrity": "sha512-c8AlO45PNFZ1BYcwaKzdt46kYbuP6xPGuGQ6h4j3XiEDpyseRRUy/h+6gxj07XovmyxKnSX9GSZ6nVbZvcVUAw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-x64": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-1.7.3.tgz", + "integrity": "sha512-vnedYcd5p4keT3iD48oSKjOIRPYcjSNNbd8MO1bKo9ajg3GwQXZLAH+0Cvlr+eMsO67/HddWmscSQwTFrC/uPA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-x64-musl": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-1.7.3.tgz", + "integrity": "sha512-UdEHKtYGWEX3eDmVWvQeT+z05T9/Sdt2+F/7zmMOFQ7boANeX8pcO6EkJPK3wxMudrApsNEKT26rzqK6sZRTRA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-win32-arm64": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-1.7.3.tgz", + "integrity": "sha512-unNCDqUKjujYkkSxs7gFIfdasttbDC4+z0kYmcqzRk6yWVoQBL4dNLcCbdnJS+qvVDNdI9rHp2NwpQ0WAdla4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-win32-x64": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-1.7.3.tgz", + "integrity": "sha512-ZmByhbrnmz/UUFYB622CECwhKIPjJLLPr5zr3edhu04LzbfcOrz16VYeNq5dpO1ADG70FORhAJkaIGdaVBG00w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz", + "integrity": "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.2.tgz", + "integrity": "sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz", + "integrity": "sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.2.tgz", + "integrity": "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz", + "integrity": "sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz", + "integrity": "sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz", + "integrity": "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz", + "integrity": "sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz", + "integrity": "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz", + "integrity": "sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz", + "integrity": "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz", + "integrity": "sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz", + "integrity": "sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz", + "integrity": "sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz", + "integrity": "sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz", + "integrity": "sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz", + "integrity": "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz", + "integrity": "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz", + "integrity": "sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz", + "integrity": "sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz", + "integrity": "sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz", + "integrity": "sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz", + "integrity": "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@types/node": { + "version": "20.12.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.12.tgz", + "integrity": "sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/prompts": { + "version": "2.4.9", + "resolved": "https://registry.npmjs.org/@types/prompts/-/prompts-2.4.9.tgz", + "integrity": "sha512-qTxFi6Buiu8+50/+3DGIWLHM6QuWsEKugJnnP6iv2Mc4ncxE4A/OJkjuVOA+5X0X1S/nq5VJRa8Lu+nwcvbrKA==", + "dev": true, + "dependencies": { + "@types/node": "*", + "kleur": "^3.0.3" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "engines": { + "node": ">=18" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/esbuild": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz", + "integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.20.2", + "@esbuild/android-arm": "0.20.2", + "@esbuild/android-arm64": "0.20.2", + "@esbuild/android-x64": "0.20.2", + "@esbuild/darwin-arm64": "0.20.2", + "@esbuild/darwin-x64": "0.20.2", + "@esbuild/freebsd-arm64": "0.20.2", + "@esbuild/freebsd-x64": "0.20.2", + "@esbuild/linux-arm": "0.20.2", + "@esbuild/linux-arm64": "0.20.2", + "@esbuild/linux-ia32": "0.20.2", + "@esbuild/linux-loong64": "0.20.2", + "@esbuild/linux-mips64el": "0.20.2", + "@esbuild/linux-ppc64": "0.20.2", + "@esbuild/linux-riscv64": "0.20.2", + "@esbuild/linux-s390x": "0.20.2", + "@esbuild/linux-x64": "0.20.2", + "@esbuild/netbsd-x64": "0.20.2", + "@esbuild/openbsd-x64": "0.20.2", + "@esbuild/sunos-x64": "0.20.2", + "@esbuild/win32-arm64": "0.20.2", + "@esbuild/win32-ia32": "0.20.2", + "@esbuild/win32-x64": "0.20.2" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-tsconfig": { + "version": "4.7.5", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.5.tgz", + "integrity": "sha512-ZCuZCnlqNzjb4QprAzXKdpp/gh6KTxSJuw3IBsPnV/7fV4NxC9ckB+vPTt8w7fJA0TaSD7c55BR47JD6MEDyDw==", + "dev": true, + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/global-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", + "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", + "dev": true, + "dependencies": { + "ini": "^1.3.5", + "kind-of": "^6.0.2", + "which": "^1.3.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, + "node_modules/is-core-module": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "dev": true, + "dependencies": { + "hasown": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "engines": { + "node": ">=6" + } + }, + "node_modules/kolorist": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/kolorist/-/kolorist-1.8.0.tgz", + "integrity": "sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==" + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==" + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ts-patch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/ts-patch/-/ts-patch-3.1.2.tgz", + "integrity": "sha512-n58F5AqjUMdp9RAKq+E1YBkmONltPVbt1nN+wrmZXoYZek6QcvaTuqvKMhYhr5BxtC53kD/exxIPA1cP1RQxsA==", + "dev": true, + "dependencies": { + "chalk": "^4.1.2", + "global-prefix": "^3.0.0", + "minimist": "^1.2.8", + "resolve": "^1.22.2", + "semver": "^7.5.4", + "strip-ansi": "^6.0.1" + }, + "bin": { + "ts-patch": "bin/ts-patch.js", + "tspc": "bin/tspc.js" + } + }, + "node_modules/tsx": { + "version": "4.10.5", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.10.5.tgz", + "integrity": "sha512-twDSbf7Gtea4I2copqovUiNTEDrT8XNFXsuHpfGbdpW/z9ZW4fTghzzhAG0WfrCuJmJiOEY1nLIjq4u3oujRWQ==", + "dev": true, + "dependencies": { + "esbuild": "~0.20.2", + "get-tsconfig": "^4.7.5" + }, + "bin": { + "tsx": "dist/cli.mjs" + }, + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + } + }, + "node_modules/typescript": { + "version": "5.4.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", + "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/typescript-transform-paths": { + "version": "3.4.7", + "resolved": "https://registry.npmjs.org/typescript-transform-paths/-/typescript-transform-paths-3.4.7.tgz", + "integrity": "sha512-1Us1kdkdfKd2unbkBAOV2HHRmbRBYpSuk9nJ7cLD2hP4QmfToiM/VpxNlhJc1eezVwVqSKSBjNSzZsK/fWR/9A==", + "dev": true, + "dependencies": { + "minimatch": "^3.0.4" + }, + "peerDependencies": { + "typescript": ">=3.6.5" + } + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, + "node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..214b91f --- /dev/null +++ b/package.json @@ -0,0 +1,28 @@ +{ + "name": "node-nitro", + "version": "0.1.0-beta.1", + "description": "", + "main": "index.js", + "scripts": { + "dev": "tspc --watch", + "test": "echo \"Error: no test specified\" && exit 1", + "start": "node ./index.js" + }, + "files": ["dist/**", "options/**", "templates/**"], + "publishConfig": { + "access": "public" + }, + "dependencies": { + "commander": "^12.1.0", + "kolorist": "^1.8.0", + "prompts": "^2.4.2" + }, + "devDependencies": { + "@biomejs/biome": "^1.7.3", + "@types/prompts": "^2.4.9", + "ts-patch": "^3.1.2", + "tsx": "^4.7.1", + "typescript": "^5.4.3", + "typescript-transform-paths": "^3.4.7" + } +} diff --git a/src/helpers/db&Orms.ts b/src/helpers/db&Orms.ts new file mode 100644 index 0000000..1a95d3c --- /dev/null +++ b/src/helpers/db&Orms.ts @@ -0,0 +1,119 @@ +import { exec } from "node:child_process"; +import fs from "node:fs"; + +import type { T_UserInput, T_UserInputCli } from "../types/prompt"; + +import { + appendFile, + copyFile, + deleteFile, + updateFile, +} from "@utils/fileSystem"; + +function ifWantTs(userInput: T_UserInput) { + switch (userInput.template) { + case "express/js": + return false; + case "express/ts": + return true; + default: + // TODO -> handle errors + throw new Error("Invalid template"); + } +} + +export async function updatePackageScript(targetPath: string) { + const targetPackagePath = `${targetPath}/package.json`; + + const appendScripts = [ + { + migrate: + "dotenvx run --env-file=.env.development -- prisma migrate dev", + }, + ]; + + fs.readFile(targetPackagePath, "utf-8", (err, data) => { + if (err) { + // TODO -> handle errors + } + + const targetData = JSON.parse(data); + + appendScripts.map((s) => { + Object.assign(targetData.scripts, s); + }); + + fs.writeFile(targetPackagePath, JSON.stringify(targetData), (err) => { + // TODO -> handle errors + }); + }); +} + +async function x( + userInput: T_UserInputCli, + projectDirPath: string, + targetPath: string, +) { + const optionsDirPath = `${projectDirPath}/options`; + let localOrmDirPath: string; + const tagetSrcPath = `${targetPath}/src`; + const targetOrmDirPath = `${tagetSrcPath}/config`; + + const targetEnvPath = `${targetPath}/.env.development`; + let envAppendData = userInput.dsn; + + const wantTs = ifWantTs(userInput); + + switch (userInput.orm) { + case "mongoose": + envAppendData = `MONGO_URI=${envAppendData}`; + appendFile(targetEnvPath, envAppendData); + + localOrmDirPath = `${optionsDirPath}/mongoose/${ + wantTs ? "ts" : "js" + }`; + + updateFile( + `${localOrmDirPath}/index.${wantTs ? "ts" : "js"}`, + `${tagetSrcPath}/index.${wantTs ? "ts" : "js"}`, + ); + + copyFile( + `${localOrmDirPath}/db.${wantTs ? "ts" : "js"}`, + `${targetOrmDirPath}/db.${wantTs ? "ts" : "js"}`, + ); + break; + + case "prisma": { + envAppendData = `DATABASE_URL=${envAppendData}`; + appendFile(targetEnvPath, envAppendData); + + exec("npx prisma init", { cwd: targetPath }, (err) => { + if (err) { + // TODO -> handle errors + } + + const defaultEnvPath = `${targetPath}/.env`; + deleteFile(defaultEnvPath); + }); + + localOrmDirPath = `${optionsDirPath}/prisma/${ + wantTs ? "ts" : "js" + }`; + + updateFile( + `${localOrmDirPath}/index.${wantTs ? "ts" : "js"}`, + `${tagetSrcPath}/index.${wantTs ? "ts" : "js"}`, + ); + + // updatePackageScript(targetPath); + break; + } + + default: + // Handle other cases or throw an error + break; + } +} + +export default x; diff --git a/src/helpers/fmt&Linters.ts b/src/helpers/fmt&Linters.ts new file mode 100644 index 0000000..65051ff --- /dev/null +++ b/src/helpers/fmt&Linters.ts @@ -0,0 +1,52 @@ +import fs from "node:fs"; + +import type { T_FormatAndLinters } from "../types/prompt"; + +import { updateFile } from "@utils/fileSystem"; + +async function addFmtAndLinterConfig( + fmtAndLinter: T_FormatAndLinters, + targetPath: string, + projectDirPath: string, +) { + const optionsDirPath = `${projectDirPath}/options`; + const localConfigPath = `${optionsDirPath}/${fmtAndLinter}/extensions.json`; + const targetConfigPath = `${targetPath}/.vscode/extensions.json`; + switch (fmtAndLinter) { + case "biome-prettier": + { + const biomeConfig = "biome.json"; + const localBiomeConfigPath = `${optionsDirPath}/${fmtAndLinter}/${biomeConfig}`; + const targetBiomeConfigPath = `${targetPath}/${biomeConfig}`; + fs.copyFile( + localBiomeConfigPath, + targetBiomeConfigPath, + (err) => { + // TODO -> handle errors + }, + ); + } + + break; + case "eslint-prettier": + { + const esLintConfig = "eslint.config.js"; + const localEsLintConfigPath = `${optionsDirPath}/${fmtAndLinter}/${esLintConfig}`; + const targetEsLintConfigPath = `${targetPath}/${esLintConfig}`; + fs.copyFile( + localEsLintConfigPath, + targetEsLintConfigPath, + (err) => { + // TODO -> handle errors + }, + ); + } + + break; + default: + break; + } + updateFile(localConfigPath, targetConfigPath); +} + +export default addFmtAndLinterConfig; diff --git a/src/helpers/handleOptions.ts b/src/helpers/handleOptions.ts new file mode 100644 index 0000000..a3d6df7 --- /dev/null +++ b/src/helpers/handleOptions.ts @@ -0,0 +1,41 @@ +import { bgCyan } from "kolorist"; +import type { T_UserInputCli } from "../types/prompt"; + +// export type T_ReturnHandleOptions = { +// dependencyCmd: string; +// devDependencyCmd: string; +// }; + +function handleAdditionalOptions( + userInput: T_UserInputCli, + tempDependency: string, + tempDevDependency: string, +) { + let dependency = tempDependency; + let devDependency = `${tempDevDependency} prettier`; + + if (userInput.formatterAndLinter === "biome-prettier") { + devDependency = `${devDependency} @biomejs/biome`; + } else { + devDependency = `${devDependency} eslint`; + if (userInput.template === "express/ts") { + devDependency = `${devDependency} @typescript-eslint/parser @typescript-eslint/eslint-plugin eslint-plugin-prettier`; + } + } + + if (userInput.wantDb) { + if (userInput.orm === "mongoose") { + dependency = `${dependency} mongoose`; + } else { + dependency = `${dependency} prisma @prisma/client`; + } + } + + const installCmd = `${dependency} && ${devDependency}`; + + console.log(bgCyan(installCmd)); + + return installCmd; +} + +export default handleAdditionalOptions; diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..3e77bdc --- /dev/null +++ b/src/index.ts @@ -0,0 +1,175 @@ +import { exec } from "node:child_process"; +import fs from "node:fs"; +import { Worker } from "node:worker_threads"; + +import x from "@helpers/db&Orms"; +import { updatePackageScript } from "@helpers/db&Orms"; +import addFmtAndLinterConfig from "@helpers/fmt&Linters"; +import handleAdditionalOptions from "@helpers/handleOptions"; +import { parseArgs, startUserInteraction } from "@utils/cli"; + +import type { + T_Arg_HandleArgs, + T_Arg_HandleCli, +} from "./types/dependencyInstallers"; +import type { T_UserInput } from "./types/prompt"; + +const cwd = process.cwd(); +let filePathArr: string[]; +export let projectDirPath: string; + +if (process.platform === "win32") { + filePathArr = __dirname.split("\\"); + filePathArr.pop(); + projectDirPath = filePathArr.join("\\"); +} else { + filePathArr = __dirname.split("/"); + filePathArr.pop(); + projectDirPath = filePathArr.join("/"); +} + +(async () => { + const parsedArgs = parseArgs(); + + if (!parsedArgs) { + const userInputCli = await startUserInteraction(); + + handleLogic(userInputCli); + } else { + handleLogic(parsedArgs); + } +})(); + +function copyTemplate(targetPath: string, targetTemplate: string) { + try { + const templatePath = `${projectDirPath}/templates/${targetTemplate}`; + fs.cpSync(templatePath, targetPath, { recursive: true }); + } catch (err) { + console.log(err); + } +} + +async function intialiseGitRepo(targetPath: string) { + const intialiseCmd = "git init"; + exec(intialiseCmd, { cwd: targetPath }, (err) => { + if (err) { + } + }); +} + +function installDependecies(targetPath: string, userInput: T_UserInput) { + let installCmd: string; + const dependencyCmd = "npm i express pino pino-http pino-pretty"; + let devDependencyCmd: string; + + const installWorkerPath = `${projectDirPath}/dist/utils/installWorker.js`; + function handleArgs({ installCmd, targetPath }: T_Arg_HandleArgs) { + const installWorker = new Worker(installWorkerPath, { + workerData: { + installCmd, + targetPath, + }, + }); + + installWorker.on("exit", (code) => { + if (code === 0) { + updatePackageScript(targetPath); + } + }); + } + + function handleCli({ + userInput, + dependencyCmd, + devDependencyCmd, + targetPath, + }: T_Arg_HandleCli) { + const installCmd = handleAdditionalOptions( + userInput, + dependencyCmd, + devDependencyCmd, + ); + + const installWorker = new Worker(installWorkerPath, { + workerData: { + installCmd, + targetPath, + }, + }); + + installWorker.on("exit", (code) => { + if (code === 0) { + updatePackageScript(targetPath); + } + }); + + addFmtAndLinterConfig( + userInput.formatterAndLinter, + targetPath, + projectDirPath, + ); + + if (userInput.wantDb) { + x(userInput, projectDirPath, targetPath); + } + } + + switch (userInput.template) { + case "express/js": + { + devDependencyCmd = "npm i --save-dev @dotenvx/dotenvx nodemon"; + + installCmd = `${dependencyCmd} && ${devDependencyCmd}`; + if (userInput.type === "args") { + handleArgs({ installCmd, targetPath }); + } else { + handleCli({ + userInput, + dependencyCmd, + devDependencyCmd, + targetPath, + }); + } + } + break; + case "express/ts": + { + devDependencyCmd = + "npm i --save-dev tsx typescript @dotenvx/dotenvx @types/express @types/node"; + + installCmd = `${dependencyCmd} && ${devDependencyCmd}`; + if (userInput.type === "args") { + handleArgs({ installCmd, targetPath }); + } else { + handleCli({ + userInput, + dependencyCmd, + devDependencyCmd, + targetPath, + }); + } + } + break; + default: + break; + } +} + +export function rollBack(targetPath: string) { + try { + fs.rmdirSync(targetPath); + } catch (err) { + // TODO -> handle errors + } +} + +async function handleLogic(userInput: T_UserInput) { + try { + const targetPath = `${cwd}/${userInput.dirName}`; + copyTemplate(targetPath, userInput.template); + + installDependecies(targetPath, userInput); + + intialiseGitRepo(targetPath); + } catch (err) {} +} diff --git a/src/types/dependencyInstallers.d.ts b/src/types/dependencyInstallers.d.ts new file mode 100644 index 0000000..86efc78 --- /dev/null +++ b/src/types/dependencyInstallers.d.ts @@ -0,0 +1,13 @@ +import type { T_UserInputCli } from "./prompt"; + +export type T_Arg_HandleArgs = { + installCmd: string; + targetPath: string; +}; + +export type T_Arg_HandleCli = { + userInput: T_UserInputCli; + dependencyCmd: string; + devDependencyCmd: string; + targetPath: string; +}; diff --git a/src/types/prompt.d.ts b/src/types/prompt.d.ts new file mode 100644 index 0000000..cea66de --- /dev/null +++ b/src/types/prompt.d.ts @@ -0,0 +1,25 @@ +declare const templateNames: readonly ["express/js", "express/ts"]; +declare const formatAndLinters: readonly ["eslint-prettier", "biome-prettier"]; +declare const orms: readonly ["prisma", "mongoose"]; + +export type T_TemplateNames = (typeof templateNames)[number]; +export type T_FormatAndLinters = (typeof formatAndLinters)[number]; +export type T_Orms = (typeof orms)[number]; + +export type T_UserInputArgs = { + type: "args"; + template: T_TemplateNames; + dirName: string; +}; + +export type T_UserInputCli = { + type: "cli"; + template: T_TemplateNames; + dirName: string; + formatterAndLinter: T_FormatAndLinters; + wantDb: boolean; + orm: T_Orms; + dsn: string; +}; + +export type T_UserInput = T_UserInputArgs | T_UserInputCli; diff --git a/src/utils/cli.ts b/src/utils/cli.ts new file mode 100644 index 0000000..f38306a --- /dev/null +++ b/src/utils/cli.ts @@ -0,0 +1,228 @@ +// still not sure which one to final but for select 'prompts' is looking nicer then inquirer +import { Command, Option } from "commander"; +import { blue, green, lightRed, magenta, red, white, yellow } from "kolorist"; +import prompts from "prompts"; + +import type { T_UserInput } from "../types/prompt"; + +type ColorFunc = (str: string | number) => string; +type Framework = { + name: string; + display: string; + color?: ColorFunc; + variants: FrameworkVariant[]; +}; +type FrameworkVariant = { + name: string; + display: string; + color: ColorFunc; + description: string; + customCommand?: string; +}; +type Options = { + name: string; + display: string; + color: ColorFunc; + description: string; +}; + +const frameworks: Framework[] = [ + { + name: "express", + display: "Express", + variants: [ + { + name: "express/js", + display: "Express", + color: yellow, + description: "Includes JavaScript.", + }, + { + name: "express/ts", + display: "Express + TypeScript", + color: blue, + description: "Includes TypeScript.", + }, + ], + }, +]; + +export const templates: ReadonlyArray = frameworks + .map((f: Framework) => { + return f.variants.map((v: FrameworkVariant) => { + return v; + }); + }) + .reduce((a, b) => a.concat(b), []); + +export const formatterAndLinters: Options[] = [ + { + name: "eslint-prettier", + display: "EsLint + Prettier", + color: magenta, + description: "Includes EsLint as linter & Prettier as Formatter.", + }, + { + name: "biome-prettier", + display: "Biome + Prettier", + color: blue, + description: + "Includes Biome for linting/formatting and Prettier for other files.", + }, +]; + +export const orms: Options[] = [ + { + name: "prisma", + display: "Relational Db + Prisma", + color: blue, + description: "Includes Prisma ORM.", + }, + { + name: "mongoose", + display: "Non-Relational Db + mongoose", + color: green, + description: "Includes mongoose OEM.", + }, +]; + +const defaultDirName = "node-nitro-app"; + +export function parseArgs() { + const program = new Command(); + + program + .addOption( + new Option("-t, --template ", "template name").choices( + templates.map((t: FrameworkVariant) => t.name), + ), + ) + .addOption( + new Option( + "-d, --dir [string]", + "name of the project directory", + ).preset(defaultDirName), + ) + .action((options) => { + if (options.dir) { + if (!options.template) { + console.log( + "error: required option '-t, --template ' not specified", + ); + process.exit(1); + } + } + }) + .parse(process.argv); + + const userArgs = program.opts(); + + if (!userArgs.template && !userArgs.dir) { + return null; + } + + const userInput: T_UserInput = { + type: "args", + template: userArgs.template, + dirName: userArgs.dir, + }; + + return userInput; +} + +export async function startUserInteraction() { + const uInput = await prompts( + [ + { + type: "select", + name: "ucTemplate", + message: "Choose your desired template", + choices: templates.map((t: FrameworkVariant) => { + const outputColor = t.color; + return { + title: outputColor(t.display), + value: t.name, + description: t.description, + }; + }), + }, + { + type: "text", + name: "ucDirName", + message: "Enter name for project directory", + initial: defaultDirName, + }, + { + type: "select", + name: "ucFormatterAndLinter", + message: "Choose your desired formatter and linter combo", + choices: formatterAndLinters.map((fl: Options) => { + const outputColor = fl.color; + + const displaySplit = fl.display + .split("+") + .map((s: string) => s.trim()); + + return { + title: `${outputColor(displaySplit[0])}${lightRed( + ` + ${displaySplit[1]}`, + )}`, + value: fl.name, + description: fl.description, + }; + }), + }, + { + type: "toggle", + name: "ucWantDb", + message: "Do you want to connect to db", + active: "yes", + inactive: "no", + }, + { + type: (prev) => (prev ? "select" : null), + name: "ucORM", + message: "Choose your desired OEM/ORM", + choices: orms.map((orm: Options) => { + const outputColor = orm.color; + + return { + title: outputColor(orm.display), + value: orm.name, + description: orm.description, + }; + }), + }, + { + type: (prev) => (prev ? "invisible" : null), + name: "ucDsn", + message: "Enter your connection string", + validate(value) { + if (value === "") { + return "Connection string cannot be empty!"; + } + + return true; + }, + }, + ], + { + onCancel() { + console.log(red("program stopped keyboard interupt")); + process.exit(1); + }, + }, + ); + + const userInput: T_UserInput = { + type: "cli", + template: uInput.ucTemplate, + dirName: uInput.ucDirName, + formatterAndLinter: uInput.ucFormatterAndLinter, + wantDb: uInput.ucWantDb, + orm: uInput.ucORM, + dsn: uInput.ucDsn, + }; + + return userInput; +} diff --git a/src/utils/fileSystem.ts b/src/utils/fileSystem.ts new file mode 100644 index 0000000..a2d3246 --- /dev/null +++ b/src/utils/fileSystem.ts @@ -0,0 +1,49 @@ +import fs from "node:fs"; + +export function deleteFile(targetFilePath: string) { + fs.unlink(targetFilePath, (err) => { + // TODO -> handle errors + }); +} + +export async function updateFile( + localFilePath: string, + targetFilePath: string, +) { + fs.readFile(targetFilePath, "utf-8", (err, data) => { + if (err) { + // TODO -> handle errors + } + + let targetData = data; + fs.readFile(localFilePath, "utf-8", (err, data) => { + if (err) { + } + + const localData = data; + targetData = localData; + + fs.writeFile(targetFilePath, targetData, (err) => { + if (err) { + // TODO -> handle errors + } + }); + }); + }); +} + +export async function copyFile(localFilePath: string, targetFilePath: string) { + fs.copyFile(localFilePath, targetFilePath, (err) => { + if (err) { + // TODO -> handle errors + } + }); +} + +export async function appendFile(targetFilePath: string, appendData: string) { + fs.appendFile(targetFilePath, appendData, (err) => { + if (err) { + // TODO -> handle errors + } + }); +} diff --git a/src/utils/installWorker.ts b/src/utils/installWorker.ts new file mode 100644 index 0000000..3c64c62 --- /dev/null +++ b/src/utils/installWorker.ts @@ -0,0 +1,15 @@ +import { execSync } from "node:child_process"; +import { workerData } from "node:worker_threads"; + +function installDependenciesInBackground( + installCmd: string, + targetPath: string, +) { + try { + execSync(installCmd, { cwd: targetPath }); + } catch (err) { + // TODO -> handle errors + } +} + +installDependenciesInBackground(workerData.installCmd, workerData.targetPath); diff --git a/templates/express/js/.editorconfig b/templates/express/js/.editorconfig new file mode 100644 index 0000000..1e7c1c2 --- /dev/null +++ b/templates/express/js/.editorconfig @@ -0,0 +1,33 @@ +# .editorconfig + +# top-most EditorConfig file +root = true + +# Unix-style newlines with a newline ending every file +[*] +end_of_line = lf +insert_final_newline = false + +# Matches multiple files with brace expansion notation +# Set default charset +[*.{js,ts,css,html}] +charset = utf-8 + +# Space indentation +[*.{js,ts,css,html,json}] +indent_style = space +indent_size = 4 + +# Matches the exact files either package.json or .travis.yml +[{package.json,.travis.yml}] +indent_style = space +indent_size = 4 + +# Matches the exact file .editorconfig +[.editorconfig] +indent_style = space +indent_size = 4 + +# Markdown files often use trailing whitespace to indicate line breaks +[*.md] +trim_trailing_whitespace = false \ No newline at end of file diff --git a/templates/express/js/.gitignore b/templates/express/js/.gitignore new file mode 100644 index 0000000..64518ba --- /dev/null +++ b/templates/express/js/.gitignore @@ -0,0 +1,200 @@ +# Created by https://www.gitignore.io/api/git,node,macos,windows,visualstudiocode +# Edit at https://www.gitignore.io/?templates=git,node,macos,windows,visualstudiocode + +### Git ### +# Created by git for backups. To disable backups in Git: +# $ git config --global mergetool.keepBackup false +*.orig + +# Created by git when using merge tools for conflicts +*.BACKUP.* +*.BASE.* +*.LOCAL.* +*.REMOTE.* +*_BACKUP_*.txt +*_BASE_*.txt +*_LOCAL_*.txt +*_REMOTE_*.txt + +### macOS ### +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +### Node ### +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# TypeScript v1 declaration files +typings/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +#.env +#.env.test + +# parcel-bundler cache (https://parceljs.org/) +.cache + +# next.js build output +.next + +# nuxt.js build output +.nuxt + +# rollup.js default build output +dist/ + +# Uncomment the public line if your project uses Gatsby +# https://nextjs.org/blog/next-9-1#public-directory-support +# https://create-react-app.dev/docs/using-the-public-folder/#docsNav +# public + +# Storybook build outputs +.out +.storybook-out + +# vuepress build output +.vuepress/dist + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# Temporary folders +tmp/ +temp/ + +### VisualStudioCode ### +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json + +### VisualStudioCode Patch ### +# Ignore all local history of files +.history + +### Windows ### +# Windows thumbnail cache files +Thumbs.db +Thumbs.db:encryptable +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +# Enviorment variables +.env.* + +# Test data +*.csv +test-data.json + +# SSL certificates +ssl + +# End of https://www.gitignore.io/api/git,node,macos,windows,visualstudiocode \ No newline at end of file diff --git a/templates/express/js/.prettierrc b/templates/express/js/.prettierrc new file mode 100644 index 0000000..a01256e --- /dev/null +++ b/templates/express/js/.prettierrc @@ -0,0 +1,11 @@ +{ + "semi": true, + "trailingComma": "all", + "singleQuote": true, + "printWidth": 80, + "tabWidth": 4, + "useTabs": false, + "bracketSpacing": true, + "arrowParens": "avoid", + "endOfLine": "lf" +} diff --git a/templates/express/js/.vscode/extensions.json b/templates/express/js/.vscode/extensions.json new file mode 100644 index 0000000..b654687 --- /dev/null +++ b/templates/express/js/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["esbenp.prettier-vscode", "editorconfig.editorconfig"] +} diff --git a/templates/express/js/README.md b/templates/express/js/README.md new file mode 100644 index 0000000..e69de29 diff --git a/templates/express/js/package.json b/templates/express/js/package.json new file mode 100644 index 0000000..f25be58 --- /dev/null +++ b/templates/express/js/package.json @@ -0,0 +1,12 @@ +{ + "name": "node-nitro-app", + "version": "0.1.0", + "description": "", + "main": "index.js", + "type": "module", + "scripts": { + "dev": "dotenvx run --env-file=.env.development -- nodemon ./src/index.js", + "test": "echo \"Error: no test specified\" && exit 1", + "start": "node ./index.js" + } +} diff --git a/templates/express/js/src/config/headers.js b/templates/express/js/src/config/headers.js new file mode 100644 index 0000000..fe1644a --- /dev/null +++ b/templates/express/js/src/config/headers.js @@ -0,0 +1,56 @@ +// Import necessary modules +import { logger } from '../logger.js'; + +// Middleware function to set HTTP headers for CORS +async function setHeaders(req, res, next) { + let allowedOrigin = []; + + // Check the environment of the application + switch (process.env.NODE_ENV) { + case 'development': + // In development, proceed to the next middleware + next(); + break; + case 'production': + { + // In production, only allow requests from your application + allowedOrigin = ['']; + + // Get the origin of the request + const origin = req.headers.origin; + + // If the origin is not allowed, send a 403 response + if (allowedOrigin.indexOf(origin) === -1) { + res.status(403).send('Origin not allowed'); + } else { + // Set CORS headers + res.setHeader('Access-Control-Allow-Credentials', 'true'); + res.setHeader('Access-Control-Allow-Origin'); + res.setHeader( + 'Access-Control-Allow-Methods', + 'GET,OPTIONS,PATCH,DELETE,POST,PUT', + ); + res.setHeader( + 'Access-Control-Allow-Headers', + 'X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version', + ); + + // If the request method is OPTIONS, send a 200 response + if (req.method === 'OPTIONS') { + res.status(200).end(); + return; + } + + // Proceed to the next middleware + next(); + } + } + break; + default: + // Log an error if the NODE_ENV value is invalid + logger.error('Invalid NODE_ENV value'); + break; + } +} + +export default setHeaders; diff --git a/templates/express/js/src/index.js b/templates/express/js/src/index.js new file mode 100644 index 0000000..76d2541 --- /dev/null +++ b/templates/express/js/src/index.js @@ -0,0 +1,22 @@ +import setHeaders from './config/headers.js'; +import { httpLogger, logger } from './logger.js'; + +import express from 'express'; + +const PORT = process.env.PORT || 3001; +const app = express(); + +app.use(express.json()); +app.use(express.urlencoded({ extended: true })); +app.use(setHeaders); +app.use(httpLogger); + +if (process.env.NODE_ENV === 'development') { + app.get('/', (req, res) => { + res.send('Welcome to api set up by node-nitro ^_+'); + }); +} + +app.listen(PORT, () => { + logger.info(`-> now listening at http://localhost:${PORT}/`); +}); diff --git a/templates/express/js/src/logger.js b/templates/express/js/src/logger.js new file mode 100644 index 0000000..724a31f --- /dev/null +++ b/templates/express/js/src/logger.js @@ -0,0 +1,15 @@ +// import pino & pino-http. +import pino from "pino"; +import pinoHttp from "pino-http"; + +// import pino-pretty. +import pretty from "pino-pretty"; + +const stream = pretty({ + levelFirst: true, + colorize: true, + ignore: "time,hostname,pid", +}); + +export const logger = pino({}, stream); +export const httpLogger = pinoHttp({ logger: logger, autoLogging: false }); diff --git a/templates/express/ts/.editorconfig b/templates/express/ts/.editorconfig new file mode 100644 index 0000000..1e7c1c2 --- /dev/null +++ b/templates/express/ts/.editorconfig @@ -0,0 +1,33 @@ +# .editorconfig + +# top-most EditorConfig file +root = true + +# Unix-style newlines with a newline ending every file +[*] +end_of_line = lf +insert_final_newline = false + +# Matches multiple files with brace expansion notation +# Set default charset +[*.{js,ts,css,html}] +charset = utf-8 + +# Space indentation +[*.{js,ts,css,html,json}] +indent_style = space +indent_size = 4 + +# Matches the exact files either package.json or .travis.yml +[{package.json,.travis.yml}] +indent_style = space +indent_size = 4 + +# Matches the exact file .editorconfig +[.editorconfig] +indent_style = space +indent_size = 4 + +# Markdown files often use trailing whitespace to indicate line breaks +[*.md] +trim_trailing_whitespace = false \ No newline at end of file diff --git a/templates/express/ts/.gitignore b/templates/express/ts/.gitignore new file mode 100644 index 0000000..64518ba --- /dev/null +++ b/templates/express/ts/.gitignore @@ -0,0 +1,200 @@ +# Created by https://www.gitignore.io/api/git,node,macos,windows,visualstudiocode +# Edit at https://www.gitignore.io/?templates=git,node,macos,windows,visualstudiocode + +### Git ### +# Created by git for backups. To disable backups in Git: +# $ git config --global mergetool.keepBackup false +*.orig + +# Created by git when using merge tools for conflicts +*.BACKUP.* +*.BASE.* +*.LOCAL.* +*.REMOTE.* +*_BACKUP_*.txt +*_BASE_*.txt +*_LOCAL_*.txt +*_REMOTE_*.txt + +### macOS ### +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +### Node ### +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# TypeScript v1 declaration files +typings/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +#.env +#.env.test + +# parcel-bundler cache (https://parceljs.org/) +.cache + +# next.js build output +.next + +# nuxt.js build output +.nuxt + +# rollup.js default build output +dist/ + +# Uncomment the public line if your project uses Gatsby +# https://nextjs.org/blog/next-9-1#public-directory-support +# https://create-react-app.dev/docs/using-the-public-folder/#docsNav +# public + +# Storybook build outputs +.out +.storybook-out + +# vuepress build output +.vuepress/dist + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# Temporary folders +tmp/ +temp/ + +### VisualStudioCode ### +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json + +### VisualStudioCode Patch ### +# Ignore all local history of files +.history + +### Windows ### +# Windows thumbnail cache files +Thumbs.db +Thumbs.db:encryptable +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +# Enviorment variables +.env.* + +# Test data +*.csv +test-data.json + +# SSL certificates +ssl + +# End of https://www.gitignore.io/api/git,node,macos,windows,visualstudiocode \ No newline at end of file diff --git a/templates/express/ts/.prettierrc b/templates/express/ts/.prettierrc new file mode 100644 index 0000000..a01256e --- /dev/null +++ b/templates/express/ts/.prettierrc @@ -0,0 +1,11 @@ +{ + "semi": true, + "trailingComma": "all", + "singleQuote": true, + "printWidth": 80, + "tabWidth": 4, + "useTabs": false, + "bracketSpacing": true, + "arrowParens": "avoid", + "endOfLine": "lf" +} diff --git a/templates/express/ts/.vscode/extensions.json b/templates/express/ts/.vscode/extensions.json new file mode 100644 index 0000000..b654687 --- /dev/null +++ b/templates/express/ts/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["esbenp.prettier-vscode", "editorconfig.editorconfig"] +} diff --git a/templates/express/ts/README.md b/templates/express/ts/README.md new file mode 100644 index 0000000..e69de29 diff --git a/templates/express/ts/package.json b/templates/express/ts/package.json new file mode 100644 index 0000000..a997651 --- /dev/null +++ b/templates/express/ts/package.json @@ -0,0 +1,11 @@ +{ + "name": "node-nitro-app", + "version": "0.1.0", + "description": "", + "main": "index.js", + "scripts": { + "dev": "dotenvx run --env-file=.env.development -- tsx watch ./src/index.ts", + "test": "echo \"Error: no test specified\" && exit 1", + "start": "node ./index.js" + } +} diff --git a/templates/express/ts/src/config/headers.ts b/templates/express/ts/src/config/headers.ts new file mode 100644 index 0000000..a707b8e --- /dev/null +++ b/templates/express/ts/src/config/headers.ts @@ -0,0 +1,62 @@ +// Import types +import type { NextFunction, Request, Response } from "express"; + +// Import necessary modules +import { logger } from "@logger"; + +// Middleware function to set HTTP headers for CORS +async function setHeaders(req: Request, res: Response, next: NextFunction) { + let allowedOrigin: string[] = []; + + // Check the environment of the application + switch (process.env.NODE_ENV) { + case "development": + // In development, proceed to the next middleware + next(); + break; + case "production": + { + // In production, only allow requests from your application + allowedOrigin = [""]; + + // Get the origin of the request + const origin = req.headers.origin; + + // If the origin is not allowed, send a 403 response + if (allowedOrigin.indexOf(origin as string) === -1) { + res.status(403).send("Origin not allowed"); + } else { + // Set CORS headers + res.setHeader("Access-Control-Allow-Credentials", "true"); + res.setHeader( + "Access-Control-Allow-Origin", + origin as string, + ); + res.setHeader( + "Access-Control-Allow-Methods", + "GET,OPTIONS,PATCH,DELETE,POST,PUT", + ); + res.setHeader( + "Access-Control-Allow-Headers", + "X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version", + ); + + // If the request method is OPTIONS, send a 200 response + if (req.method === "OPTIONS") { + res.status(200).end(); + return; + } + + // Proceed to the next middleware + next(); + } + } + break; + default: + // Log an error if the NODE_ENV value is invalid + logger.error("Invalid NODE_ENV value"); + break; + } +} + +export default setHeaders; diff --git a/templates/express/ts/src/index.ts b/templates/express/ts/src/index.ts new file mode 100644 index 0000000..3fb572d --- /dev/null +++ b/templates/express/ts/src/index.ts @@ -0,0 +1,22 @@ +import setHeaders from "./config/headers"; +import { httpLogger, logger } from "./logger"; + +import express from "express"; + +const PORT = process.env.PORT || 3001; +const app = express(); + +app.use(express.json()); +app.use(express.urlencoded({ extended: true })); +app.use(setHeaders); +app.use(httpLogger); + +if (process.env.NODE_ENV === "development") { + app.get("/", (req, res) => { + res.send("Welcome to api set up by node-nitro ^_+"); + }); +} + +app.listen(PORT, () => { + logger.info(`-> now listening at http://localhost:${PORT}/`); +}); diff --git a/templates/express/ts/src/logger.ts b/templates/express/ts/src/logger.ts new file mode 100644 index 0000000..724a31f --- /dev/null +++ b/templates/express/ts/src/logger.ts @@ -0,0 +1,15 @@ +// import pino & pino-http. +import pino from "pino"; +import pinoHttp from "pino-http"; + +// import pino-pretty. +import pretty from "pino-pretty"; + +const stream = pretty({ + levelFirst: true, + colorize: true, + ignore: "time,hostname,pid", +}); + +export const logger = pino({}, stream); +export const httpLogger = pinoHttp({ logger: logger, autoLogging: false }); diff --git a/templates/express/ts/tsconfig.json b/templates/express/ts/tsconfig.json new file mode 100644 index 0000000..7f4a466 --- /dev/null +++ b/templates/express/ts/tsconfig.json @@ -0,0 +1,28 @@ +{ + "compilerOptions": { + "target": "ES6", + "module": "NodeNext", + "lib": ["es6"], + "allowJs": true, + "outDir": "./dist", + "rootDir": "./src/", + "strict": true, + "noImplicitAny": true, + "esModuleInterop": true, + "resolveJsonModule": true, + "typeRoots": ["./types", "./node_modules/@types"], + "paths": { + "@controllers/*": ["./src/controllers/*"], + "@helpers/*": ["./src/helpers/*"], + "@middlewares/*": ["./src/middlewares/*"], + "@models/*": ["./src/models/*"], + "@routes/*": ["./src/routes/*"], + "@utils/*": ["./src/utils/*"], + "@validations/*": ["./src/validations/*"], + "@services/*": ["./src/services/*"], + "@logger": ["./src/logger"] + }, + "plugins": [{ "transform": "typescript-transform-paths" }] + }, + "exclude": ["node_modules", "dist", "coverage", "*.config.js"] +} diff --git a/templates/express/ts/types/enviorment.d.ts b/templates/express/ts/types/enviorment.d.ts new file mode 100644 index 0000000..6502294 --- /dev/null +++ b/templates/express/ts/types/enviorment.d.ts @@ -0,0 +1,9 @@ +declare global { + namespace NodeJS { + interface ProcessEnv { + NODE_ENV: "development" | "production"; + } + } +} + +export type {}; diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..5f3a047 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,36 @@ +{ + "compilerOptions": { + "target": "ES6", + "module": "NodeNext", + "lib": ["dom", "es6", "dom.iterable", "scripthost"], + "allowJs": true, + "outDir": "./dist", + "rootDir": "./src/", + "strict": true, + "noImplicitAny": true, + "esModuleInterop": true, + "resolveJsonModule": true, + "typeRoots": ["./types", "./node_modules/@types"], + "paths": { + "@controllers/*": ["./src/controllers/*"], + "@helpers/*": ["./src/helpers/*"], + "@middlewares/*": ["./src/middlewares/*"], + "@models/*": ["./src/models/*"], + "@routes/*": ["./src/routes/*"], + "@utils/*": ["./src/utils/*"], + "@validations/*": ["./src/validations/*"], + "@services/*": ["./src/services/*"], + "@logger": ["./src/logger"] + }, + "plugins": [{ "transform": "typescript-transform-paths" }] + }, + "exclude": [ + "./index.js", + "node_modules", + "dist", + "coverage", + "*.config.js", + "templates", + "options" + ] +}