├── .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 | [](https://github.com/keyyard/create-mc-bedrock-cli)
6 | [](https://github.com/keyyard/create-mc-bedrock-cli)
7 | [](https://nodejs.org/)
8 | [](LICENSE)
9 |
10 | [](https://bedrockcli.keyyard.xyz/)
11 |
12 |
13 |
14 |
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 |
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 |
132 |
133 |
134 |
135 |
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 |
--------------------------------------------------------------------------------