@minecraft/creator-tools
Version:
Minecraft Creator Tools command line and libraries.
149 lines (148 loc) • 5.56 kB
TypeScript
/**
* HttpStorage.ts
*
* ARCHITECTURE DOCUMENTATION
* ==========================
*
* HttpStorage is a client-side storage implementation that fetches content
* via HTTP and receives real-time updates via WebSocket notifications.
*
* REAL-TIME SYNCHRONIZATION:
* --------------------------
* 1. HttpStorage connects to /ws/notifications WebSocket endpoint
* 2. Subscribes to file/folder change events for specific slots
* 3. When notifications arrive, converts them to standard IStorage events
* 4. Consumers (MCWorld, etc.) subscribe to these events
*
* DATA FLOW:
* ----------
* NodeStorage (fs.watch) -> HttpServer (broadcast) -> WebSocket ->
* HttpStorage (this) -> notifyFileAdded/Removed/Updated -> MCWorld -> WorldView
*
* WEBSOCKET PROTOCOL:
* -------------------
* - Connect: ws://host:port/ws/notifications?token=<authToken>
* - Subscribe: { header: {..., messageType: "subscriptionRequest", messagePurpose: "subscribe" },
* body: { eventNames: ["fileChanged", "fileAdded", ...], slot: 0 } }
* - Receive: IServerNotification messages with file/folder change details
*
* RELATED FILES:
* --------------
* - IServerNotification.ts: WebSocket message format definitions
* - IStorageWatcher.ts: INotificationReceiver interface
* - HttpServer.ts: Server-side WebSocket broadcaster
* - NodeStorage.ts: Server-side file watcher source
*
* USAGE:
* ------
* const storage = HttpStorage.get("http://localhost:6126/api/worldContent/0/");
* storage.authToken = "encrypted-token";
* await storage.connectToNotifications();
* storage.onFileAdded.subscribe((sender, file) => console.log("File added:", file.name));
*/
import HttpFolder from "./HttpFolder";
import StorageBase from "./StorageBase";
import IStorage from "./IStorage";
import { INotificationReceiver } from "./IStorageWatcher";
export default class HttpStorage extends StorageBase implements IStorage, INotificationReceiver {
rootFolder: HttpFolder;
baseUrl: string;
/**
* Bearer token for Authorization header.
* When set, requests will include "Authorization: Bearer <token>" header.
* This is used for authenticated endpoints like /api/content.
*/
authToken?: string;
/**
* When true (default), the storage is read-only and write operations will throw.
* Set to false to enable HTTP PUT/DELETE operations for editing content.
*/
readOnly: boolean;
/** WebSocket connection for receiving notifications */
private _webSocket;
/** Currently subscribed event names */
private _subscribedEvents;
/** Server slot this storage is associated with (for filtering notifications) */
private _slot?;
/** Whether we're currently connected to the notification server */
private _isConnected;
/** Reconnection timer */
private _reconnectTimer?;
/** Whether auto-reconnect is enabled */
private _autoReconnect;
/**
* Event fired when the server sends a shutdown notification.
* This indicates the entire MCT server is shutting down (not just a BDS instance).
* Subscribers should show appropriate UI feedback and disable auto-reconnect.
* Args: (reason: string, graceful: boolean)
*/
private _onServerShutdown;
/**
* Subscribe to server shutdown notifications.
* This is fired when the MCT server is about to shut down.
*/
get onServerShutdown(): import("ste-events").IEvent<HttpStorage, {
reason: string;
graceful: boolean;
}>;
/**
* Static cache of HttpStorage instances by base URL.
* Used to avoid creating duplicate storage instances for the same URL.
*/
private static _storageCache;
/**
* Get or create an HttpStorage instance for the given base URL.
* Reuses cached instances to avoid creating duplicates.
* @param baseUrl The base URL for the storage
* @returns A cached or new HttpStorage instance
*/
static get(baseUrl: string): HttpStorage;
/**
* Clear the storage cache. Useful for testing or when storage should be refreshed.
*/
static clearCache(): void;
constructor(newUrl: string);
getAvailable(): Promise<boolean>;
get isConnected(): boolean;
/**
* Get the underlying WebSocket connection.
* Can be used to listen for raw notifications (e.g., debug stats).
*/
get webSocket(): WebSocket | null;
/**
* Set the slot number for filtering notifications.
*/
set slot(value: number | undefined);
get slot(): number | undefined;
/**
* Connect to the WebSocket notification endpoint.
* The WebSocket URL is derived from the baseUrl.
*
* @param url Optional override URL for the WebSocket endpoint
* @param authToken Optional auth token (uses this.authToken if not provided)
*/
connect(url?: string, authToken?: string): Promise<void>;
/**
* Disconnect from the WebSocket notification server.
*/
disconnect(): void;
/**
* Subscribe to specific event types.
*
* @param eventNames Array of event names to subscribe to
* @param slot Optional slot number to filter events
*/
subscribe(eventNames: string[], slot?: number): Promise<void>;
/**
* Unsubscribe from specific event types.
*/
unsubscribe(eventNames: string[]): Promise<void>;
/**
* Send a subscription request to the server.
*/
private _sendSubscription;
/**
* Handle an incoming notification message.
*/
private _handleNotification;
}