@mafly/bdev-cli 0.0.0-stage → 0.1.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.
@@ -0,0 +1,164 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { generateManifests } from "../utils/manifest.js";
4
+ import { saveConfig } from "../utils/config.js";
5
+ import { logger } from "../utils/logger.js";
6
+ const DEFAULT_ICON_BASE64 = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==";
7
+ export async function initCommand(targetDirArg, options) {
8
+ const targetDir = path.resolve(targetDirArg || ".");
9
+ const projectName = options.name || path.basename(targetDir) || "my-bedrock-addon";
10
+ const projectDesc = options.desc || `${projectName} - Bedrock Addon created with bdev`;
11
+ const isTs = options.lang !== "js";
12
+ const hasRp = options.rp !== false;
13
+ logger.info(`Scaffolding Bedrock Addon project: ${projectName}`);
14
+ logger.info(`Directory: ${targetDir}`);
15
+ logger.info(`Language: ${isTs ? "TypeScript" : "JavaScript"} | Resource Pack: ${hasRp ? "Yes" : "No"}`);
16
+ if (!fs.existsSync(targetDir)) {
17
+ fs.mkdirSync(targetDir, { recursive: true });
18
+ }
19
+ const { bpManifest, rpManifest } = generateManifests({
20
+ name: projectName,
21
+ description: projectDesc,
22
+ hasScript: true,
23
+ hasRp,
24
+ minEngineVersion: [1, 21, 0],
25
+ serverVersion: "1.16.0",
26
+ });
27
+ // 1. Behavior Pack
28
+ const bpDir = path.join(targetDir, "behavior_pack");
29
+ fs.mkdirSync(bpDir, { recursive: true });
30
+ fs.writeFileSync(path.join(bpDir, "manifest.json"), JSON.stringify(bpManifest, null, 2) + "\n");
31
+ fs.writeFileSync(path.join(bpDir, "pack_icon.png"), Buffer.from(DEFAULT_ICON_BASE64, "base64"));
32
+ // 2. Resource Pack (if enabled)
33
+ if (hasRp && rpManifest) {
34
+ const rpDir = path.join(targetDir, "resource_pack");
35
+ fs.mkdirSync(rpDir, { recursive: true });
36
+ fs.writeFileSync(path.join(rpDir, "manifest.json"), JSON.stringify(rpManifest, null, 2) + "\n");
37
+ fs.writeFileSync(path.join(rpDir, "pack_icon.png"), Buffer.from(DEFAULT_ICON_BASE64, "base64"));
38
+ const textsDir = path.join(rpDir, "texts");
39
+ fs.mkdirSync(textsDir, { recursive: true });
40
+ fs.writeFileSync(path.join(textsDir, "en_US.lang"), `pack.name=${projectName}\npack.description=${projectDesc}\n`);
41
+ }
42
+ // 3. Scripts / Source code
43
+ const starterCode = `import { world, system } from "@minecraft/server";
44
+
45
+ world.afterEvents.worldInitialize.subscribe(() => {
46
+ world.sendMessage("Hello from ${projectName}!");
47
+ });
48
+
49
+ let ticks = 0;
50
+ system.runInterval(() => {
51
+ ticks++;
52
+ if (ticks % 100 === 0) {
53
+ // Periodic tick logic
54
+ }
55
+ }, 20);
56
+ `;
57
+ if (isTs) {
58
+ const srcDir = path.join(targetDir, "src");
59
+ fs.mkdirSync(srcDir, { recursive: true });
60
+ fs.writeFileSync(path.join(srcDir, "main.ts"), starterCode);
61
+ // tsconfig.json
62
+ const tsconfig = {
63
+ compilerOptions: {
64
+ target: "ES2020",
65
+ module: "ESNext",
66
+ moduleResolution: "Bundler",
67
+ strict: true,
68
+ skipLibCheck: true,
69
+ noEmit: true,
70
+ },
71
+ include: ["src/**/*"],
72
+ };
73
+ fs.writeFileSync(path.join(targetDir, "tsconfig.json"), JSON.stringify(tsconfig, null, 2) + "\n");
74
+ }
75
+ else {
76
+ const scriptsDir = path.join(bpDir, "scripts");
77
+ fs.mkdirSync(scriptsDir, { recursive: true });
78
+ fs.writeFileSync(path.join(scriptsDir, "main.js"), starterCode);
79
+ }
80
+ // 4. package.json
81
+ const pkgJson = {
82
+ name: projectName.toLowerCase().replace(/[^a-z0-9-_]/g, "-"),
83
+ version: "1.0.0",
84
+ description: projectDesc,
85
+ type: "module",
86
+ scripts: {
87
+ build: "bdev build",
88
+ dev: "bdev dev",
89
+ package: "bdev package",
90
+ },
91
+ dependencies: {
92
+ "@minecraft/server": "1.16.0",
93
+ "@minecraft/server-ui": "1.7.0",
94
+ },
95
+ };
96
+ if (isTs) {
97
+ pkgJson.devDependencies = {
98
+ "@types/node": "^22.0.0",
99
+ typescript: "^5.0.0",
100
+ };
101
+ }
102
+ fs.writeFileSync(path.join(targetDir, "package.json"), JSON.stringify(pkgJson, null, 2) + "\n");
103
+ // 5. bdev.json config
104
+ saveConfig({
105
+ name: projectName,
106
+ mojangPath: options.path ? path.resolve(options.path) : undefined,
107
+ }, { dir: targetDir });
108
+ // 6. Comprehensive .gitignore
109
+ const gitignoreLines = [
110
+ "# Dependencies",
111
+ "node_modules/",
112
+ "",
113
+ "# Build outputs",
114
+ "dist/",
115
+ ];
116
+ if (isTs) {
117
+ gitignoreLines.push("behavior_pack/scripts/");
118
+ }
119
+ gitignoreLines.push("", "# bdev cache & local configs", ".bdev/", "*.local.json", "", "# Logs", "*.log", "npm-debug.log*", "yarn-debug.log*", "yarn-error.log*", "", "# OS files", ".DS_Store", ".DS_Store?", "._*", ".Spotlight-V100", ".Trashes", "ehthumbs.db", "Thumbs.db", "", "# Editor files", ".vscode/", ".idea/");
120
+ fs.writeFileSync(path.join(targetDir, ".gitignore"), gitignoreLines.join("\n") + "\n");
121
+ // 7. README.md
122
+ const readmeContent = `# ${projectName}
123
+
124
+ ${projectDesc}
125
+
126
+ ## Development
127
+
128
+ Run development watcher (auto builds, symlinks, and starts WebSocket hot reload):
129
+ \`\`\`bash
130
+ bdev dev
131
+ \`\`\`
132
+
133
+ In your Minecraft world (cheats enabled), connect the game to bdev hot reload:
134
+ \`\`\`
135
+ /connect localhost:8000
136
+ \`\`\`
137
+ Whenever you save script files, bdev will automatically execute \`/reload\` in game.
138
+
139
+ To configure your \`com.mojang\` Bedrock directory:
140
+ \`\`\`bash
141
+ bdev set-path "C:\\path\\to\\com.mojang"
142
+ # or
143
+ bdev dev -p "C:\\path\\to\\com.mojang"
144
+ \`\`\`
145
+
146
+ ## Build & Package
147
+
148
+ Compile scripts and validate manifest:
149
+ \`\`\`bash
150
+ bdev build
151
+ \`\`\`
152
+
153
+ Bundle into \`.mcaddon\` and \`.mcpack\` for distribution:
154
+ \`\`\`bash
155
+ bdev package
156
+ \`\`\`
157
+ `;
158
+ fs.writeFileSync(path.join(targetDir, "README.md"), readmeContent);
159
+ logger.success(`Project initialized successfully at ${targetDir}`);
160
+ if (options.path) {
161
+ logger.success(`Configured com.mojang path: ${path.resolve(options.path)}`);
162
+ }
163
+ logger.info("Run: cd " + (targetDirArg || ".") + " && bdev dev");
164
+ }
@@ -0,0 +1,5 @@
1
+ export interface PackageOptions {
2
+ output?: string;
3
+ name?: string;
4
+ }
5
+ export declare function packageCommand(dirArg?: string, options?: PackageOptions): Promise<void>;
@@ -0,0 +1,103 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import archiver from "archiver";
4
+ import { buildCommand } from "./build.js";
5
+ import { logger } from "../utils/logger.js";
6
+ function archiveDirectory(sourceDir, destZipPath, prefix = "") {
7
+ return new Promise((resolve, reject) => {
8
+ const output = fs.createWriteStream(destZipPath);
9
+ const archive = archiver("zip", { zlib: { level: 9 } });
10
+ output.on("close", () => {
11
+ resolve(archive.pointer());
12
+ });
13
+ archive.on("error", (err) => {
14
+ reject(err);
15
+ });
16
+ archive.pipe(output);
17
+ archive.directory(sourceDir, prefix || false);
18
+ archive.finalize();
19
+ });
20
+ }
21
+ function archiveMultiple(entries, destZipPath) {
22
+ return new Promise((resolve, reject) => {
23
+ const output = fs.createWriteStream(destZipPath);
24
+ const archive = archiver("zip", { zlib: { level: 9 } });
25
+ output.on("close", () => {
26
+ resolve(archive.pointer());
27
+ });
28
+ archive.on("error", (err) => {
29
+ reject(err);
30
+ });
31
+ archive.pipe(output);
32
+ for (const entry of entries) {
33
+ archive.directory(entry.dir, entry.prefix);
34
+ }
35
+ archive.finalize();
36
+ });
37
+ }
38
+ function formatBytes(bytes) {
39
+ if (bytes < 1024)
40
+ return `${bytes} B`;
41
+ if (bytes < 1024 * 1024)
42
+ return `${(bytes / 1024).toFixed(1)} KB`;
43
+ return `${(bytes / (1024 * 1024)).toFixed(2)} MB`;
44
+ }
45
+ export async function packageCommand(dirArg, options = {}) {
46
+ const rootDir = path.resolve(dirArg || ".");
47
+ const bpDir = path.join(rootDir, "behavior_pack");
48
+ const rpDir = path.join(rootDir, "resource_pack");
49
+ const hasBp = fs.existsSync(bpDir);
50
+ const hasRp = fs.existsSync(rpDir);
51
+ if (!hasBp && !hasRp) {
52
+ logger.error(`No behavior_pack or resource_pack found in ${rootDir}.`);
53
+ process.exit(1);
54
+ }
55
+ logger.info("Building project before packaging...");
56
+ const buildOk = await buildCommand(rootDir);
57
+ if (!buildOk) {
58
+ logger.error("Build failed. Aborting package.");
59
+ process.exit(1);
60
+ }
61
+ const outDir = options.output
62
+ ? path.resolve(rootDir, options.output)
63
+ : path.join(rootDir, "dist");
64
+ if (!fs.existsSync(outDir)) {
65
+ fs.mkdirSync(outDir, { recursive: true });
66
+ }
67
+ const baseName = options.name || path.basename(rootDir);
68
+ const spinner = logger.spinner("Packaging Bedrock Addon...");
69
+ try {
70
+ const generatedFiles = [];
71
+ // Package BP if present
72
+ if (hasBp) {
73
+ const bpZipPath = path.join(outDir, `${baseName}_BP.mcpack`);
74
+ const size = await archiveDirectory(bpDir, bpZipPath);
75
+ generatedFiles.push({ path: bpZipPath, size });
76
+ }
77
+ // Package RP if present
78
+ if (hasRp) {
79
+ const rpZipPath = path.join(outDir, `${baseName}_RP.mcpack`);
80
+ const size = await archiveDirectory(rpDir, rpZipPath);
81
+ generatedFiles.push({ path: rpZipPath, size });
82
+ }
83
+ // If both exist, package into .mcaddon
84
+ if (hasBp && hasRp) {
85
+ const mcaddonPath = path.join(outDir, `${baseName}.mcaddon`);
86
+ const size = await archiveMultiple([
87
+ { dir: bpDir, prefix: `${baseName}_BP` },
88
+ { dir: rpDir, prefix: `${baseName}_RP` },
89
+ ], mcaddonPath);
90
+ generatedFiles.push({ path: mcaddonPath, size });
91
+ }
92
+ spinner.succeed("Packaging complete!");
93
+ logger.info("Generated distribution packages:");
94
+ for (const f of generatedFiles) {
95
+ logger.success(` ${path.relative(rootDir, f.path)} (${formatBytes(f.size)})`);
96
+ }
97
+ }
98
+ catch (err) {
99
+ spinner.fail("Packaging failed");
100
+ logger.error(err.message);
101
+ process.exit(1);
102
+ }
103
+ }
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,148 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from "commander";
3
+ import { initCommand } from "./commands/init.js";
4
+ import { buildCommand } from "./commands/build.js";
5
+ import { devCommand } from "./commands/dev.js";
6
+ import { packageCommand } from "./commands/package.js";
7
+ import { doctorCommand } from "./commands/doctor.js";
8
+ import { setConfigCommand, getConfigCommand, setPathCommand, } from "./commands/config.js";
9
+ const program = new Command();
10
+ program
11
+ .name("bdev")
12
+ .description("Modern CLI tool for Minecraft Bedrock Edition Addon development")
13
+ .version("0.1.0");
14
+ program
15
+ .command("init [directory]")
16
+ .description("Scaffold a new Bedrock addon project")
17
+ .option("-n, --name <name>", "Project / pack name")
18
+ .option("-d, --desc <description>", "Pack description")
19
+ .option("-p, --path <path>", "Custom com.mojang path to save in bdev.json")
20
+ .option("--no-rp", "Scaffold Behavior Pack only (skip Resource Pack)")
21
+ .option("--lang <lang>", "Script language: ts or js", "ts")
22
+ .action(async (directory, options) => {
23
+ try {
24
+ await initCommand(directory, options);
25
+ }
26
+ catch (err) {
27
+ console.error(err.message);
28
+ process.exit(1);
29
+ }
30
+ });
31
+ program
32
+ .command("build [directory]")
33
+ .description("Compile TypeScript scripts and validate manifests")
34
+ .option("-m, --minify", "Minify bundled JavaScript")
35
+ .option("--no-sourcemap", "Disable sourcemap generation")
36
+ .action(async (directory, options) => {
37
+ try {
38
+ const ok = await buildCommand(directory, options);
39
+ if (!ok)
40
+ process.exit(1);
41
+ }
42
+ catch (err) {
43
+ console.error(err.message);
44
+ process.exit(1);
45
+ }
46
+ });
47
+ program
48
+ .command("dev [directory]")
49
+ .description("Symlink packs to com.mojang, start hot-reload WebSocket, and watch for changes")
50
+ .option("-p, --path <path>", "Custom com.mojang directory path")
51
+ .option("-s, --save", "Save custom path to bdev.json for future use")
52
+ .option("-P, --port <port>", "WebSocket server port for Minecraft hot reload", "8000")
53
+ .option("--no-ws", "Disable WebSocket hot reload server")
54
+ .option("--no-link", "Skip creating symlinks to development directories")
55
+ .action(async (directory, options) => {
56
+ try {
57
+ await devCommand(directory, options);
58
+ }
59
+ catch (err) {
60
+ console.error(err.message);
61
+ process.exit(1);
62
+ }
63
+ });
64
+ program
65
+ .command("package [directory]")
66
+ .alias("deploy")
67
+ .description("Build and compress packs into .mcaddon and .mcpack files")
68
+ .option("-o, --output <dir>", "Output directory for packages", "dist")
69
+ .option("-n, --name <name>", "Package file name prefix")
70
+ .action(async (directory, options) => {
71
+ try {
72
+ await packageCommand(directory, options);
73
+ }
74
+ catch (err) {
75
+ console.error(err.message);
76
+ process.exit(1);
77
+ }
78
+ });
79
+ program
80
+ .command("set-path <path>")
81
+ .alias("path")
82
+ .description("Set com.mojang Bedrock path in configuration")
83
+ .option("-g, --global", "Save path globally in ~/.bdev/config.json")
84
+ .action(async (pathInput, options) => {
85
+ try {
86
+ await setPathCommand(pathInput, options);
87
+ }
88
+ catch (err) {
89
+ console.error(err.message);
90
+ process.exit(1);
91
+ }
92
+ });
93
+ const configCmd = program
94
+ .command("config")
95
+ .description("Manage bdev configuration");
96
+ configCmd
97
+ .command("set <key> <value>")
98
+ .description("Set configuration key (e.g. mojangPath /path/to/com.mojang)")
99
+ .option("-g, --global", "Set globally in ~/.bdev/config.json")
100
+ .action(async (key, value, options) => {
101
+ try {
102
+ await setConfigCommand(key, value, options);
103
+ }
104
+ catch (err) {
105
+ console.error(err.message);
106
+ process.exit(1);
107
+ }
108
+ });
109
+ configCmd
110
+ .command("get [key]")
111
+ .description("Get configuration key or list all")
112
+ .option("-g, --global", "Get from ~/.bdev/config.json only")
113
+ .action(async (key, options) => {
114
+ try {
115
+ await getConfigCommand(key, options);
116
+ }
117
+ catch (err) {
118
+ console.error(err.message);
119
+ process.exit(1);
120
+ }
121
+ });
122
+ configCmd
123
+ .command("path <path>")
124
+ .description("Set com.mojang directory path")
125
+ .option("-g, --global", "Set globally in ~/.bdev/config.json")
126
+ .action(async (pathInput, options) => {
127
+ try {
128
+ await setPathCommand(pathInput, options);
129
+ }
130
+ catch (err) {
131
+ console.error(err.message);
132
+ process.exit(1);
133
+ }
134
+ });
135
+ program
136
+ .command("doctor")
137
+ .description("Verify environment requirements and Bedrock paths")
138
+ .option("-p, --path <path>", "Custom com.mojang path to check")
139
+ .action(async (options) => {
140
+ try {
141
+ await doctorCommand(options.path);
142
+ }
143
+ catch (err) {
144
+ console.error(err.message);
145
+ process.exit(1);
146
+ }
147
+ });
148
+ program.parse();
@@ -0,0 +1,2 @@
1
+ import * as esbuildNative from "esbuild";
2
+ export declare function runBuild(options: esbuildNative.BuildOptions): Promise<esbuildNative.BuildResult>;
@@ -0,0 +1,29 @@
1
+ import * as esbuildNative from "esbuild";
2
+ import * as esbuildWasm from "esbuild-wasm";
3
+ let wasmInitialized = false;
4
+ export async function runBuild(options) {
5
+ try {
6
+ return await esbuildNative.build(options);
7
+ }
8
+ catch (err) {
9
+ const errorObj = err;
10
+ const message = typeof errorObj?.message === "string" ? errorObj.message : "";
11
+ // If it's a code/syntax error from esbuild itself, rethrow directly
12
+ if (Array.isArray(errorObj?.errors) && errorObj.errors.length > 0) {
13
+ throw err;
14
+ }
15
+ // If missing native executable or module resolution in compiled binary, fallback to wasm
16
+ const isBinaryResolutionError = message.includes("Cannot find module 'esbuild'") ||
17
+ message.includes("could not be found") ||
18
+ message.includes("cannot be bundled") ||
19
+ message.includes("Failed to resolve entry for package");
20
+ if (isBinaryResolutionError) {
21
+ if (!wasmInitialized) {
22
+ await esbuildWasm.initialize({});
23
+ wasmInitialized = true;
24
+ }
25
+ return (await esbuildWasm.build(options));
26
+ }
27
+ throw err;
28
+ }
29
+ }
@@ -0,0 +1,14 @@
1
+ export interface BDevConfig {
2
+ name?: string;
3
+ mojangPath?: string;
4
+ [key: string]: unknown;
5
+ }
6
+ export declare function getGlobalConfigPath(): string;
7
+ export declare function getLocalConfigPath(targetDir?: string): string;
8
+ export declare function loadGlobalConfig(): BDevConfig;
9
+ export declare function loadLocalConfig(targetDir?: string): BDevConfig;
10
+ export declare function loadMergedConfig(targetDir?: string): BDevConfig;
11
+ export declare function saveConfig(updates: Partial<BDevConfig>, opts?: {
12
+ global?: boolean;
13
+ dir?: string;
14
+ }): string;
@@ -0,0 +1,58 @@
1
+ import fs from "node:fs";
2
+ import os from "node:os";
3
+ import path from "node:path";
4
+ const GLOBAL_CONFIG_DIR = path.join(os.homedir(), ".bdev");
5
+ const GLOBAL_CONFIG_PATH = path.join(GLOBAL_CONFIG_DIR, "config.json");
6
+ export function getGlobalConfigPath() {
7
+ return GLOBAL_CONFIG_PATH;
8
+ }
9
+ export function getLocalConfigPath(targetDir = process.cwd()) {
10
+ return path.join(path.resolve(targetDir), "bdev.json");
11
+ }
12
+ export function loadGlobalConfig() {
13
+ try {
14
+ if (fs.existsSync(GLOBAL_CONFIG_PATH)) {
15
+ const raw = fs.readFileSync(GLOBAL_CONFIG_PATH, "utf-8");
16
+ return JSON.parse(raw);
17
+ }
18
+ }
19
+ catch {
20
+ // Ignore read errors
21
+ }
22
+ return {};
23
+ }
24
+ export function loadLocalConfig(targetDir = process.cwd()) {
25
+ try {
26
+ const localPath = getLocalConfigPath(targetDir);
27
+ if (fs.existsSync(localPath)) {
28
+ const raw = fs.readFileSync(localPath, "utf-8");
29
+ return JSON.parse(raw);
30
+ }
31
+ }
32
+ catch {
33
+ // Ignore read errors
34
+ }
35
+ return {};
36
+ }
37
+ export function loadMergedConfig(targetDir = process.cwd()) {
38
+ const globalConf = loadGlobalConfig();
39
+ const localConf = loadLocalConfig(targetDir);
40
+ return { ...globalConf, ...localConf };
41
+ }
42
+ export function saveConfig(updates, opts = {}) {
43
+ if (opts.global) {
44
+ if (!fs.existsSync(GLOBAL_CONFIG_DIR)) {
45
+ fs.mkdirSync(GLOBAL_CONFIG_DIR, { recursive: true });
46
+ }
47
+ const current = loadGlobalConfig();
48
+ const merged = { ...current, ...updates };
49
+ fs.writeFileSync(GLOBAL_CONFIG_PATH, JSON.stringify(merged, null, 2) + "\n");
50
+ return GLOBAL_CONFIG_PATH;
51
+ }
52
+ const targetDir = opts.dir ? path.resolve(opts.dir) : process.cwd();
53
+ const localPath = getLocalConfigPath(targetDir);
54
+ const current = loadLocalConfig(targetDir);
55
+ const merged = { ...current, ...updates };
56
+ fs.writeFileSync(localPath, JSON.stringify(merged, null, 2) + "\n");
57
+ return localPath;
58
+ }
@@ -0,0 +1,8 @@
1
+ import { Ora } from "ora";
2
+ export declare const logger: {
3
+ info(msg: string): void;
4
+ success(msg: string): void;
5
+ warn(msg: string): void;
6
+ error(msg: string): void;
7
+ spinner(text: string): Ora;
8
+ };
@@ -0,0 +1,19 @@
1
+ import pc from "picocolors";
2
+ import ora from "ora";
3
+ export const logger = {
4
+ info(msg) {
5
+ console.log(`${pc.cyan("ℹ")} ${msg}`);
6
+ },
7
+ success(msg) {
8
+ console.log(`${pc.green("✔")} ${msg}`);
9
+ },
10
+ warn(msg) {
11
+ console.log(`${pc.yellow("⚠")} ${msg}`);
12
+ },
13
+ error(msg) {
14
+ console.error(`${pc.red("✖")} ${msg}`);
15
+ },
16
+ spinner(text) {
17
+ return ora({ text, color: "cyan" }).start();
18
+ },
19
+ };
@@ -0,0 +1,42 @@
1
+ export interface ManifestHeader {
2
+ name: string;
3
+ description: string;
4
+ uuid: string;
5
+ version: [number, number, number];
6
+ min_engine_version?: [number, number, number];
7
+ }
8
+ export interface ManifestModule {
9
+ type: "data" | "script" | "resources" | "client_data" | string;
10
+ uuid: string;
11
+ version: [number, number, number];
12
+ language?: string;
13
+ entry?: string;
14
+ description?: string;
15
+ }
16
+ export interface ManifestDependency {
17
+ uuid?: string;
18
+ version?: [number, number, number] | string;
19
+ module_name?: string;
20
+ }
21
+ export interface BedrockManifest {
22
+ format_version: number;
23
+ header: ManifestHeader;
24
+ modules: ManifestModule[];
25
+ dependencies?: ManifestDependency[];
26
+ }
27
+ export interface ValidationResult {
28
+ valid: boolean;
29
+ errors: string[];
30
+ }
31
+ export declare function validateManifest(manifestPath: string): ValidationResult;
32
+ export declare function generateManifests(opts: {
33
+ name: string;
34
+ description: string;
35
+ hasScript: boolean;
36
+ hasRp: boolean;
37
+ minEngineVersion?: [number, number, number];
38
+ serverVersion?: string;
39
+ }): {
40
+ bpManifest: BedrockManifest;
41
+ rpManifest?: BedrockManifest;
42
+ };