@minecraft/creator-tools
Version:
Minecraft Creator Tools command line and libraries.
257 lines (256 loc) • 8.36 kB
TypeScript
/**
* CommandContextFactory - Creates fully-hydrated ICommandContext from CLI options
*
* ARCHITECTURE DOCUMENTATION
* ==========================
*
* This factory is the central point for:
* 1. Parsing Commander.js options into typed structures
* 2. Detecting and loading projects (moved from loadProjects() in index.ts)
* 3. Setting up storage abstractions
* 4. Creating worker pools
* 5. Configuring logging
*
* ENTRY POINT:
* CommandContextFactory.create() is called from index.ts after Commander.js
* parses the command line. It returns a fully-hydrated ICommandContext that
* commands use to access projects, storage, logging, and worker pools.
*
* KEY METHODS:
* - create(): Main entry point, orchestrates all setup
* - loadProjects(): Detects and loads projects from input path
* - parseThreads(): Converts thread option to number
* - parseOutputType(): Converts output type string to enum
* - resolveSuite(): Converts suite string to ProjectInfoSuite enum
*
* PROJECT DETECTION LOGIC:
* The project detection supports several modes:
*
* 1. Single File Mode (-f, --file):
* - Input is a single file (e.g., .mcaddon, .mcpack, .zip)
* - Creates one project from that file
*
* 2. Multi-Level Multi-Project:
* - Root folder contains subfolders
* - Each subfolder contains .zip/.mcaddon files + optional .data.json
* - Each zip becomes a separate project
*
* 3. Children-of-Folder Multi-Project:
* - Root folder contains zip files directly OR subfolders that are projects
* - Subfolders with manifest.json, behavior_packs/, etc. are detected
*
* 4. Single Project (fallback):
* - Treat the entire input folder as one project
*
* STORAGE SETUP:
* - inputStorage: NodeStorage pointing to input folder (read-only for non-edit commands)
* - outputStorage: NodeStorage pointing to output folder (or same as input)
* - Additional storage for Minecraft paths, deployment, etc.
*
* WORKER POOL:
* - Created via createWorkerPool() from WorkerPool.ts
* - Supports parallel execution with configurable thread count
* - Falls back to single-threaded mode when threads=1
*
* LOGGING:
* - Created via createLogger() from Logger.ts
* - Supports verbose, quiet, and debug modes
* - ConsoleLogger for normal output, SilentLogger for testing
*
* KEY FILES:
* - ICommandContext.ts: Interface definitions
* - WorkerPool.ts: Parallel execution
* - Logger.ts: Logging implementation
* - ClUtils.ts: Legacy utilities (being migrated)
*/
import CreatorTools from "../../app/CreatorTools";
import LocalEnvironment from "../../local/LocalEnvironment";
import { TaskType } from "../ClUtils";
import { ICommandContext, ILogger } from "./ICommandContext";
/**
* Raw options as parsed by Commander.js.
* This interface captures all the global options.
*/
export interface IRawOptions {
inputFolder?: string;
outputFolder?: string;
outputFile?: string;
inputFile?: string;
additionalFiles?: string;
basePath?: string;
threads?: string;
single?: boolean;
force?: boolean;
debug?: boolean;
verbose?: boolean;
quiet?: boolean;
json?: boolean;
yes?: boolean;
dryRun?: boolean;
outputType?: string;
port?: string;
httpsPort?: string;
slot?: string;
adminpc?: string;
updatepc?: string;
displaypc?: string;
fullpc?: string;
title?: string;
domain?: string;
motd?: string;
runOnce?: boolean;
timeout?: string;
forceInk?: boolean;
mcpRequireAuth?: boolean;
logFile?: string;
features?: string;
experimentalSslCert?: string;
experimentalSslKey?: string;
experimentalSslPfx?: string;
experimentalSslPfxPassphrase?: string;
experimentalSslCa?: string;
experimentalSslPort?: string;
experimentalSslOnly?: boolean;
betaApis?: boolean;
editor?: boolean;
difficulty?: string;
gameMode?: string;
worldName?: string;
seed?: string;
ensureWorld?: boolean;
testWorld?: boolean;
launch?: boolean;
suite?: string;
exclusions?: string;
aggregateReports?: string;
warnOnly?: boolean;
projectStartsWith?: string;
isolated?: boolean;
referenceFolder?: string;
/** Raw command-specific options forwarded from Commander (escape hatch for per-command flags). */
commandOptions?: Record<string, any>;
}
/**
* Command-specific arguments parsed from Commander.js.
*/
export interface ICommandArgs {
subCommand?: string;
propertyValue?: string;
searchTerm?: string;
mode?: string;
type?: string;
newName?: string;
description?: string;
}
/**
* Factory for creating ICommandContext instances.
*/
export declare class CommandContextFactory {
/** Folder names that indicate a Minecraft project root. */
static readonly PROJECT_INDICATOR_FOLDERS: string[];
/** Maximum number of parent levels to walk when auto-discovering a project root. */
static readonly MAX_DISCOVERY_LEVELS = 8;
/**
* Walk up from `startDir` to find the nearest Minecraft project root.
*
* A folder qualifies as a project root if it contains:
* - A `package.json` file, OR
* - A child folder matching one of the Minecraft pack folder conventions
* (behavior_packs, resource_packs, etc.)
*
* The search stops when:
* - A qualifying folder is found (returned immediately)
* - MAX_DISCOVERY_LEVELS parent directories have been checked
* - The folder is at a "second-order root" — its parent is a filesystem
* root (e.g. `C:\projects` on Windows, `/home` on Unix), to avoid
* scanning broad top-level directories
* - The filesystem root is reached
*
* If no qualifying folder is found, `startDir` is returned unchanged
* (preserving the current cwd-fallback behavior).
*/
static resolveProjectRoot(startDir: string, log?: ILogger): string;
/**
* Check whether a directory looks like a Minecraft project root.
*
* Returns true if the directory contains a `package.json` file or any
* of the standard Minecraft pack folder names.
*/
static isProjectRoot(dir: string): boolean;
/**
* Create a fully-hydrated command context.
*
* @param creatorTools Initialized CreatorTools instance
* @param localEnv Initialized LocalEnvironment
* @param taskType The command being executed
* @param options Raw options from Commander.js
* @param args Command-specific arguments
*/
static create(creatorTools: CreatorTools, localEnv: LocalEnvironment, taskType: TaskType, options: IRawOptions, args?: ICommandArgs): Promise<ICommandContext>;
/**
* Parse threads option.
*/
private static parseThreads;
/**
* Parse output type option.
*/
private static parseOutputType;
/**
* Get work folder, creating if needed for write commands.
*/
private static getWorkFolder;
/**
* Detect projects in the input folder/file.
*
* This is the core project detection logic migrated from loadProjects() in index.ts.
*/
private static detectProjects;
/**
* Detect multi-level multi-project layout.
*
* Structure:
* root/
* subfolder1/
* project1.zip
* project1.data.json
* subfolder2/
* project2.mcaddon
*/
private static detectMultiLevelProjects;
/**
* Detect children-of-folder multi-project layout.
*
* Structure:
* root/
* project1.mcaddon
* project2.zip
* project3/
* manifest.json
* ...
*/
private static detectChildrenProjects;
/**
* Hydrate project start infos into full Project instances.
*/
private static hydrateProjects;
/**
* Parse additional files option.
*/
private static parseAdditionalFiles;
/**
* Parse a port string into a valid port number, falling back to a default.
*/
static parsePort(portStr: string | undefined, defaultPort: number): number;
/**
* Parse server-related options.
*/
private static parseServerOptions;
/**
* Parse world-related options.
*/
private static parseWorldOptions;
/**
* Parse validation-specific options.
*/
private static parseValidationOptions;
}