Documentation Index
Fetch the complete documentation index at: https://mintlify.com/mojang/minecraft-creator-tools/llms.txt
Use this file to discover all available pages before exploring further.
Minecraft Creator Tools provides several storage implementations for different environments and use cases. All implementations share the same IStorage interface.
NodeStorage
For Node.js environments, providing access to the local file system.
Constructor
import { NodeStorage } from "@minecraft/creator-tools";
const storage = new NodeStorage(
"/path/to/folder", // Root path
"MyProject" // Storage name
);
Properties
class NodeStorage extends StorageBase implements IStorage {
rootPath: string; // File system path
name: string; // Storage name
rootFolder: NodeFolder; // Root folder
static platformFolderDelimiter: string; // Path separator for platform
get folderDelimiter(): string; // Returns path.sep
}
Static Methods
// Create storage from a file or folder path
static async createFromPath(
path: string
): Promise<NodeFile | NodeFolder>;
// Create storage, auto-detecting and extracting ZIP files
static async createFromPathIncludingZip(
path: string
): Promise<IFolder | undefined>;
// Get parent folder path
static getParentFolderPath(parentPath: string): string;
// Ensure path ends with delimiter
static ensureEndsWithDelimiter(path: string): string;
// Ensure path starts with delimiter
static ensureStartsWithDelimiter(path: string): string;
Example Usage
import { NodeStorage } from "@minecraft/creator-tools";
// Create storage for a behavior pack
const storage = new NodeStorage(
"/Users/me/minecraft/behavior_packs/my_pack",
"MyBehaviorPack"
);
// Load and access files
await storage.rootFolder.load();
const manifestFile = await storage.rootFolder.getFileFromRelativePath("manifest.json");
if (manifestFile) {
await manifestFile.loadContent();
console.log(manifestFile.content);
}
// Auto-detect and extract .mcpack files
const folder = await NodeStorage.createFromPathIncludingZip(
"/path/to/pack.mcpack"
);
if (folder) {
await folder.load();
console.log("Pack contains:", folder.fileCount, "files");
}
Source: ~/workspace/source/app/src/local/NodeStorage.ts:12-127
BrowserStorage
For browser environments, providing persistent client-side storage using IndexedDB via localforage.
Constructor
import { BrowserStorage } from "@minecraft/creator-tools";
const storage = new BrowserStorage(
"myproject" // Storage name (null for default)
);
Properties
class BrowserStorage extends StorageBase implements IStorage {
rootFolder: BrowserFolder;
static isConfigured: boolean; // Whether localforage is configured
}
Static Methods
// Configure localforage (called automatically)
static ensureConfigured(): void;
Configuration
BrowserStorage automatically configures localforage with:
localforage.config({
name: "Minecraft Creator Tools",
storeName: "minecraft_creator_tools",
version: 1.0,
});
Example Usage
import { BrowserStorage } from "@minecraft/creator-tools";
// Create browser storage
const storage = new BrowserStorage("myproject");
// Files persist across browser sessions
const file = await storage.rootFolder.ensureFileFromRelativePath("data.json");
file.setContent(JSON.stringify({ foo: "bar" }));
await file.saveContent();
// Later session - file is still there
await storage.rootFolder.load();
const loadedFile = await storage.rootFolder.getFileFromRelativePath("data.json");
if (loadedFile) {
await loadedFile.loadContent();
console.log(loadedFile.content); // { foo: "bar" }
}
Source: ~/workspace/source/app/src/storage/BrowserStorage.ts:9-44
HttpStorage
For read-only access to files served over HTTP/HTTPS.
Constructor
import { HttpStorage } from "@minecraft/creator-tools";
const storage = new HttpStorage(
"https://example.com/packs/" // Base URL
);
Properties
class HttpStorage extends StorageBase implements IStorage {
rootFolder: HttpFolder;
baseUrl: string; // Base URL for all requests
}
Behavior
- Automatically appends trailing slash to
baseUrl
- Read-only (save operations will fail)
- Files are fetched on-demand via HTTP GET
- Good for serving sample packs or templates
Example Usage
import { HttpStorage } from "@minecraft/creator-tools";
// Create storage pointing to a web-hosted pack
const storage = new HttpStorage(
"https://cdn.example.com/minecraft/samples/hello-world/"
);
// Load files from the server
const manifest = await storage.rootFolder.getFileFromRelativePath("manifest.json");
if (manifest) {
await manifest.loadContent();
console.log(manifest.content);
}
// Read-only - saves will not persist to server
manifest.setContent("modified");
await manifest.saveContent(); // This is a no-op for HttpStorage
Source: ~/workspace/source/app/src/storage/HttpStorage.ts:8-30
GitHubStorage
For read-only access to GitHub repositories.
Constructor
import { GitHubStorage, GitHubManager } from "@minecraft/creator-tools";
const manager = new GitHubManager();
const storage = new GitHubStorage(
manager,
"minecraft-samples", // Repository name
"microsoft", // Owner (must be 'microsoft' or 'mojang')
"main", // Branch (optional)
"behavior_packs/" // Sub-path (optional)
);
Properties
class GitHubStorage extends StorageBase implements IStorage {
rootFolder: GitHubFolder;
manager: GitHubManager; // GitHub API manager
repoName: string; // Repository name
ownerName: string; // Owner name (microsoft or mojang only)
branch?: string; // Branch name
subPath: string; // Sub-path within repo
}
Security Restrictions
For security reasons, GitHubStorage only allows access to repositories owned by:
Attempting to access other repositories will throw an error:
// ✅ Allowed
const storage1 = new GitHubStorage(manager, "samples", "microsoft");
const storage2 = new GitHubStorage(manager, "scripts", "mojang");
// ❌ Throws error
const storage3 = new GitHubStorage(manager, "repo", "other-user");
// Error: Unsupported GitHub action.
Example Usage
import { GitHubStorage, GitHubManager } from "@minecraft/creator-tools";
// Create manager and storage
const manager = new GitHubManager();
const storage = new GitHubStorage(
manager,
"minecraft-samples",
"microsoft",
"main",
"behavior_packs/hello_world/"
);
// Access files from GitHub
await storage.rootFolder.load();
const manifest = await storage.rootFolder.getFileFromRelativePath("manifest.json");
if (manifest) {
await manifest.loadContent();
console.log(manifest.content);
}
Source: ~/workspace/source/app/src/github/GitHubStorage.ts:9-62
ZipStorage
For working with ZIP archives, including .mcpack, .mcaddon, .mcworld, and .mctemplate files.
Constructor
import { ZipStorage } from "@minecraft/creator-tools";
const storage = new ZipStorage();
Properties
class ZipStorage extends StorageBase implements IStorage {
name?: string;
rootFolder: ZipFolder;
modified: Date | null;
lastLoadedOrSaved: Date | null;
allowAllFiles: boolean; // Allow files not in AllowedExtensionsSet
get updatedSinceLoad(): boolean; // Check if modified since load
}
Loading Methods
// Load from base64 string
await storage.loadFromBase64(base64String, "pack.mcpack");
// Load from Uint8Array
await storage.loadFromUint8Array(bytes, "pack.zip");
// Load from an IFile
const zipStorage = await ZipStorage.loadFromFile(file);
Generating Methods
// Generate compressed archive as Uint8Array
const bytes = await storage.generateCompressedUint8ArrayAsync();
// Generate as base64 string
const base64 = await storage.generateCompressedBase64Async();
// Generate as blob (browser) or buffer (Node)
const blob = await storage.generateBlobAsync();
Static Factory Methods
// Create from JSON string
const storage = ZipStorage.fromJsonString(jsonString);
// Create from JavaScript object
const storage = ZipStorage.fromJsObject({ foo: "bar" });
// Load from IFile and extract to object
const obj = await ZipStorage.toJsObject(storage);
// Convert ZIP bytes to JSON object
const obj = await ZipStorage.fromZipBytesToJsonObject(bytes);
Security Validation
ZipStorage includes security checks:
// File size limits (configurable via SecurityUtilities.MAX_UPLOAD_SIZE)
// File count limits (configurable via SecurityUtilities.MAX_ZIP_FILES)
// Path validation (prevents directory traversal attacks)
if (storage.errorStatus === StorageErrorStatus.unprocessable) {
console.error("ZIP validation failed:", storage.errorMessage);
}
Example Usage
import { ZipStorage } from "@minecraft/creator-tools";
// Load an existing .mcpack file
const file = await folder.getFileFromRelativePath("pack.mcpack");
if (file) {
const zipStorage = await ZipStorage.loadFromFile(file);
if (zipStorage) {
// Access files inside the ZIP
await zipStorage.rootFolder.load();
const manifest = await zipStorage.rootFolder.getFileFromRelativePath("manifest.json");
if (manifest) {
await manifest.loadContent();
console.log(manifest.content);
}
// Modify and regenerate
manifest.setContent("modified content");
const newBytes = await zipStorage.generateCompressedUint8ArrayAsync();
// Save back to original file
file.setContent(newBytes);
await file.saveContent();
}
}
// Create a new ZIP from scratch
const newZip = new ZipStorage();
const newFile = newZip.rootFolder.ensureFile("test.txt");
newFile.setContent("Hello World");
await newFile.saveContent();
const bytes = await newZip.generateCompressedUint8ArrayAsync();
Source: ~/workspace/source/app/src/storage/ZipStorage.ts:14-253
Storage (In-Memory)
For temporary in-memory storage without persistence.
Constructor
import { Storage } from "@minecraft/creator-tools";
const storage = new Storage();
Properties
class Storage extends StorageBase implements IStorage {
rootFolder: Folder;
static readonly folderDelimiter = "/";
}
Behavior
- Files and folders exist only in memory
- No persistence between sessions
- Fast for temporary operations
- Good for testing and transformations
Example Usage
import { Storage } from "@minecraft/creator-tools";
// Create temporary storage
const tempStorage = new Storage();
// Create files
const file = await tempStorage.rootFolder.ensureFileFromRelativePath("temp.json");
file.setContent(JSON.stringify({ data: "test" }));
// Use for transformations
const result = processFile(file);
// Storage is discarded when no longer referenced
Source: ~/workspace/source/app/src/storage/Storage.ts:8-46
StorageBase
All storage implementations extend StorageBase, which provides common functionality:
Common Features
abstract class StorageBase implements IStorage {
// Change tracking
isContentUpdated: boolean;
readOnly: boolean;
// Version management
priorVersions: IVersionContent[];
currentVersionId?: string;
// Events
onFileAdded: IEvent<IStorage, IFile>;
onFileRemoved: IEvent<IStorage, string>;
onFileContentsUpdated: IEvent<IStorage, IFileUpdateEvent>;
onFolderMoved: IEvent<IStorage, IFolderMove>;
// Error handling
errorStatus?: StorageErrorStatus;
errorMessage?: string;
// Availability
available?: boolean;
abstract getAvailable(): Promise<boolean>;
// Path utilities
static readonly slashFolderDelimiter = "/";
joinPath(pathA: string, pathB: string): string;
static getParentFolderPath(path: string): string;
}
Version Management
// Add a new version
storage.addVersion(versionContent, FileUpdateType.regularEdit);
// Navigate version history
storage.setToVersion(versionId); // Jump to a specific version
storage.trimAfterVersion(versionId); // Remove future versions
// Current version tracking
if (storage.currentVersionId) {
console.log("Viewing historical version");
}
Scan for Changes
// Full scan of all folders and files
await storage.scanForChanges();
// Incremental scan (one folder at a time)
await storage.incrementalScanForChanges();
// Notify of external update to specific path
await storage.notifyPathWasUpdatedExternal("/path/to/file.json");
Source: ~/workspace/source/app/src/storage/StorageBase.ts:14-300
Choosing a Storage Implementation
| Use Case | Implementation | Reason |
|---|
| Desktop app file access | NodeStorage | Direct file system access |
| Web app data persistence | BrowserStorage | Client-side storage with IndexedDB |
| Serving sample packs | HttpStorage | Simple HTTP hosting |
| Microsoft/Mojang samples | GitHubStorage | Access official repositories |
| Working with .mcpack files | ZipStorage | Read/write compressed archives |
| Temporary transformations | Storage | No persistence overhead |
| Unit testing | Storage | Fast, no I/O |
Detecting Environment and Creating Storage
import {
NodeStorage,
BrowserStorage,
Storage,
CreatorToolsHost,
HostType
} from "@minecraft/creator-tools";
function createStorage(path?: string): IStorage {
if (CreatorToolsHost.hostType === HostType.electronNodeJs ||
CreatorToolsHost.hostType === HostType.toolsNodejs) {
// Node environment
if (path) {
return new NodeStorage(path, "Project");
}
} else {
// Browser environment
return new BrowserStorage("myapp");
}
// Fallback to in-memory
return new Storage();
}
Unified Loading Pattern
import { IStorage } from "@minecraft/creator-tools";
async function loadProject(storage: IStorage) {
// Same code works for all storage types
await storage.rootFolder.load();
const manifest = await storage.rootFolder.getFileFromRelativePath("manifest.json");
if (manifest) {
await manifest.loadContent();
return manifest.content;
}
}
// Works with any storage implementation
const nodeStorage = new NodeStorage("/path", "name");
const browserStorage = new BrowserStorage("name");
const httpStorage = new HttpStorage("https://example.com/");
await loadProject(nodeStorage);
await loadProject(browserStorage);
await loadProject(httpStorage);