├── .github └── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── .gitignore ├── CNAME ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── medias ├── create-bedrock-cli-banner.png ├── gif.gif ├── img1.png └── img2.png ├── package-lock.json ├── package.json └── src ├── cli ├── commands.js └── index.js ├── services ├── fileService.js ├── gitService.js ├── manifestService.js └── templateLabels.js └── utils ├── helpers.js └── logger.js /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ -------------------------------------------------------------------------------- /CNAME: -------------------------------------------------------------------------------- 1 | bedrockcli.keyyard.xyz -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, religion, or sexual identity 10 | and orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | * Demonstrating empathy and kindness toward other people 21 | * Being respectful of differing opinions, viewpoints, and experiences 22 | * Giving and gracefully accepting constructive feedback 23 | * Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | * Focusing on what is best not just for us as individuals, but for the 26 | overall community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | * The use of sexualized language or imagery, and sexual attention or 31 | advances of any kind 32 | * Trolling, insulting or derogatory comments, and personal or political attacks 33 | * Public or private harassment 34 | * Publishing others' private information, such as a physical or email 35 | address, without their explicit permission 36 | * Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards of 42 | acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies when 54 | an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail address, 56 | posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement at 63 | contact@keyyard.xyz. 64 | All complaints will be reviewed and investigated promptly and fairly. 65 | 66 | All community leaders are obligated to respect the privacy and security of the 67 | reporter of any incident. 68 | 69 | ## Enforcement Guidelines 70 | 71 | Community leaders will follow these Community Impact Guidelines in determining 72 | the consequences for any action they deem in violation of this Code of Conduct: 73 | 74 | ### 1. Correction 75 | 76 | **Community Impact**: Use of inappropriate language or other behavior deemed 77 | unprofessional or unwelcome in the community. 78 | 79 | **Consequence**: A private, written warning from community leaders, providing 80 | clarity around the nature of the violation and an explanation of why the 81 | behavior was inappropriate. A public apology may be requested. 82 | 83 | ### 2. Warning 84 | 85 | **Community Impact**: A violation through a single incident or series 86 | of actions. 87 | 88 | **Consequence**: A warning with consequences for continued behavior. No 89 | interaction with the people involved, including unsolicited interaction with 90 | those enforcing the Code of Conduct, for a specified period of time. This 91 | includes avoiding interactions in community spaces as well as external channels 92 | like social media. Violating these terms may lead to a temporary or 93 | permanent ban. 94 | 95 | ### 3. Temporary Ban 96 | 97 | **Community Impact**: A serious violation of community standards, including 98 | sustained inappropriate behavior. 99 | 100 | **Consequence**: A temporary ban from any sort of interaction or public 101 | communication with the community for a specified period of time. No public or 102 | private interaction with the people involved, including unsolicited interaction 103 | with those enforcing the Code of Conduct, is allowed during this period. 104 | Violating these terms may lead to a permanent ban. 105 | 106 | ### 4. Permanent Ban 107 | 108 | **Community Impact**: Demonstrating a pattern of violation of community 109 | standards, including sustained inappropriate behavior, harassment of an 110 | individual, or aggression toward or disparagement of classes of individuals. 111 | 112 | **Consequence**: A permanent ban from any sort of public interaction within 113 | the community. 114 | 115 | ## Attribution 116 | 117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 118 | version 2.0, available at 119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. 120 | 121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct 122 | enforcement ladder](https://github.com/mozilla/diversity). 123 | 124 | [homepage]: https://www.contributor-covenant.org 125 | 126 | For answers to common questions about this code of conduct, see the FAQ at 127 | https://www.contributor-covenant.org/faq. Translations are available at 128 | https://www.contributor-covenant.org/translations. 129 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | We’d love your help to make Create MC Bedrock CLI even better! 2 | Whether you have ideas, spot a bug, or want to share new samples, your contributions are always welcome. 3 | 4 | Want to add a new workspace template? 5 | Simply open a pull request to the [Custom MC Scripting Templates](https://github.com/Keyyard/custom-mc-scripting-templates) repository. 6 | 7 | Every suggestion, issue, or PR helps the community grow—jump in and let’s build something awesome together! 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | MIT License 3 | 4 | Copyright (c) 2025 Keyyard 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Create MC Bedrock CLI 2 | 3 |
4 | 5 | [![GitHub Stars](https://img.shields.io/github/stars/keyyard/create-mc-bedrock-cli?style=social)](https://github.com/keyyard/create-mc-bedrock-cli) 6 | [![Version](https://img.shields.io/badge/version-1.3.0-blue.svg)](https://github.com/keyyard/create-mc-bedrock-cli) 7 | [![Node.js](https://img.shields.io/badge/Node.js-18%2B-green.svg)](https://nodejs.org/) 8 | [![License](https://img.shields.io/badge/license-MIT-orange.svg)](LICENSE) 9 | 10 | [![Website](https://img.shields.io/badge/visit%20our%20website-8A2BE2)](https://bedrockcli.keyyard.xyz/) 11 | 12 |
13 | 14 | Create MC Bedrock CLI Banner 15 | 16 |
17 | 18 | **The Fastest Way to Start Minecraft Bedrock Addon Development! 🚀** 19 | 20 | 21 | --- 22 | 23 | **Tired of manually setting up Minecraft Bedrock workspaces?** 24 | With `create-mc-bedrock`, you can bootstrap your next project in seconds, using official Microsoft samples and fresh manifest UUIDs every time. 25 | 26 | ## Table of Contents 27 | - [✨ Why Use Create MC Bedrock CLI?](#-why-use-create-mc-bedrock-cli) 28 | - [🚀 How It Works](#-how-it-works) 29 | - [📸 Showcase](#-showcase) 30 | - [🛠️ Features](#-features) 31 | - [📦 Requirements](#-requirements) 32 | - [💡 Pro Tips](#-pro-tips) 33 | - [🤝 Contributing](#-contributing) 34 | - [📄 License](#-license) 35 | - [🙏 Credits](#-credits) 36 | 37 | ## ✨ Why Use Create MC Bedrock CLI? 38 | 39 | ### ⚡ **Instant Project Setup** 40 | 41 | No more copy-pasting or manual configuration. Select a sample, pick a folder, and your workspace is ready to go—complete with unique manifest UUIDs. 42 | 43 | ### 🧠 **Focus on Building, Not Boilerplate** 44 | 45 | Spend your time creating, not setting up. All the essentials are handled for you, so you can jump straight into development. 46 | 47 | ### 🔒 **Always Unique, Always Clean** 48 | 49 | Every project is generated with new manifest UUIDs, ensuring no conflicts and a smooth import into Minecraft. 50 | 51 | ### 🗂️ **Official Samples, Your Way** 52 | 53 | Choose from a curated list of Microsoft’s best scripting samples. Your selected template is cloned directly into your chosen folder—no nested directories, no confusion. 54 | 55 | --- 56 | 57 | ## 🚀 How It Works 58 | 59 | 1. **Run the CLI:** 60 | ```bash 61 | npx create-mc-bedrock 62 | ``` 63 | 2. **Follow the Prompts:** 64 | - Select a sample project (⭐ `ts-starter` is recommended for TypeScript users!) 65 | - Choose your destination folder 66 | 3. **Start Coding:** 67 | - Your workspace is ready, with all manifests updated and temp files cleaned up. 68 | 69 | --- 70 | 71 | ## 📸 Showcase 72 | 73 |
74 | Create MC Bedrock CLI in action 75 | Create MC Bedrock CLI screenshot 76 | Create MC Bedrock CLI screenshot 77 |
78 | 79 | --- 80 | 81 | ## 🛠️ Features 82 | 83 | - Interactive CLI with sample selection 84 | - Direct cloning to your specified folder (no more nested directories) 85 | - Automatic manifest UUID regeneration for every project 86 | - Supports both JavaScript and TypeScript samples 87 | - Cleans up temporary files after setup 88 | 89 | --- 90 | 91 | ## 📦 Requirements 92 | 93 | - Node.js 18 or higher 94 | - Git 95 | 96 | --- 97 | 98 | ## 💡 Pro Tips 99 | 100 | - Use the ⭐ `ts-starter` template for a modern TypeScript setup. 101 | - Run the CLI with `npx` for the latest version every time. 102 | - All generated projects are ready to open in VS Code—just `cd` into your folder and run `code .` 103 | 104 | --- 105 | 106 | ## 🤝 Contributing 107 | 108 | We’d love your help to make Create MC Bedrock CLI even better! 109 | Whether you have ideas, spot a bug, or want to share new samples, your contributions are always welcome. 110 | 111 | Want to add a new workspace template? 112 | Simply open a pull request to the [Custom MC Scripting Templates](https://github.com/Keyyard/custom-mc-scripting-templates) repository. 113 | 114 | Every suggestion, issue, or PR helps the community grow—jump in and let’s build something awesome together! 115 | 116 | --- 117 | 118 | ## 🙏 Credits 119 | 120 | - **Beyond64** ([OsmaanGani](https://github.com/OsmaanGani)): Package banner artist 121 | - **PottedPropagule** ([PottedPropagule](https://github.com/PottedPropagule)): Issue reporter and helpful feedback 122 | 123 | --- 124 | 125 | ## ⭐ Stargazers Over Time 126 | 127 | 128 | 129 | 130 | 131 | Star History Chart 132 | 133 | 134 | 135 |
136 | **Made with ❤️ for the Minecraft Bedrock dev community** 137 |
138 | 139 | ⭐ Star us on GitHub 140 | 141 |
142 | -------------------------------------------------------------------------------- /medias/create-bedrock-cli-banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Keyyard/create-mc-bedrock-cli/acbb75f84e57273135af5c98a025faedf7a0252c/medias/create-bedrock-cli-banner.png -------------------------------------------------------------------------------- /medias/gif.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Keyyard/create-mc-bedrock-cli/acbb75f84e57273135af5c98a025faedf7a0252c/medias/gif.gif -------------------------------------------------------------------------------- /medias/img1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Keyyard/create-mc-bedrock-cli/acbb75f84e57273135af5c98a025faedf7a0252c/medias/img1.png -------------------------------------------------------------------------------- /medias/img2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Keyyard/create-mc-bedrock-cli/acbb75f84e57273135af5c98a025faedf7a0252c/medias/img2.png -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "create-mc-bedrock", 3 | "version": "1.2.1", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "create-mc-bedrock", 9 | "version": "1.2.1", 10 | "license": "MIT", 11 | "dependencies": { 12 | "inquirer": "^9.3.7", 13 | "simple-git": "^3.27.0", 14 | "uuid": "^9.0.0" 15 | }, 16 | "bin": { 17 | "create-mc-bedrock": "src/cli/index.js" 18 | } 19 | }, 20 | "node_modules/@inquirer/figures": { 21 | "version": "1.0.11", 22 | "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.11.tgz", 23 | "integrity": "sha512-eOg92lvrn/aRUqbxRyvpEWnrvRuTYRifixHkYVpJiygTgVSBIHDqLh0SrMQXkafvULg3ck11V7xvR+zcgvpHFw==", 24 | "license": "MIT", 25 | "engines": { 26 | "node": ">=18" 27 | } 28 | }, 29 | "node_modules/@kwsites/file-exists": { 30 | "version": "1.1.1", 31 | "resolved": "https://registry.npmjs.org/@kwsites/file-exists/-/file-exists-1.1.1.tgz", 32 | "integrity": "sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw==", 33 | "license": "MIT", 34 | "dependencies": { 35 | "debug": "^4.1.1" 36 | } 37 | }, 38 | "node_modules/@kwsites/promise-deferred": { 39 | "version": "1.1.1", 40 | "resolved": "https://registry.npmjs.org/@kwsites/promise-deferred/-/promise-deferred-1.1.1.tgz", 41 | "integrity": "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==", 42 | "license": "MIT" 43 | }, 44 | "node_modules/ansi-escapes": { 45 | "version": "4.3.2", 46 | "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", 47 | "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", 48 | "license": "MIT", 49 | "dependencies": { 50 | "type-fest": "^0.21.3" 51 | }, 52 | "engines": { 53 | "node": ">=8" 54 | }, 55 | "funding": { 56 | "url": "https://github.com/sponsors/sindresorhus" 57 | } 58 | }, 59 | "node_modules/ansi-regex": { 60 | "version": "5.0.1", 61 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 62 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 63 | "license": "MIT", 64 | "engines": { 65 | "node": ">=8" 66 | } 67 | }, 68 | "node_modules/ansi-styles": { 69 | "version": "4.3.0", 70 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 71 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 72 | "license": "MIT", 73 | "dependencies": { 74 | "color-convert": "^2.0.1" 75 | }, 76 | "engines": { 77 | "node": ">=8" 78 | }, 79 | "funding": { 80 | "url": "https://github.com/chalk/ansi-styles?sponsor=1" 81 | } 82 | }, 83 | "node_modules/base64-js": { 84 | "version": "1.5.1", 85 | "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", 86 | "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", 87 | "funding": [ 88 | { 89 | "type": "github", 90 | "url": "https://github.com/sponsors/feross" 91 | }, 92 | { 93 | "type": "patreon", 94 | "url": "https://www.patreon.com/feross" 95 | }, 96 | { 97 | "type": "consulting", 98 | "url": "https://feross.org/support" 99 | } 100 | ], 101 | "license": "MIT" 102 | }, 103 | "node_modules/bl": { 104 | "version": "4.1.0", 105 | "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", 106 | "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", 107 | "license": "MIT", 108 | "dependencies": { 109 | "buffer": "^5.5.0", 110 | "inherits": "^2.0.4", 111 | "readable-stream": "^3.4.0" 112 | } 113 | }, 114 | "node_modules/bluebird": { 115 | "version": "3.7.2", 116 | "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", 117 | "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", 118 | "license": "MIT" 119 | }, 120 | "node_modules/buffer": { 121 | "version": "5.7.1", 122 | "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", 123 | "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", 124 | "funding": [ 125 | { 126 | "type": "github", 127 | "url": "https://github.com/sponsors/feross" 128 | }, 129 | { 130 | "type": "patreon", 131 | "url": "https://www.patreon.com/feross" 132 | }, 133 | { 134 | "type": "consulting", 135 | "url": "https://feross.org/support" 136 | } 137 | ], 138 | "license": "MIT", 139 | "dependencies": { 140 | "base64-js": "^1.3.1", 141 | "ieee754": "^1.1.13" 142 | } 143 | }, 144 | "node_modules/chalk": { 145 | "version": "4.1.2", 146 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", 147 | "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", 148 | "license": "MIT", 149 | "dependencies": { 150 | "ansi-styles": "^4.1.0", 151 | "supports-color": "^7.1.0" 152 | }, 153 | "engines": { 154 | "node": ">=10" 155 | }, 156 | "funding": { 157 | "url": "https://github.com/chalk/chalk?sponsor=1" 158 | } 159 | }, 160 | "node_modules/chardet": { 161 | "version": "0.7.0", 162 | "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", 163 | "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", 164 | "license": "MIT" 165 | }, 166 | "node_modules/cli-cursor": { 167 | "version": "3.1.0", 168 | "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", 169 | "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", 170 | "license": "MIT", 171 | "dependencies": { 172 | "restore-cursor": "^3.1.0" 173 | }, 174 | "engines": { 175 | "node": ">=8" 176 | } 177 | }, 178 | "node_modules/cli-spinners": { 179 | "version": "2.9.2", 180 | "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", 181 | "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", 182 | "license": "MIT", 183 | "engines": { 184 | "node": ">=6" 185 | }, 186 | "funding": { 187 | "url": "https://github.com/sponsors/sindresorhus" 188 | } 189 | }, 190 | "node_modules/cli-width": { 191 | "version": "4.1.0", 192 | "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", 193 | "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", 194 | "license": "ISC", 195 | "engines": { 196 | "node": ">= 12" 197 | } 198 | }, 199 | "node_modules/clone": { 200 | "version": "1.0.4", 201 | "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", 202 | "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", 203 | "license": "MIT", 204 | "engines": { 205 | "node": ">=0.8" 206 | } 207 | }, 208 | "node_modules/color-convert": { 209 | "version": "2.0.1", 210 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 211 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 212 | "license": "MIT", 213 | "dependencies": { 214 | "color-name": "~1.1.4" 215 | }, 216 | "engines": { 217 | "node": ">=7.0.0" 218 | } 219 | }, 220 | "node_modules/color-name": { 221 | "version": "1.1.4", 222 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 223 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 224 | "license": "MIT" 225 | }, 226 | "node_modules/core-util-is": { 227 | "version": "1.0.3", 228 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", 229 | "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", 230 | "license": "MIT" 231 | }, 232 | "node_modules/debug": { 233 | "version": "4.4.0", 234 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", 235 | "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", 236 | "license": "MIT", 237 | "dependencies": { 238 | "ms": "^2.1.3" 239 | }, 240 | "engines": { 241 | "node": ">=6.0" 242 | }, 243 | "peerDependenciesMeta": { 244 | "supports-color": { 245 | "optional": true 246 | } 247 | } 248 | }, 249 | "node_modules/defaults": { 250 | "version": "1.0.4", 251 | "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", 252 | "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", 253 | "license": "MIT", 254 | "dependencies": { 255 | "clone": "^1.0.2" 256 | }, 257 | "funding": { 258 | "url": "https://github.com/sponsors/sindresorhus" 259 | } 260 | }, 261 | "node_modules/duplexer2": { 262 | "version": "0.1.4", 263 | "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", 264 | "integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==", 265 | "license": "BSD-3-Clause", 266 | "dependencies": { 267 | "readable-stream": "^2.0.2" 268 | } 269 | }, 270 | "node_modules/duplexer2/node_modules/readable-stream": { 271 | "version": "2.3.8", 272 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", 273 | "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", 274 | "license": "MIT", 275 | "dependencies": { 276 | "core-util-is": "~1.0.0", 277 | "inherits": "~2.0.3", 278 | "isarray": "~1.0.0", 279 | "process-nextick-args": "~2.0.0", 280 | "safe-buffer": "~5.1.1", 281 | "string_decoder": "~1.1.1", 282 | "util-deprecate": "~1.0.1" 283 | } 284 | }, 285 | "node_modules/duplexer2/node_modules/safe-buffer": { 286 | "version": "5.1.2", 287 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 288 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", 289 | "license": "MIT" 290 | }, 291 | "node_modules/duplexer2/node_modules/string_decoder": { 292 | "version": "1.1.1", 293 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", 294 | "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", 295 | "license": "MIT", 296 | "dependencies": { 297 | "safe-buffer": "~5.1.0" 298 | } 299 | }, 300 | "node_modules/emoji-regex": { 301 | "version": "8.0.0", 302 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 303 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", 304 | "license": "MIT" 305 | }, 306 | "node_modules/external-editor": { 307 | "version": "3.1.0", 308 | "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", 309 | "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", 310 | "license": "MIT", 311 | "dependencies": { 312 | "chardet": "^0.7.0", 313 | "iconv-lite": "^0.4.24", 314 | "tmp": "^0.0.33" 315 | }, 316 | "engines": { 317 | "node": ">=4" 318 | } 319 | }, 320 | "node_modules/fs-extra": { 321 | "version": "11.3.0", 322 | "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.0.tgz", 323 | "integrity": "sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==", 324 | "license": "MIT", 325 | "dependencies": { 326 | "graceful-fs": "^4.2.0", 327 | "jsonfile": "^6.0.1", 328 | "universalify": "^2.0.0" 329 | }, 330 | "engines": { 331 | "node": ">=14.14" 332 | } 333 | }, 334 | "node_modules/graceful-fs": { 335 | "version": "4.2.11", 336 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", 337 | "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", 338 | "license": "ISC" 339 | }, 340 | "node_modules/has-flag": { 341 | "version": "4.0.0", 342 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 343 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", 344 | "license": "MIT", 345 | "engines": { 346 | "node": ">=8" 347 | } 348 | }, 349 | "node_modules/iconv-lite": { 350 | "version": "0.4.24", 351 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 352 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 353 | "license": "MIT", 354 | "dependencies": { 355 | "safer-buffer": ">= 2.1.2 < 3" 356 | }, 357 | "engines": { 358 | "node": ">=0.10.0" 359 | } 360 | }, 361 | "node_modules/ieee754": { 362 | "version": "1.2.1", 363 | "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", 364 | "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", 365 | "funding": [ 366 | { 367 | "type": "github", 368 | "url": "https://github.com/sponsors/feross" 369 | }, 370 | { 371 | "type": "patreon", 372 | "url": "https://www.patreon.com/feross" 373 | }, 374 | { 375 | "type": "consulting", 376 | "url": "https://feross.org/support" 377 | } 378 | ], 379 | "license": "BSD-3-Clause" 380 | }, 381 | "node_modules/inherits": { 382 | "version": "2.0.4", 383 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 384 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 385 | "license": "ISC" 386 | }, 387 | "node_modules/inquirer": { 388 | "version": "9.3.7", 389 | "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-9.3.7.tgz", 390 | "integrity": "sha512-LJKFHCSeIRq9hanN14IlOtPSTe3lNES7TYDTE2xxdAy1LS5rYphajK1qtwvj3YmQXvvk0U2Vbmcni8P9EIQW9w==", 391 | "license": "MIT", 392 | "dependencies": { 393 | "@inquirer/figures": "^1.0.3", 394 | "ansi-escapes": "^4.3.2", 395 | "cli-width": "^4.1.0", 396 | "external-editor": "^3.1.0", 397 | "mute-stream": "1.0.0", 398 | "ora": "^5.4.1", 399 | "run-async": "^3.0.0", 400 | "rxjs": "^7.8.1", 401 | "string-width": "^4.2.3", 402 | "strip-ansi": "^6.0.1", 403 | "wrap-ansi": "^6.2.0", 404 | "yoctocolors-cjs": "^2.1.2" 405 | }, 406 | "engines": { 407 | "node": ">=18" 408 | } 409 | }, 410 | "node_modules/is-fullwidth-code-point": { 411 | "version": "3.0.0", 412 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 413 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 414 | "license": "MIT", 415 | "engines": { 416 | "node": ">=8" 417 | } 418 | }, 419 | "node_modules/is-interactive": { 420 | "version": "1.0.0", 421 | "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", 422 | "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", 423 | "license": "MIT", 424 | "engines": { 425 | "node": ">=8" 426 | } 427 | }, 428 | "node_modules/is-unicode-supported": { 429 | "version": "0.1.0", 430 | "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", 431 | "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", 432 | "license": "MIT", 433 | "engines": { 434 | "node": ">=10" 435 | }, 436 | "funding": { 437 | "url": "https://github.com/sponsors/sindresorhus" 438 | } 439 | }, 440 | "node_modules/isarray": { 441 | "version": "1.0.0", 442 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 443 | "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", 444 | "license": "MIT" 445 | }, 446 | "node_modules/jsonfile": { 447 | "version": "6.1.0", 448 | "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", 449 | "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", 450 | "license": "MIT", 451 | "dependencies": { 452 | "universalify": "^2.0.0" 453 | }, 454 | "optionalDependencies": { 455 | "graceful-fs": "^4.1.6" 456 | } 457 | }, 458 | "node_modules/log-symbols": { 459 | "version": "4.1.0", 460 | "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", 461 | "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", 462 | "license": "MIT", 463 | "dependencies": { 464 | "chalk": "^4.1.0", 465 | "is-unicode-supported": "^0.1.0" 466 | }, 467 | "engines": { 468 | "node": ">=10" 469 | }, 470 | "funding": { 471 | "url": "https://github.com/sponsors/sindresorhus" 472 | } 473 | }, 474 | "node_modules/mimic-fn": { 475 | "version": "2.1.0", 476 | "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", 477 | "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", 478 | "license": "MIT", 479 | "engines": { 480 | "node": ">=6" 481 | } 482 | }, 483 | "node_modules/ms": { 484 | "version": "2.1.3", 485 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 486 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", 487 | "license": "MIT" 488 | }, 489 | "node_modules/mute-stream": { 490 | "version": "1.0.0", 491 | "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz", 492 | "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==", 493 | "license": "ISC", 494 | "engines": { 495 | "node": "^14.17.0 || ^16.13.0 || >=18.0.0" 496 | } 497 | }, 498 | "node_modules/node-int64": { 499 | "version": "0.4.0", 500 | "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", 501 | "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", 502 | "license": "MIT" 503 | }, 504 | "node_modules/onetime": { 505 | "version": "5.1.2", 506 | "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", 507 | "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", 508 | "license": "MIT", 509 | "dependencies": { 510 | "mimic-fn": "^2.1.0" 511 | }, 512 | "engines": { 513 | "node": ">=6" 514 | }, 515 | "funding": { 516 | "url": "https://github.com/sponsors/sindresorhus" 517 | } 518 | }, 519 | "node_modules/ora": { 520 | "version": "5.4.1", 521 | "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", 522 | "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", 523 | "license": "MIT", 524 | "dependencies": { 525 | "bl": "^4.1.0", 526 | "chalk": "^4.1.0", 527 | "cli-cursor": "^3.1.0", 528 | "cli-spinners": "^2.5.0", 529 | "is-interactive": "^1.0.0", 530 | "is-unicode-supported": "^0.1.0", 531 | "log-symbols": "^4.1.0", 532 | "strip-ansi": "^6.0.0", 533 | "wcwidth": "^1.0.1" 534 | }, 535 | "engines": { 536 | "node": ">=10" 537 | }, 538 | "funding": { 539 | "url": "https://github.com/sponsors/sindresorhus" 540 | } 541 | }, 542 | "node_modules/os-tmpdir": { 543 | "version": "1.0.2", 544 | "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", 545 | "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", 546 | "license": "MIT", 547 | "engines": { 548 | "node": ">=0.10.0" 549 | } 550 | }, 551 | "node_modules/process-nextick-args": { 552 | "version": "2.0.1", 553 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", 554 | "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", 555 | "license": "MIT" 556 | }, 557 | "node_modules/readable-stream": { 558 | "version": "3.6.2", 559 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", 560 | "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", 561 | "license": "MIT", 562 | "dependencies": { 563 | "inherits": "^2.0.3", 564 | "string_decoder": "^1.1.1", 565 | "util-deprecate": "^1.0.1" 566 | }, 567 | "engines": { 568 | "node": ">= 6" 569 | } 570 | }, 571 | "node_modules/restore-cursor": { 572 | "version": "3.1.0", 573 | "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", 574 | "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", 575 | "license": "MIT", 576 | "dependencies": { 577 | "onetime": "^5.1.0", 578 | "signal-exit": "^3.0.2" 579 | }, 580 | "engines": { 581 | "node": ">=8" 582 | } 583 | }, 584 | "node_modules/run-async": { 585 | "version": "3.0.0", 586 | "resolved": "https://registry.npmjs.org/run-async/-/run-async-3.0.0.tgz", 587 | "integrity": "sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==", 588 | "license": "MIT", 589 | "engines": { 590 | "node": ">=0.12.0" 591 | } 592 | }, 593 | "node_modules/rxjs": { 594 | "version": "7.8.2", 595 | "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", 596 | "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", 597 | "license": "Apache-2.0", 598 | "dependencies": { 599 | "tslib": "^2.1.0" 600 | } 601 | }, 602 | "node_modules/safe-buffer": { 603 | "version": "5.2.1", 604 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 605 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", 606 | "funding": [ 607 | { 608 | "type": "github", 609 | "url": "https://github.com/sponsors/feross" 610 | }, 611 | { 612 | "type": "patreon", 613 | "url": "https://www.patreon.com/feross" 614 | }, 615 | { 616 | "type": "consulting", 617 | "url": "https://feross.org/support" 618 | } 619 | ], 620 | "license": "MIT" 621 | }, 622 | "node_modules/safer-buffer": { 623 | "version": "2.1.2", 624 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 625 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", 626 | "license": "MIT" 627 | }, 628 | "node_modules/signal-exit": { 629 | "version": "3.0.7", 630 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", 631 | "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", 632 | "license": "ISC" 633 | }, 634 | "node_modules/simple-git": { 635 | "version": "3.27.0", 636 | "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-3.27.0.tgz", 637 | "integrity": "sha512-ivHoFS9Yi9GY49ogc6/YAi3Fl9ROnF4VyubNylgCkA+RVqLaKWnDSzXOVzya8csELIaWaYNutsEuAhZrtOjozA==", 638 | "license": "MIT", 639 | "dependencies": { 640 | "@kwsites/file-exists": "^1.1.1", 641 | "@kwsites/promise-deferred": "^1.1.1", 642 | "debug": "^4.3.5" 643 | }, 644 | "funding": { 645 | "type": "github", 646 | "url": "https://github.com/steveukx/git-js?sponsor=1" 647 | } 648 | }, 649 | "node_modules/string_decoder": { 650 | "version": "1.3.0", 651 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", 652 | "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", 653 | "license": "MIT", 654 | "dependencies": { 655 | "safe-buffer": "~5.2.0" 656 | } 657 | }, 658 | "node_modules/string-width": { 659 | "version": "4.2.3", 660 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", 661 | "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", 662 | "license": "MIT", 663 | "dependencies": { 664 | "emoji-regex": "^8.0.0", 665 | "is-fullwidth-code-point": "^3.0.0", 666 | "strip-ansi": "^6.0.1" 667 | }, 668 | "engines": { 669 | "node": ">=8" 670 | } 671 | }, 672 | "node_modules/strip-ansi": { 673 | "version": "6.0.1", 674 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 675 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 676 | "license": "MIT", 677 | "dependencies": { 678 | "ansi-regex": "^5.0.1" 679 | }, 680 | "engines": { 681 | "node": ">=8" 682 | } 683 | }, 684 | "node_modules/supports-color": { 685 | "version": "7.2.0", 686 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", 687 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", 688 | "license": "MIT", 689 | "dependencies": { 690 | "has-flag": "^4.0.0" 691 | }, 692 | "engines": { 693 | "node": ">=8" 694 | } 695 | }, 696 | "node_modules/tmp": { 697 | "version": "0.0.33", 698 | "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", 699 | "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", 700 | "license": "MIT", 701 | "dependencies": { 702 | "os-tmpdir": "~1.0.2" 703 | }, 704 | "engines": { 705 | "node": ">=0.6.0" 706 | } 707 | }, 708 | "node_modules/tslib": { 709 | "version": "2.8.1", 710 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", 711 | "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", 712 | "license": "0BSD" 713 | }, 714 | "node_modules/type-fest": { 715 | "version": "0.21.3", 716 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", 717 | "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", 718 | "license": "(MIT OR CC0-1.0)", 719 | "engines": { 720 | "node": ">=10" 721 | }, 722 | "funding": { 723 | "url": "https://github.com/sponsors/sindresorhus" 724 | } 725 | }, 726 | "node_modules/universalify": { 727 | "version": "2.0.1", 728 | "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", 729 | "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", 730 | "license": "MIT", 731 | "engines": { 732 | "node": ">= 10.0.0" 733 | } 734 | }, 735 | "node_modules/unzipper": { 736 | "version": "0.12.3", 737 | "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.12.3.tgz", 738 | "integrity": "sha512-PZ8hTS+AqcGxsaQntl3IRBw65QrBI6lxzqDEL7IAo/XCEqRTKGfOX56Vea5TH9SZczRVxuzk1re04z/YjuYCJA==", 739 | "license": "MIT", 740 | "dependencies": { 741 | "bluebird": "~3.7.2", 742 | "duplexer2": "~0.1.4", 743 | "fs-extra": "^11.2.0", 744 | "graceful-fs": "^4.2.2", 745 | "node-int64": "^0.4.0" 746 | } 747 | }, 748 | "node_modules/util-deprecate": { 749 | "version": "1.0.2", 750 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 751 | "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", 752 | "license": "MIT" 753 | }, 754 | "node_modules/uuid": { 755 | "version": "9.0.1", 756 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", 757 | "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", 758 | "funding": [ 759 | "https://github.com/sponsors/broofa", 760 | "https://github.com/sponsors/ctavan" 761 | ], 762 | "license": "MIT", 763 | "bin": { 764 | "uuid": "dist/bin/uuid" 765 | } 766 | }, 767 | "node_modules/wcwidth": { 768 | "version": "1.0.1", 769 | "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", 770 | "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", 771 | "license": "MIT", 772 | "dependencies": { 773 | "defaults": "^1.0.3" 774 | } 775 | }, 776 | "node_modules/wrap-ansi": { 777 | "version": "6.2.0", 778 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", 779 | "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", 780 | "license": "MIT", 781 | "dependencies": { 782 | "ansi-styles": "^4.0.0", 783 | "string-width": "^4.1.0", 784 | "strip-ansi": "^6.0.0" 785 | }, 786 | "engines": { 787 | "node": ">=8" 788 | } 789 | }, 790 | "node_modules/yoctocolors-cjs": { 791 | "version": "2.1.2", 792 | "resolved": "https://registry.npmjs.org/yoctocolors-cjs/-/yoctocolors-cjs-2.1.2.tgz", 793 | "integrity": "sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA==", 794 | "license": "MIT", 795 | "engines": { 796 | "node": ">=18" 797 | }, 798 | "funding": { 799 | "url": "https://github.com/sponsors/sindresorhus" 800 | } 801 | } 802 | } 803 | } 804 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "create-mc-bedrock", 3 | "version": "1.3.0", 4 | "description": "create-mc-bedrock is a simple and interactive CLI tool to help you quickly set up Minecraft Bedrock workspaces with given templates from both Microsoft's and Customs!", 5 | "main": "src/cli/index.js", 6 | "bin": { 7 | "create-mc-bedrock": "src/cli/index.js" 8 | }, 9 | "scripts": { 10 | "start": "node src/cli/index.js" 11 | }, 12 | "keywords": [ 13 | "minecraft", 14 | "bedrock", 15 | "cli", 16 | "create" 17 | ], 18 | "author": "keyyard", 19 | "homepage": "https://bedrockcli.keyyard.xyz", 20 | "repository": { 21 | "type": "git", 22 | "url": "https://github.com/keyyard/create-mc-bedrock-cli.git", 23 | "directory": "/" 24 | }, 25 | "bugs": { 26 | "url": "https://github.com/keyyard/create-mc-bedrock-cli/issues" 27 | }, 28 | "engines": { 29 | "node": ">=14" 30 | }, 31 | "files": [ 32 | "src/", 33 | "README.md", 34 | "medias/" 35 | ], 36 | "license": "MIT", 37 | "dependencies": { 38 | "inquirer": "^9.3.7", 39 | "simple-git": "^3.27.0", 40 | "uuid": "^9.0.0" 41 | }, 42 | "type": "module" 43 | } -------------------------------------------------------------------------------- /src/cli/commands.js: -------------------------------------------------------------------------------- 1 | import inquirer from 'inquirer'; 2 | import { getSourceOptions, getCustomCategories, getCustomTemplates } from '../services/gitService.js'; 3 | // Prompt for category if custom source is selected 4 | export async function promptCategory() { 5 | let categories = await getCustomCategories(); 6 | // Filter out categories with no templates 7 | const filteredCategories = []; 8 | for (const cat of categories) { 9 | const templates = await getCustomTemplates(cat.value); 10 | if (templates && templates.length > 0) { 11 | filteredCategories.push(cat); 12 | } 13 | } 14 | if (!filteredCategories.length) { 15 | throw new Error('No categories with templates found in custom templates.'); 16 | } 17 | const { category } = await inquirer.prompt([ 18 | { 19 | type: 'list', 20 | name: 'category', 21 | message: 'Select a template category:', 22 | choices: filteredCategories 23 | } 24 | ]); 25 | return category; 26 | } 27 | 28 | // Prompt for template within a category 29 | export async function promptTemplate(category) { 30 | const templates = await getCustomTemplates(category); 31 | if (!templates.length) { 32 | throw new Error('No templates found in this category.'); 33 | } 34 | const { template } = await inquirer.prompt([ 35 | { 36 | type: 'list', 37 | name: 'template', 38 | message: 'Select a template:', 39 | choices: templates 40 | } 41 | ]); 42 | return template; 43 | } 44 | 45 | export async function promptSource() { 46 | return inquirer.prompt([ 47 | { 48 | type: 'list', 49 | name: 'source', 50 | message: 'Select a template source:', 51 | choices: getSourceOptions() 52 | } 53 | ]); 54 | } 55 | 56 | export async function promptUser(samples) { 57 | return inquirer.prompt([ 58 | { 59 | type: 'list', 60 | name: 'sample', 61 | message: 'Select a sample to clone:', 62 | choices: samples 63 | }, 64 | { 65 | type: 'input', 66 | name: 'destination', 67 | message: 'Enter the destination folder:', 68 | default: './' 69 | } 70 | ]); 71 | } 72 | -------------------------------------------------------------------------------- /src/cli/index.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | import { displayAsciiArt } from '../utils/logger.js'; 3 | import { fetchSamples, getSamples } from '../services/gitService.js'; 4 | import { promptSource, promptUser, promptCategory, promptTemplate } from './commands.js'; 5 | import { moveSample } from '../services/fileService.js'; 6 | import { updateManifestFiles } from '../services/manifestService.js'; 7 | import { cleanupTempFiles } from '../utils/helpers.js'; 8 | import path from 'path'; 9 | import inquirer from 'inquirer'; 10 | 11 | async function run() { 12 | await displayAsciiArt(); 13 | 14 | try { 15 | await cleanupTempFiles(); 16 | const { source } = await promptSource(); 17 | await cleanupTempFiles(); 18 | await fetchSamples(source); 19 | 20 | let sample, destination, samplePath; 21 | if (source === 'custom') { 22 | const category = await promptCategory(); 23 | sample = await promptTemplate(category); 24 | const answers = await inquirer.prompt([ 25 | { 26 | type: 'input', 27 | name: 'destination', 28 | message: 'Enter the destination folder:', 29 | default: './' 30 | } 31 | ]); 32 | destination = answers.destination; 33 | samplePath = path.join('./temp-repo-custom', category, sample); 34 | } else { 35 | const samples = await getSamples(source); 36 | if (samples.length === 0) { 37 | console.error('No samples found in the repository.'); 38 | return; 39 | } 40 | const answers = await promptUser(samples); 41 | sample = answers.sample; 42 | destination = answers.destination; 43 | samplePath = path.join('./temp-repo-microsoft', sample); 44 | } 45 | 46 | const targetPath = path.resolve(destination); 47 | await moveSample(samplePath, targetPath); 48 | 49 | // Update manifest files after moving the sample 50 | const relativePath = path.relative(process.cwd(), targetPath); 51 | await updateManifestFiles(relativePath, destination); 52 | } catch (error) { 53 | console.error(error.message); 54 | } finally { 55 | await cleanupTempFiles(); 56 | } 57 | } 58 | 59 | run(); 60 | -------------------------------------------------------------------------------- /src/services/fileService.js: -------------------------------------------------------------------------------- 1 | import fs, { mkdir } from 'fs/promises'; 2 | import path from 'path'; 3 | 4 | export async function moveSample(samplePath, targetPath, isRoot = true) { 5 | try { 6 | await mkdir(targetPath, { recursive: true }); 7 | const entries = await fs.readdir(samplePath, { withFileTypes: true }); 8 | 9 | for (const entry of entries) { 10 | const sourcePath = path.join(samplePath, entry.name); 11 | const destinationPath = path.join(targetPath, entry.name); 12 | 13 | if (entry.isDirectory()) { 14 | await moveSample(sourcePath, destinationPath, false); 15 | } else { 16 | await fs.copyFile(sourcePath, destinationPath); 17 | } 18 | } 19 | 20 | if (isRoot) { 21 | console.log('Sample workspace generated successfully!'); 22 | console.log(`🎉 Your project is ready! To get started:\n 1. Navigate to your project folder:\n cd ${targetPath}\n 2. Open the project in your code editor:\n code .\n 3. Start building your Minecraft Bedrock project! 🚀`); 23 | } 24 | } catch (error) { 25 | throw new Error(`Error moving sample: ${error.message}`); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/services/gitService.js: -------------------------------------------------------------------------------- 1 | import simpleGit from 'simple-git'; 2 | import fs from 'fs/promises'; 3 | import { cleanupTempFiles } from '../utils/helpers.js'; 4 | import { getTemplateLabel, sortTemplates } from './templateLabels.js'; 5 | 6 | const sources = { 7 | microsoft: { 8 | name: 'Microsoft Official Templates', 9 | repo: 'https://github.com/microsoft/minecraft-scripting-samples.git', 10 | tempRepoPath: './temp-repo-microsoft' 11 | }, 12 | custom: { 13 | name: '⭐ Custom Templates', 14 | repo: 'https://github.com/Keyyard/custom-mc-scripting-templates.git', 15 | tempRepoPath: './temp-repo-custom' 16 | } 17 | }; 18 | export async function fetchSamples(sourceKey) { 19 | const source = sources[sourceKey]; 20 | const git = simpleGit(); 21 | console.log(`Fetching available samples from ${source.name}...`); 22 | await cleanupTempFiles(); 23 | try { 24 | await git.clone(source.repo, source.tempRepoPath, ['--depth', '1']); 25 | } catch (error) { 26 | if (error.message && error.message.includes('spawn git ENOENT')) { 27 | throw new Error('Git is not installed or not found in your PATH. Please install Git from https://git-scm.com/downloads and try again.'); 28 | } 29 | throw new Error(`Error fetching samples: ${error.message}`); 30 | } 31 | } 32 | 33 | /** 34 | * Retrieves a list of available samples from the specified source. 35 | * 36 | * This function reads the contents of the temporary repository directory 37 | * for the given source, filters out non-directory entries and those 38 | * starting with a dot, and maps them into a list of sample objects. 39 | * The samples are sorted to prioritize the 'ts-starter' sample. 40 | * 41 | * @param {string} sourceKey - The key identifying the source repository. 42 | * @returns {Promise>} A promise that resolves 43 | * to an array of sample objects, each containing a name and a value. 44 | */ 45 | 46 | 47 | // New: Get categories for custom templates 48 | export async function getCustomCategories() { 49 | const source = sources.custom; 50 | try { 51 | const entries = await fs.readdir(source.tempRepoPath, { withFileTypes: true }); 52 | return entries 53 | .filter(entry => entry.isDirectory() && !entry.name.startsWith('.')) 54 | .map(entry => ({ 55 | name: formatCategoryName(entry.name), 56 | value: entry.name 57 | })); 58 | } catch (error) { 59 | console.error('Error reading categories:', error.message); 60 | return []; 61 | } 62 | } 63 | 64 | // New: Get templates within a selected custom category 65 | export async function getCustomTemplates(category) { 66 | const source = sources.custom; 67 | const categoryPath = `${source.tempRepoPath}/${category}`; 68 | try { 69 | const entries = await fs.readdir(categoryPath, { withFileTypes: true }); 70 | let templates = entries 71 | .filter(entry => entry.isDirectory() && !entry.name.startsWith('.')) 72 | .map(entry => ({ 73 | name: getTemplateLabel(entry.name), 74 | value: entry.name 75 | })); 76 | templates = templates.sort(sortTemplates); 77 | return templates; 78 | } catch (error) { 79 | console.error('Error reading templates:', error.message); 80 | return []; 81 | } 82 | } 83 | 84 | // Helper to format category names for display 85 | function formatCategoryName(name) { 86 | // Convert kebab-case or snake_case to Title Case 87 | return name 88 | .replace(/[-_]/g, ' ') 89 | .replace(/\b\w/g, l => l.toUpperCase()); 90 | } 91 | 92 | // For Microsoft source, keep the old getSamples behavior 93 | export async function getSamples(sourceKey, category) { 94 | const source = sources[sourceKey]; 95 | if (sourceKey === 'custom' && category) { 96 | return getCustomTemplates(category); 97 | } 98 | try { 99 | const entries = await fs.readdir(source.tempRepoPath, { withFileTypes: true }); 100 | let samples = entries 101 | .filter(entry => entry.isDirectory() && !entry.name.startsWith('.')) 102 | .map(entry => ({ 103 | name: getTemplateLabel(entry.name), 104 | value: entry.name 105 | })); 106 | samples = samples.sort(sortTemplates); 107 | return samples; 108 | } catch (error) { 109 | console.error('Error reading samples:', error.message); 110 | return []; 111 | } 112 | } 113 | 114 | /** 115 | * Returns a list of source options for the user to select from. 116 | * @returns {import('inquirer').ListChoice[]} A list of source options. 117 | */ 118 | export function getSourceOptions() { 119 | return Object.entries(sources).map(([key, source]) => ({ 120 | name: source.name, 121 | value: key 122 | })); 123 | } 124 | -------------------------------------------------------------------------------- /src/services/manifestService.js: -------------------------------------------------------------------------------- 1 | import fs from 'fs/promises'; 2 | import path from 'path'; 3 | import { v4 as uuidv4 } from 'uuid'; 4 | 5 | export async function updateManifestFiles(destination, userInputName) { 6 | const manifestPaths = [ 7 | path.join(destination, 'behavior_packs', 'starter', 'manifest.json'), 8 | path.join(destination, 'resource_packs', 'starter', 'manifest.json') 9 | ]; 10 | 11 | for (const manifestPath of manifestPaths) { 12 | try { 13 | const manifestExists = await fs.access(manifestPath).then(() => true).catch(() => false); 14 | if (!manifestExists) continue; 15 | 16 | const manifestContent = JSON.parse(await fs.readFile(manifestPath, 'utf-8')); 17 | 18 | // Update UUIDs 19 | manifestContent.header.uuid = uuidv4(); 20 | if (manifestContent.modules) { 21 | manifestContent.modules.forEach(module => { 22 | module.uuid = uuidv4(); 23 | module.description = `Generated from npx create-mc-bedrock`; 24 | }); 25 | } 26 | 27 | // Update name and description based on user input and type (RP/BP) 28 | const type = manifestPath.includes('behavior_packs') ? 'BP' : 'RP'; 29 | manifestContent.header.name = `${userInputName} ${type}`; 30 | manifestContent.header.description = `Generated from npx create-mc-bedrock`; 31 | 32 | // Write updated manifest back to file 33 | await fs.writeFile(manifestPath, JSON.stringify(manifestContent, null, 2), 'utf-8'); 34 | } catch (error) { 35 | console.error(`Error updating manifest at ${manifestPath}:`, error.message); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/services/templateLabels.js: -------------------------------------------------------------------------------- 1 | // Template label and priority configuration for custom templates 2 | // Add or edit entries here to control display and ordering 3 | 4 | export const templateLabels = { 5 | 'ts-starter': '⭐ ts-starter', 6 | // Add more mappings here as needed 7 | }; 8 | 9 | export const templatePriority = [ 10 | 'ts-starter', 11 | // Add more template names here for top-priority display 12 | ]; 13 | 14 | export function getTemplateLabel(name) { 15 | return templateLabels[name] || name; 16 | } 17 | 18 | export function sortTemplates(a, b) { 19 | const aIndex = templatePriority.indexOf(a.value); 20 | const bIndex = templatePriority.indexOf(b.value); 21 | if (aIndex !== -1 && bIndex !== -1) return aIndex - bIndex; 22 | if (aIndex !== -1) return -1; 23 | if (bIndex !== -1) return 1; 24 | return a.name.localeCompare(b.name); 25 | } 26 | -------------------------------------------------------------------------------- /src/utils/helpers.js: -------------------------------------------------------------------------------- 1 | import fs from 'fs/promises'; 2 | 3 | export async function cleanupTempFiles() { 4 | try { 5 | await fs.rm('./temp-repo', { recursive: true, force: true }); 6 | await fs.rm('./temp-repo-custom', { recursive: true, force: true }); 7 | } catch (error) { 8 | console.error('Error cleaning up temporary files:', error.message); 9 | } 10 | } -------------------------------------------------------------------------------- /src/utils/logger.js: -------------------------------------------------------------------------------- 1 | export async function displayAsciiArt() { 2 | const artLines = [ 3 | '---', 4 | '', 5 | ' ▄▄· ▄▄▄ ▄▄▄ . ▄▄▄· ▄▄▄▄▄▄▄▄ . ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▄▄▄ ▄▄· ▄ •▄ ▄▄· ▄▄▌ ▪ ', 6 | '▐█ ▌▪▀▄ █·▀▄.▀·▐█ ▀█ •██ ▀▄.▀· ▐█ ▀█▪▀▄.▀·██▪ ██ ▀▄ █·▪ ▐█ ▌▪█▌▄▌▪ ▐█ ▌▪██• ██ ', 7 | '██ ▄▄▐▀▀▄ ▐▀▀▪▄▄█▀▀█ ▐█.▪▐▀▀▪▄ ▐█▀▀█▄▐▀▀▪▄▐█· ▐█▌▐▀▀▄ ▄█▀▄ ██ ▄▄▐▀▀▄· ██ ▄▄██▪ ▐█·', 8 | '▐███▌▐█•█▌▐█▄▄▌▐█ ▪▐▌ ▐█▌·▐█▄▄▌ ██▄▪▐█▐█▄▄▌██. ██ ▐█•█▌▐█▌.▐▌▐███▌▐█.█▌ ▐███▌▐█▌▐▌▐█▌', 9 | '·▀▀▀ .▀ ▀ ▀▀▀ ▀ ▀ ▀▀▀ ▀▀▀ ·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• .▀ ▀ ▀█▄▀▪·▀▀▀ ·▀ ▀ ·▀▀▀ .▀▀▀ ▀▀▀', 10 | '', 11 | '---', 12 | 'by @keyyard - workspaces from Microsoft Minecraft Scripting Samples', 13 | '---', 14 | ]; 15 | 16 | for (const line of artLines) { 17 | console.log(line); 18 | await new Promise(resolve => setTimeout(resolve, 100)); 19 | } 20 | } 21 | --------------------------------------------------------------------------------