UNPKG

@minecraft/creator-tools

Version:

Minecraft Creator Tools command line and libraries.

508 lines (507 loc) 17.8 kB
"use strict"; // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const StorageUtilities_1 = __importDefault(require("./StorageUtilities")); const Utilities_1 = __importDefault(require("./../core/Utilities")); const AllFolderFileIterator_1 = __importDefault(require("./AllFolderFileIterator")); const Log_1 = __importDefault(require("../core/Log")); const ste_events_1 = require("ste-events"); class FolderBase { get ensuredName() { return this.name; } isDisposed = false; #lastLoadedOrSaved; manager; #onFolderMoved = new ste_events_1.EventDispatcher(); #onChildFolderMoved = new ste_events_1.EventDispatcher(); errorStatus; get onFolderMoved() { return this.#onFolderMoved.asEvent(); } get onChildFolderMoved() { return this.#onChildFolderMoved.asEvent(); } get isLoaded() { return this.#lastLoadedOrSaved !== null; } get canIgnore() { return StorageUtilities_1.default.isIgnorableFolder(this.name); } get allFiles() { let parentFolder = this; return { [Symbol.asyncIterator]() { return new AllFolderFileIterator_1.default(parentFolder); }, }; } get folderCount() { let i = 0; for (const folderName in this.folders) { if (this.folders[folderName]) { i++; } } return i; } get fileCount() { let i = 0; // eslint-disable-next-line for (const fileName in this.files) { if (this.files[fileName]) { i++; } } return i; } get storageRelativePath() { if (this.parentFolder === null) { return "/"; } else { return this.parentFolder.storageRelativePath + this.name + "/"; } } get lastLoadedOrSaved() { return this.#lastLoadedOrSaved; } get fullPath() { return this.storageRelativePath; } get extendedPath() { let start = ""; if (this.storage.storagePath) { start = this.storage.storagePath; } let result = start + this.fullPath; if (!result.endsWith(this.storage.folderDelimiter)) { result += this.storage.folderDelimiter; } return result; } constructor() { this.#lastLoadedOrSaved = null; } updateLastLoadedOrSaved() { this.#lastLoadedOrSaved = new Date(); } getFolderRelativePath(toFolder) { if (toFolder.storage !== this.storage && this.storage.storagePath) { const parentPath = toFolder.storageRelativePath; if (parentPath && this.extendedPath && this.extendedPath.startsWith(parentPath) && StorageUtilities_1.default.ensureEndsWithDelimiter(parentPath)) { const subPath = this.extendedPath.substring(parentPath.length - 1); return subPath; } return this.extendedPath; } else if (this === toFolder) { return "/"; } else if (this.parentFolder === null) { return undefined; } else { const result = this.parentFolder.getFolderRelativePath(toFolder); if (result === undefined) { return undefined; } return result + this.name + "/"; } } dispose() { this.manager = undefined; if (this.folders) { for (const folderName in this.folders) { const folder = this.folders[folderName]; if (folder) { folder.dispose(); this.folders[folderName] = undefined; } } } if (this.files) { for (const fileName in this.files) { const file = this.files[fileName]; if (file) { file.dispose(); this.files[fileName] = undefined; } } } this.isDisposed = true; } async setStructureFromFileList(fileList) { this.updateLastLoadedOrSaved(); for (const file of fileList) { let folderPath = StorageUtilities_1.default.getFolderPath(file); if (folderPath) { folderPath = StorageUtilities_1.default.ensureEndsDelimited(folderPath); if (folderPath.length > 2) { const folder = (await this.ensureFolderFromRelativePath(folderPath, true)); folder.updateLastLoadedOrSaved(); let parentFolder = folder.parentFolder; while (parentFolder && parentFolder !== this) { parentFolder.updateLastLoadedOrSaved(); parentFolder = parentFolder.parentFolder; } } await this.ensureFileFromRelativePath(file, true); } } } isSameFolder(newFolderStorageRelativePath) { if (StorageUtilities_1.default.canonicalizePath(newFolderStorageRelativePath) === StorageUtilities_1.default.canonicalizePath(this.storageRelativePath)) { return true; } return false; } _addExistingFolderToParent(folder) { const nameCanon = StorageUtilities_1.default.canonicalizeName(folder.name); if (Utilities_1.default.isUsableAsObjectKey(nameCanon)) { this.folders[nameCanon] = folder; } } _removeExistingFolderFromParent(folder) { const nameCanon = StorageUtilities_1.default.canonicalizeName(folder.name); if (Utilities_1.default.isUsableAsObjectKey(nameCanon)) { this.folders[nameCanon] = undefined; } } folderExists(name) { if (this.isDisposed) { Log_1.default.throwIsDisposed(); } const nameCanon = StorageUtilities_1.default.canonicalizeName(name); return !Utilities_1.default.isNullOrUndefined(this.folders[nameCanon]); } fileExists(name) { if (this.isDisposed) { Log_1.default.throwIsDisposed(); } const nameCanon = StorageUtilities_1.default.canonicalizeName(name); return !Utilities_1.default.isNullOrUndefined(this.files[nameCanon]); } async deleteFileFromRelativePath(path) { path = this.canonicalizePath(path); const file = await this.getFileFromRelativePath(path); if (file !== undefined) { return await file.deleteThisFile(); } return false; } canonicalizePath(path) { return path.replace(/\\/g, "/"); } async getFileFromRelativePath(path) { if (this.isDisposed) { Log_1.default.throwIsDisposed(); } if (path.length < 2) { throw Error("Path is too short."); } path = this.canonicalizePath(path); if (path[0] !== "/") { throw Error("Storage relative path '" + path + "' is not in the right format."); } await this.ensureExists(); await this.load(false); const nextSlash = path.indexOf("/", 1); if (nextSlash < 0) { const fileName = path.substring(1, path.length); return this.files[StorageUtilities_1.default.canonicalizeName(fileName)]; } else { const folderName = path.substring(1, nextSlash); const folder = this.folders[StorageUtilities_1.default.canonicalizeName(folderName)]; if (folder === undefined || folder === null) { return undefined; } return await folder.getFileFromRelativePath(path.substring(nextSlash, path.length)); } } clearAllManagers() { if (this.manager) { this.manager = undefined; } for (const fileName in this.files) { const file = this.files[fileName]; if (file) { file.manager = undefined; } } for (const folderName in this.folders) { const folder = this.folders[folderName]; if (folder) { folder.clearAllManagers(); } } } async getFolderFromRelativePath(path) { if (this.isDisposed) { Log_1.default.throwIsDisposed(); } if (path === "/" || path === "\\") { return this; } if (path.length < 2) { throw Error("Path is too short."); } path = this.canonicalizePath(path); if (path[0] !== "/") { throw Error("Storage relative path '" + path + "' is not in the right format."); } await this.ensureExists(); await this.load(false); const nextSlash = path.indexOf("/", 1); if (nextSlash < 0) { const folderName = path.substring(1, path.length); return this.folders[StorageUtilities_1.default.canonicalizeName(folderName)]; } else { let folderName = path.substring(1, nextSlash); folderName = StorageUtilities_1.default.canonicalizeName(folderName); const folder = this.folders[folderName]; if (folder === undefined || folder === null) { return undefined; } const nextPath = path.substring(nextSlash, path.length); if (nextPath === "/" || nextPath === "\\") { return folder; } return await folder.getFolderFromRelativePath(nextPath); } } getFolderByIndex(index) { let curIndex = 0; for (const folderName in this.folders) { const folder = this.folders[folderName]; if (folder && curIndex === index) { return folder; } if (folder) { curIndex++; } } return undefined; } getSortedFolderKeys() { return Object.keys(this.folders).sort(); } getSortedFileKeys() { return Object.keys(this.files).sort(); } getSummary() { let str = "P: " + this.fullPath + " FO:"; for (const folderName in this.folders) { str += " " + folderName; } str += " FI:"; for (const fileName in this.files) { str += " " + fileName; } return str; } getFolderFromRelativePathLocal(path) { if (this.isDisposed) { Log_1.default.throwIsDisposed(); } if (path === "/" || path === "\\") { return this; } if (path.length < 2) { throw Error("Path is too short."); } path = this.canonicalizePath(path); if (path[0] !== "/") { throw Error("Storage relative path '" + path + "' is not in the right format."); } const nextSlash = path.indexOf("/", 1); if (nextSlash < 0) { const folderName = path.substring(1, path.length); return this.folders[StorageUtilities_1.default.canonicalizeName(folderName)]; } else { const folderName = path.substring(1, nextSlash); let folder = this.folders[StorageUtilities_1.default.canonicalizeName(folderName)]; if (folder === undefined || folder === null) { if (folderName.endsWith("#")) { const storageFile = this.files[StorageUtilities_1.default.canonicalizeName(folderName.substring(0, folderName.length - 1))]; if (storageFile) { if (storageFile.fileContainerStorage) { folder = storageFile.fileContainerStorage.rootFolder; } } } if (folder === undefined || folder === null) { return undefined; } } const nextPath = path.substring(nextSlash, path.length); if (nextPath === "/" || nextPath === "\\") { return folder; } return folder.getFolderFromRelativePathLocal(nextPath); } } async saveAll(force) { // Log.verbose("Saving all at " + this.storageRelativePath); if (this.isDisposed) { Log_1.default.throwIsDisposed(); } for (const fileName in this.files) { const file = this.files[fileName]; if (file !== undefined && (file.needsSave || force)) { await file.saveContent(force); } } for (const folderName in this.folders) { const folder = this.folders[folderName]; if (folder !== undefined && !folder.errorStatus) { await folder.saveAll(force); } } return true; } async ensureFolderFromRelativePath(path, ignoreLoad) { if (this.isDisposed) { Log_1.default.throwIsDisposed(); } if (path === "/" || path === "\\") { return this; } if (path.startsWith("./")) { path = path.substring(1); } path = this.canonicalizePath(path); if (path[path.length - 1] !== "/") { path = path + "/"; } if (path[0] !== "/") { throw Error("Storage relative path '" + path + "' is not in the right format."); } if (!ignoreLoad) { await this.ensureExists(); await this.load(false); } const nextSlash = path.indexOf("/", 1); if (nextSlash < 0) { throw new Error("Unexpected path format error"); } else { const folderName = path.substring(1, nextSlash); const folder = this.ensureFolder(folderName); if (nextSlash === path.length - 1) { return folder; } else { return folder.ensureFolderFromRelativePath(path.substring(nextSlash, path.length), ignoreLoad); } } } async ensureFileFromRelativePath(path, ignoreLoad) { if (this.isDisposed) { Log_1.default.throwIsDisposed(); } if (path.length < 2) { throw Error("Path is too short."); } path = this.canonicalizePath(path); if (path[0] !== "/") { throw Error("Storage relative path '" + path + "' is not in the right format."); } await this.ensureExists(); if (!ignoreLoad) { await this.load(false); } const nextSlash = path.indexOf("/", 1); if (nextSlash < 0) { const file = this.ensureFile(path.substring(1, path.length)); return file; } else { const folderName = path.substring(1, nextSlash); const folder = this.ensureFolder(folderName); const file = await folder.ensureFileFromRelativePath(path.substring(nextSlash, path.length), ignoreLoad); return file; } } async deleteFile(name) { const nameCanon = StorageUtilities_1.default.canonicalizeName(name); const file = this.files[nameCanon]; if (file !== undefined) { return await file.deleteThisFile(); } this.files[nameCanon] = undefined; return false; } removeFolder(name) { const nameCanon = StorageUtilities_1.default.canonicalizeName(name); if (!Utilities_1.default.isUsableAsObjectKey(nameCanon)) { throw new Error(); } const exists = this.folders[nameCanon] !== undefined; this.folders[nameCanon] = undefined; return exists; } async rename(name) { let targetPath = name; if (this.parentFolder !== null) { targetPath = this.storage.joinPath(this.parentFolder.storageRelativePath, targetPath); } return await this.moveTo(targetPath); } async recursiveDeleteThisFolder() { let isAllDeletes = await this.recursiveDeleteContentsOfThisFolder(); this.removeMeFromParent(); return isAllDeletes; } async recursiveDeleteContentsOfThisFolder() { let isAllDeletes = true; await this.load(true); for (const folderName in this.folders) { const folder = this.folders[folderName]; if (folder) { if (!(await folder.deleteThisFolder())) { isAllDeletes = false; } } } for (const fileName in this.files) { const file = this.files[fileName]; if (file) { if (!(await file.deleteThisFile(true))) { isAllDeletes = false; } } } return isAllDeletes; } notifyFolderMoved(folderMove) { this.#onFolderMoved.dispatch(this, folderMove); if (this.parentFolder) { this.parentFolder.notifyChildFolderMoved(folderMove); } this.storage.notifyFolderMoved(folderMove); } notifyChildFolderMoved(folderMove) { this.#onChildFolderMoved.dispatch(this, folderMove); if (this.parentFolder) { this.parentFolder.notifyChildFolderMoved(folderMove); } } removeMeFromParent() { if (this.parentFolder) { this.parentFolder.removeFolder(this.name); } } } exports.default = FolderBase;