create-mcbepack 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,197 @@
1
+ # create-mcbepack
2
+
3
+ Interactive CLI tool for scaffolding MCBEPACK projects
4
+
5
+ [![npm version](https://badge.fury.io/js/create-mcbepack.svg)](https://www.npmjs.com/package/create-mcbepack)
6
+ [![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
7
+
8
+ ## Overview
9
+
10
+ `create-mcbepack` is an interactive command-line tool that facilitates rapid scaffolding of Minecraft Bedrock Edition addon projects with best practices and modern development tooling.
11
+
12
+ ## Features
13
+
14
+ - **Interactive Project Setup** - Guided prompts for project configuration
15
+ - **Multiple Pack Types** - Support for Behavior Packs and Resource Packs
16
+ - **Script API Integration** - Optional Script API setup with package selection
17
+ - **Language Choice** - TypeScript or JavaScript support
18
+ - **Release Channel Selection** - Choose between stable, beta, or preview releases
19
+ - **Auto-generated Configuration** - Automatic manifest, package.json, and tsconfig generation
20
+ - **Project Templates** - Pre-configured templates with best practices
21
+
22
+ ## Usage
23
+
24
+ ### Quick Start
25
+
26
+ ```bash
27
+ bunx create-mcbepack
28
+ ```
29
+
30
+ ### Interactive Prompts
31
+
32
+ The CLI will guide you through the following steps:
33
+
34
+ 1. **Pack Type Selection**
35
+ - Choose between Behavior Pack and/or Resource Pack
36
+
37
+ 2. **Project Information**
38
+ - Project name
39
+ - Description
40
+ - Author name(s)
41
+ - Minimum engine version
42
+
43
+ 3. **Script API Configuration** (if Behavior Pack is selected)
44
+ - Enable/disable Script API
45
+ - Select programming language (TypeScript/JavaScript)
46
+ - Choose game release channel (stable/beta/preview)
47
+ - Select Script API packages to include:
48
+ - `@minecraft/server`
49
+ - `@minecraft/server-ui`
50
+ - `@minecraft/server-net`
51
+ - `@minecraft/server-admin`
52
+ - `@minecraft/server-gametest`
53
+ - `@minecraft/vanilla-data`
54
+ - `@minecraft/math`
55
+
56
+ 4. **Project Preview**
57
+ - Review generated file structure
58
+ - Confirm project creation
59
+
60
+ ### Example
61
+
62
+ ```bash
63
+ $ bunx create-mcbepack
64
+
65
+ Create MCBEPack
66
+
67
+ ? Select a extension type?
68
+ ◉ Behavior Pack
69
+ ◉ Resource Pack
70
+
71
+ ? What is the name of the project? my-awesome-addon
72
+ ? What is the description of the project? An amazing Minecraft addon
73
+ ? What is the author's name? YourName
74
+ ? What is the minimum engine version required? 1.21.0
75
+
76
+ ? Do you want to add a script api to behavior? Yes
77
+ ? Which language do you want to use? typescript
78
+ ? What game type would you like to use? stable
79
+ ? Which packages would you like to add?
80
+ ◉ @minecraft/server
81
+ ◉ @minecraft/server-ui
82
+
83
+ Success! Created project my-awesome-addon
84
+ at: /path/to/my-awesome-addon
85
+
86
+ Next steps:
87
+
88
+ 1. cd my-awesome-addon
89
+ 2. bun install
90
+ 3. bun run dev
91
+
92
+ Available commands:
93
+ • bun run dev - Start development server
94
+ • bun run build:zip - Build project
95
+ • bun run build:mcpack - Build project
96
+ • bun run build:addon - Build project
97
+ ```
98
+
99
+ ## Generated Project Structure
100
+
101
+ ```
102
+ my-awesome-addon/
103
+ ├── scripts/ # TypeScript/JavaScript source files (if Script API enabled)
104
+ │ └── index.ts
105
+ ├── .env.local # Minecraft path configuration
106
+ ├── .gitignore
107
+ ├── package.json
108
+ ├── tsconfig.json # TypeScript configuration (if TypeScript selected)
109
+ ├── pack_icon.png
110
+ └── README.md
111
+ ```
112
+
113
+ ## Configuration Files
114
+
115
+ ### package.json
116
+
117
+ Automatically generated with:
118
+
119
+ - Project metadata
120
+ - Script API dependencies (if enabled)
121
+ - Development scripts
122
+ - Peer dependencies (`@mcbepack/cli`, `@mcbepack/api`)
123
+
124
+ ### tsconfig.json
125
+
126
+ Pre-configured TypeScript settings optimized for Minecraft addon development:
127
+
128
+ - ESNext target
129
+ - Bundler module resolution
130
+ - Source maps disabled for production
131
+
132
+ ### .env.local
133
+
134
+ Minecraft installation paths configuration:
135
+
136
+ ```env
137
+ BASE_PATH="C:\Users\YourName\AppData\Roaming\Minecraft Bedrock\Users\Shared\games\com.mojang"
138
+ RESOURCE_PATH="development_resource_packs"
139
+ BEHAVIOR_PATH="development_behavior_packs"
140
+ ```
141
+
142
+ ## Development
143
+
144
+ ### Building from Source
145
+
146
+ ```bash
147
+ # Clone the repository
148
+ git clone https://github.com/bugphxne/create-mcbepack.git
149
+ cd mcbepack/packages/create-mcbepack
150
+
151
+ # Install dependencies
152
+ bun install
153
+
154
+ # Build
155
+ bun run build
156
+
157
+ # Test locally
158
+ bun run test
159
+ ```
160
+
161
+ ### Project Structure
162
+
163
+ ```
164
+ create-mcbepack/
165
+ ├── src/
166
+ │ ├── index.ts # Main CLI entry point
167
+ │ ├── prompt.ts # Interactive prompts
168
+ │ ├── types.ts # TypeScript type definitions
169
+ │ └── utils/
170
+ │ ├── collect-info.ts # Project information collection
171
+ │ ├── create-files.ts # File generation
172
+ │ └── generate-files.ts # File list generation
173
+ ├── templates/ # Project templates
174
+ │ ├── README.md
175
+ │ ├── tsconfig.json
176
+ │ ├── .env.local
177
+ │ ├── .gitignore
178
+ │ └── pack_icon.png
179
+ └── bin/ # Compiled output
180
+ ```
181
+
182
+ ## Related Packages
183
+
184
+ - [`@mcbepack/cli`](../cli) - Development and build tooling
185
+ - [`@mcbepack/api`](../api) - Utility APIs for Script API
186
+ - [`@mcbepack/common`](../common) - Shared utilities
187
+
188
+ ## License
189
+
190
+ GPL-3.0 - see [LICENSE](./LICENSE) for details
191
+
192
+ ## Resources
193
+
194
+ - [GitHub Repository](https://github.com/bugphxne/create-mcbepack)
195
+ - [npm Package](https://www.npmjs.com/package/create-mcbepack)
196
+ - [Documentation](https://docs.mbext.online/mcbepack)
197
+ - [Issue Tracker](https://github.com/bugphxne/create-mcbepack/issues)
package/out/index.js ADDED
@@ -0,0 +1,60 @@
1
+ #!/usr/bin/env node
2
+ import fs from "node:fs";
3
+ import path from "node:path";
4
+ import pc from "picocolors";
5
+ import { collectProjectInfo } from "./utils/collect-info";
6
+ import { generateFileList } from "./utils/generate-files";
7
+ import { createFiles, previewFiles } from "./utils/create-files";
8
+ import prompt from "./prompt";
9
+ async function main() {
10
+ try {
11
+ console.log(pc.bold(pc.cyan("\nCreate MCBEPack\n")));
12
+ const config = await collectProjectInfo();
13
+ const files = generateFileList(config);
14
+ previewFiles(files, config.name);
15
+ console.log();
16
+ const { confirmed } = await prompt.confirm({
17
+ message: "Do you want to create this project?",
18
+ default: true,
19
+ });
20
+ if (!confirmed) {
21
+ console.log(pc.yellow("\nProject creation cancelled"));
22
+ process.exit(0);
23
+ }
24
+ const projectRoot = path.join(process.cwd(), config.name);
25
+ if (fs.existsSync(projectRoot)) {
26
+ console.log(pc.red(`\nDirectory ${config.name} already exists`));
27
+ process.exit(1);
28
+ }
29
+ createFiles(files);
30
+ console.log(`\n${pc.green("Success!")} Created project ${pc.cyan(config.name)}`);
31
+ console.log(pc.dim(` at: ${projectRoot}\n`));
32
+ console.log(pc.bold("Next steps:\n"));
33
+ console.log(` ${pc.cyan("1.")} cd ${config.name}`);
34
+ if (config.script?.enabled) {
35
+ console.log(` ${pc.cyan("2.")} bun install`);
36
+ console.log(` ${pc.cyan("3.")} bun run dev\n`);
37
+ }
38
+ else {
39
+ console.log(` ${pc.cyan("2.")} Start developing your project\n`);
40
+ }
41
+ if (config.script?.enabled) {
42
+ console.log(pc.dim("Available commands:"));
43
+ console.log(pc.dim(" • bun run dev - Start development server"));
44
+ console.log(pc.dim(" • bun run build:zip - Build project"));
45
+ console.log(pc.dim(" • bun run build:mcpack - Build project"));
46
+ console.log(pc.dim(" • bun run build:addon - Build project"));
47
+ }
48
+ else {
49
+ console.log(pc.dim("Available commands:"));
50
+ console.log(pc.dim(" • bun run build:zip - Build project"));
51
+ console.log(pc.dim(" • bun run build:mcpack - Build project"));
52
+ console.log(pc.dim(" • bun run build:addon - Build project"));
53
+ }
54
+ }
55
+ catch (error) {
56
+ console.error(pc.red("\nError occurred:"), error);
57
+ process.exit(1);
58
+ }
59
+ }
60
+ main();
package/out/prompt.js ADDED
@@ -0,0 +1,92 @@
1
+ import enquirer from 'enquirer';
2
+ import { constants } from '@mcbepack/common';
3
+ const extension = async () => {
4
+ const response = await enquirer.prompt({
5
+ type: 'multiselect',
6
+ name: 'extensions',
7
+ message: 'Select a extension type?',
8
+ choices: [
9
+ { name: 'behavior', message: 'Behavior Pack' },
10
+ { name: 'resource', message: 'Resource Pack' },
11
+ ]
12
+ });
13
+ return response;
14
+ };
15
+ const api = async () => {
16
+ const response = await enquirer.prompt({
17
+ type: "confirm",
18
+ name: "api",
19
+ message: "Do you want to add a script api to behavior?",
20
+ initial: true
21
+ });
22
+ return response;
23
+ };
24
+ const info = async () => {
25
+ const response = await enquirer.prompt([
26
+ {
27
+ type: 'input',
28
+ name: 'name',
29
+ message: 'What is the name of the project?',
30
+ },
31
+ {
32
+ type: 'input',
33
+ name: 'description',
34
+ message: 'What is the description of the project?',
35
+ },
36
+ {
37
+ type: 'input',
38
+ name: 'author',
39
+ message: 'What is the author\'s name? Use commas to separate multiple authors(,).',
40
+ },
41
+ {
42
+ type: 'input',
43
+ name: 'minimumEngineVersion',
44
+ message: 'What is the minimum engine version required?',
45
+ validate: input => {
46
+ if (input.length === 0)
47
+ return 'Minimum engine version is required';
48
+ const version = input.split('.');
49
+ const response = 'Minimum engine version must be in the format x.x.x';
50
+ return version.every((v) => !isNaN(parseInt(v))) || response;
51
+ }
52
+ }
53
+ ]);
54
+ return response;
55
+ };
56
+ const script = async () => {
57
+ const response = await enquirer.prompt([
58
+ {
59
+ type: 'select',
60
+ name: 'language',
61
+ message: 'Which language do you want to use?',
62
+ choices: ['typescript', 'javascript']
63
+ },
64
+ {
65
+ type: 'select',
66
+ name: 'release',
67
+ message: 'What game type would you like to use?',
68
+ choices: ['stable', 'beta', 'preview'],
69
+ },
70
+ {
71
+ type: 'multiselect',
72
+ name: 'packages',
73
+ message: 'Which packages would you like to add?',
74
+ choices: [
75
+ ...constants.packages.modules,
76
+ ...constants.packages.plugins
77
+ ],
78
+ validate: input => input.length > 0 || 'At least one package is required'
79
+ }
80
+ ]);
81
+ return response;
82
+ };
83
+ const confirm = async (options) => {
84
+ const response = await enquirer.prompt({
85
+ type: "confirm",
86
+ name: "confirmed",
87
+ message: options.message,
88
+ initial: options.default ?? true
89
+ });
90
+ return response;
91
+ };
92
+ export default { extension, api, info, script, confirm };
package/out/types.js ADDED
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,54 @@
1
+ import { v4 as uuidv4 } from "uuid";
2
+ import pc from "picocolors";
3
+ import { getDependency } from "@mcbepack/common";
4
+ import prompt from "../prompt";
5
+ export async function collectProjectInfo() {
6
+ console.log(pc.bold("Please provide project information\n"));
7
+ const { extensions } = await prompt.extension();
8
+ const { name, description, author, minimumEngineVersion } = await prompt.info();
9
+ const uuids = {
10
+ behavior: uuidv4(),
11
+ resource: uuidv4(),
12
+ scriptModule: uuidv4(),
13
+ };
14
+ const config = {
15
+ name,
16
+ description,
17
+ author,
18
+ minimumEngineVersion,
19
+ extensions,
20
+ uuids,
21
+ };
22
+ if (extensions.includes("behavior")) {
23
+ const { api } = await prompt.api();
24
+ if (api) {
25
+ const { language, release, packages } = await prompt.script();
26
+ console.log(pc.dim("\nFetching dependencies..."));
27
+ const dependencies = await Promise.all(packages.map(async (packageName) => {
28
+ const dep = await getDependency(packageName, release);
29
+ return {
30
+ packageName: dep.packageName,
31
+ version: dep.version,
32
+ fullVersion: dep.fullVersion,
33
+ };
34
+ }));
35
+ config.script = {
36
+ enabled: true,
37
+ language,
38
+ release,
39
+ packages,
40
+ dependencies,
41
+ };
42
+ }
43
+ else {
44
+ config.script = {
45
+ enabled: false,
46
+ language: "javascript",
47
+ release: "",
48
+ packages: [],
49
+ dependencies: [],
50
+ };
51
+ }
52
+ }
53
+ return config;
54
+ }
@@ -0,0 +1,77 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import pc from "picocolors";
4
+ export function createFiles(files) {
5
+ console.log(`\nCreating ${files.length} files...\n`);
6
+ for (const file of files) {
7
+ try {
8
+ const dir = path.dirname(file.path);
9
+ if (!fs.existsSync(dir)) {
10
+ fs.mkdirSync(dir, { recursive: true });
11
+ }
12
+ if (file.type === "copy" && file.source) {
13
+ fs.copyFileSync(file.source, file.path);
14
+ }
15
+ else {
16
+ fs.writeFileSync(file.path, file.content);
17
+ }
18
+ console.log(` ${pc.green("✓")} ${path.relative(process.cwd(), file.path)}`);
19
+ }
20
+ catch (error) {
21
+ console.error(` ${pc.red("✗")} ${path.relative(process.cwd(), file.path)}`);
22
+ throw error;
23
+ }
24
+ }
25
+ }
26
+ export function previewFiles(files, projectName) {
27
+ console.log(`\nFiles to be created in ${pc.cyan(projectName)}:\n`);
28
+ const projectRoot = path.join(process.cwd(), projectName);
29
+ const tree = buildFileTree(files, projectRoot);
30
+ printTree(tree);
31
+ }
32
+ function buildFileTree(files, projectRoot) {
33
+ const root = {
34
+ name: path.basename(projectRoot),
35
+ type: "directory",
36
+ children: new Map(),
37
+ };
38
+ for (const file of files) {
39
+ const relativePath = path.relative(projectRoot, file.path);
40
+ const parts = relativePath.split(path.sep);
41
+ let current = root;
42
+ for (let i = 0; i < parts.length; i++) {
43
+ const part = parts[i];
44
+ const isLast = i === parts.length - 1;
45
+ if (!current.children) {
46
+ current.children = new Map();
47
+ }
48
+ if (!current.children.has(part)) {
49
+ current.children.set(part, {
50
+ name: part,
51
+ type: isLast ? "file" : "directory",
52
+ children: isLast ? undefined : new Map(),
53
+ });
54
+ }
55
+ current = current.children.get(part);
56
+ }
57
+ }
58
+ return root;
59
+ }
60
+ function printTree(node, prefix = "", isLast = true) {
61
+ const connector = isLast ? "└── " : "├── ";
62
+ if (prefix === "") {
63
+ console.log(` ${pc.cyan(node.name)}/`);
64
+ }
65
+ else {
66
+ const displayName = node.type === "directory" ? `${pc.cyan(node.name)}/` : node.name;
67
+ console.log(` ${prefix}${connector}${displayName}`);
68
+ }
69
+ if (node.children) {
70
+ const children = Array.from(node.children.values());
71
+ children.forEach((child, index) => {
72
+ const isLastChild = index === children.length - 1;
73
+ const newPrefix = prefix + (isLast ? " " : "│ ");
74
+ printTree(child, newPrefix, isLastChild);
75
+ });
76
+ }
77
+ }
@@ -0,0 +1,191 @@
1
+ import path from "node:path";
2
+ import { fileURLToPath } from "node:url";
3
+ import { constants } from "@mcbepack/common";
4
+ const __filename = fileURLToPath(import.meta.url);
5
+ const __dirname = path.dirname(__filename);
6
+ export function generateFileList(config) {
7
+ const files = [];
8
+ const projectRoot = path.join(process.cwd(), config.name);
9
+ const templatesDir = path.join(__dirname, "..", "..", "templates");
10
+ const baseManifest = {
11
+ format_version: 2,
12
+ header: {
13
+ name: config.name,
14
+ description: config.description,
15
+ uuid: "",
16
+ version: [1, 0, 0],
17
+ min_engine_version: config.minimumEngineVersion.split('.').map(Number),
18
+ },
19
+ metadata: {
20
+ authors: config.author.split(',').map(a => a.trim()),
21
+ generated_with: {
22
+ "create-mcbepack": [1, 0, 0],
23
+ },
24
+ },
25
+ };
26
+ files.push({
27
+ path: path.join(projectRoot, "README.md"),
28
+ content: "",
29
+ type: "copy",
30
+ source: path.join(templatesDir, "README.md"),
31
+ });
32
+ if (config.extensions.includes("behavior")) {
33
+ const bpRoot = path.join(projectRoot, "src", "behavior_pack");
34
+ files.push({
35
+ path: path.join(bpRoot, "pack_icon.png"),
36
+ content: "",
37
+ type: "copy",
38
+ source: path.join(templatesDir, "pack_icon.png"),
39
+ });
40
+ const bpManifest = {
41
+ ...baseManifest,
42
+ header: {
43
+ ...baseManifest.header,
44
+ uuid: config.uuids.behavior,
45
+ },
46
+ capabilities: ['script_eval'],
47
+ modules: [],
48
+ dependencies: [],
49
+ };
50
+ if (config.script?.enabled) {
51
+ bpManifest.modules = [
52
+ {
53
+ type: "script",
54
+ language: "javascript",
55
+ entry: "scripts/index.js",
56
+ uuid: config.uuids.scriptModule,
57
+ version: [1, 0, 0],
58
+ },
59
+ ];
60
+ bpManifest.dependencies = [
61
+ ...config.script.dependencies
62
+ .filter(dep => !constants.packages.plugins.includes(dep.packageName))
63
+ .map(dep => ({
64
+ module_name: dep.packageName,
65
+ version: dep.version,
66
+ })),
67
+ ];
68
+ if (config.extensions.includes("resource")) {
69
+ bpManifest.dependencies.push({
70
+ uuid: config.uuids.resource,
71
+ version: [1, 0, 0],
72
+ });
73
+ }
74
+ files.push({
75
+ path: path.join(projectRoot, ".env.local"),
76
+ content: "",
77
+ type: "copy",
78
+ source: path.join(templatesDir, ".env.local"),
79
+ });
80
+ files.push({
81
+ path: path.join(projectRoot, ".gitignore"),
82
+ content: "",
83
+ type: "copy",
84
+ source: path.join(templatesDir, ".gitignore"),
85
+ });
86
+ const packageJson = {
87
+ name: config.name,
88
+ scripts: {
89
+ dev: "mcbepack dev",
90
+ "build:zip": "mcbepack build -o zip",
91
+ "build:mcpack": "mcbepack build -o mcpack",
92
+ "build:addon": "mcbepack build -o addon",
93
+ "update:stable": "mcbepack update -o stable",
94
+ "update:beta": "mcbepack update -o beta",
95
+ "update:preview": "mcbepack update -o preview",
96
+ },
97
+ devDependencies: Object.fromEntries(config.script.dependencies.map(dep => [dep.packageName, dep.fullVersion])),
98
+ peerDependencies: {
99
+ "@mcbepack/cli": "latest",
100
+ "@mcbepack/api": "latest",
101
+ ...(config.script.language === "typescript" ? { "typescript": "latest" } : {})
102
+ }
103
+ };
104
+ files.push({
105
+ path: path.join(projectRoot, "package.json"),
106
+ content: JSON.stringify(packageJson, null, 2),
107
+ type: "file",
108
+ });
109
+ const scriptsDir = path.join(projectRoot, "scripts");
110
+ if (config.script.language === "typescript") {
111
+ files.push({
112
+ path: path.join(scriptsDir, "index.ts"),
113
+ content: "console.log('Hello World!');",
114
+ type: "file",
115
+ });
116
+ files.push({
117
+ path: path.join(projectRoot, "tsconfig.json"),
118
+ content: "",
119
+ type: "copy",
120
+ source: path.join(templatesDir, "tsconfig.json"),
121
+ });
122
+ }
123
+ else {
124
+ files.push({
125
+ path: path.join(scriptsDir, "index.js"),
126
+ content: "console.log('Hello World!');",
127
+ type: "file",
128
+ });
129
+ }
130
+ }
131
+ files.push({
132
+ path: path.join(bpRoot, "manifest.json"),
133
+ content: JSON.stringify(bpManifest, null, 2),
134
+ type: "file",
135
+ });
136
+ }
137
+ if (config.extensions.includes("resource")) {
138
+ const rpRoot = path.join(projectRoot, "src", "resource_pack");
139
+ files.push({
140
+ path: path.join(rpRoot, "pack_icon.png"),
141
+ content: "",
142
+ type: "copy",
143
+ source: path.join(templatesDir, "pack_icon.png"),
144
+ });
145
+ const rpManifest = {
146
+ ...baseManifest,
147
+ header: {
148
+ ...baseManifest.header,
149
+ uuid: config.uuids.resource,
150
+ },
151
+ modules: [
152
+ {
153
+ type: "resources",
154
+ uuid: config.uuids.resource,
155
+ version: [1, 0, 0],
156
+ },
157
+ ],
158
+ dependencies: [],
159
+ };
160
+ if (config.extensions.includes("behavior")) {
161
+ rpManifest.dependencies = [
162
+ {
163
+ uuid: config.uuids.behavior,
164
+ version: [1, 0, 0],
165
+ }
166
+ ];
167
+ }
168
+ files.push({
169
+ path: path.join(rpRoot, "manifest.json"),
170
+ content: JSON.stringify(rpManifest, null, 2),
171
+ type: "file",
172
+ });
173
+ }
174
+ if (!config.script?.enabled) {
175
+ files.push({
176
+ path: path.join(projectRoot, "package.json"),
177
+ content: JSON.stringify({
178
+ scripts: {
179
+ "build:zip": "mcbepack build -o zip",
180
+ "build:mcpack": "mcbepack build -o mcpack",
181
+ "build:addon": "mcbepack build -o addon",
182
+ },
183
+ peerDependencies: {
184
+ "@mcbepack/cli": "latest"
185
+ }
186
+ }, null, 2),
187
+ type: "file",
188
+ });
189
+ }
190
+ return files;
191
+ }