@minecraft/creator-tools
Version:
Minecraft Creator Tools command line and libraries.
189 lines (188 loc) • 6.25 kB
JavaScript
;
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
Object.defineProperty(exports, "__esModule", { value: true });
exports.ToolCommandRegistry = void 0;
const ToolCommandParser_1 = require("./ToolCommandParser");
/**
* Central registry for ToolCommands.
*/
class ToolCommandRegistry {
static _instance;
commands = new Map();
/**
* Get the singleton instance.
*/
static get instance() {
if (!this._instance) {
this._instance = new ToolCommandRegistry();
}
return this._instance;
}
/**
* Register a ToolCommand.
* @param command The command to register
*/
register(command) {
const { name, aliases } = command.metadata;
// Register by name (lowercase for case-insensitive lookup)
const lowerName = name.toLowerCase();
if (this.commands.has(lowerName)) {
throw new Error(`ToolCommand '${name}' is already registered`);
}
this.commands.set(lowerName, command);
// Register aliases
if (aliases) {
for (const alias of aliases) {
const lowerAlias = alias.toLowerCase();
if (this.commands.has(lowerAlias)) {
throw new Error(`ToolCommand alias '${alias}' conflicts with existing command`);
}
this.commands.set(lowerAlias, command);
}
}
}
/**
* Register multiple commands.
*/
registerAll(commands) {
for (let i = 0; i < commands.length; i++) {
const command = commands[i];
if (!command) {
throw new Error(`ToolCommand at index ${i} is undefined or null (out of ${commands.length} commands)`);
}
this.register(command);
}
}
/**
* Get a command by name or alias.
* @param name Command name or alias (case-insensitive)
*/
get(name) {
return this.commands.get(name.toLowerCase());
}
/**
* Check if a command exists.
*/
has(name) {
return this.commands.has(name.toLowerCase());
}
/**
* Get all unique commands (excluding alias duplicates).
* Optionally filter by scope.
*/
getAll(scope) {
const seen = new Set();
const result = [];
for (const command of this.commands.values()) {
if (seen.has(command))
continue;
seen.add(command);
// Filter by scope if specified
if (scope) {
const scopes = command.metadata.scopes;
// If no scopes defined, command is available everywhere
if (scopes && !scopes.includes(scope)) {
continue;
}
}
result.push(command);
}
// Sort by category then name
result.sort((a, b) => {
const catCmp = a.metadata.category.localeCompare(b.metadata.category);
if (catCmp !== 0)
return catCmp;
return a.metadata.name.localeCompare(b.metadata.name);
});
return result;
}
/**
* Get all command names (for autocomplete).
*/
getCommandNames(scope) {
return this.getAll(scope).map((c) => c.metadata.name);
}
/**
* Execute a command from a command string.
* @param commandText Full command text (e.g., "/create template myproject --traits mob")
* @param context Execution context
* @returns Command result, or undefined if command not found
*/
async execute(commandText, context) {
const parsed = ToolCommandParser_1.ToolCommandParser.parse(commandText);
if (!parsed) {
return undefined;
}
return this.executeCommand(parsed.commandName, parsed.args, parsed.flags, context);
}
/**
* Execute a command with pre-parsed arguments.
*/
async executeCommand(name, args, flags, context) {
const command = this.get(name);
if (!command) {
return undefined;
}
// Check scope restrictions
const scopes = command.metadata.scopes;
if (scopes && !scopes.includes(context.scope)) {
return {
success: false,
error: {
code: "SCOPE_RESTRICTED",
message: `Command '${name}' is not available in ${context.scope} context`,
},
};
}
// Check project requirement
if (command.metadata.requiresProject && !context.project) {
return {
success: false,
error: {
code: "PROJECT_REQUIRED",
message: `Command '${name}' requires an active project`,
},
};
}
// Check Minecraft requirement
if (command.metadata.requiresMinecraft && !context.minecraft) {
return {
success: false,
error: {
code: "MINECRAFT_REQUIRED",
message: `Command '${name}' requires an active Minecraft server connection`,
},
};
}
try {
return await command.execute(context, args, flags);
}
catch (error) {
const message = error instanceof Error ? error.message : String(error);
return {
success: false,
error: {
code: "EXECUTION_ERROR",
message: `Error executing '${name}': ${message}`,
},
};
}
}
/**
* Get autocomplete suggestions for a partial command.
* @param text The partial command text being typed
* @param cursorPos The cursor position in the text
* @param context Execution context
*/
async getCompletions(text, cursorPos, context) {
return ToolCommandParser_1.ToolCommandParser.getCompletions(text, cursorPos, this, context);
}
/**
* Clear all registered commands (for testing).
*/
clear() {
this.commands.clear();
}
}
exports.ToolCommandRegistry = ToolCommandRegistry;