UNPKG

@minecraft/creator-tools

Version:

Minecraft Creator Tools command line and libraries.

296 lines (294 loc) 11.2 kB
"use strict"; // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. Object.defineProperty(exports, "__esModule", { value: true }); const FileSystemFile_1 = require("./FileSystemFile"); const FileSystemStorage_1 = require("./FileSystemStorage"); const StorageUtilities_1 = require("./StorageUtilities"); const Utilities_1 = require("./../core/Utilities"); const Log_1 = require("./../core/Log"); const FolderBase_1 = require("./FolderBase"); class FileSystemFolder extends FolderBase_1.default { get handle() { return this._handle; } set handle(newHandle) { this._handle = newHandle; } get writeHandle() { return this._writeHandle; } set writeHandle(newHandle) { this._writeHandle = newHandle; } get storage() { return this._storage; } get parentFolder() { return this._parentFolder; } get name() { return this._name; } get fullPath() { return (this._parentPath + FileSystemStorage_1.default.fileSystemFolderDelimiter + StorageUtilities_1.default.canonicalizeName(this.name)); } constructor(storage, parentFolder, parentPath, folderName, handle) { super(); this._storage = storage; this._parentFolder = parentFolder; this._handle = handle; this._writeHandle = handle; this._parentPath = parentPath; this._name = folderName; this._lastSavedContent = ""; this.lastSavedFileCount = 0; this.folders = {}; this.files = {}; } async getIsEmptyError(depth, processedFolders) { if (depth && depth > 10) { return "Folder hierarchy is too deep."; } await this.load(false); for (const fileName in this.files) { return "Folder '" + this.fullPath + "' is not empty."; } const folderCount = this.folderCount; processedFolders = processedFolders === undefined ? folderCount : processedFolders + this.folderCount; if (folderCount > 1000) { return "Folder hierarchy is too complex. (" + folderCount + " folders)"; } if (processedFolders > 4000) { return "Too many folders to process in this folder."; } for (const folderName in this.folders) { const folder = this.folders[folderName]; if (folder) { const result = await folder.getFirstUnsafeError(depth === undefined ? 1 : depth + 1, processedFolders); if (result !== undefined) { return result; } } } return undefined; } async getFirstUnsafeError(depth, processedFolders) { if (depth && depth > 10) { return "Folder hierarchy is too deep."; } await this.load(false); for (const fileName in this.files) { if (!StorageUtilities_1.default.isUsableFile(fileName)) { return "Cannot work with '" + this.fullPath + fileName + "'"; } } const folderCount = this.folderCount; processedFolders = processedFolders === undefined ? folderCount : processedFolders + this.folderCount; if (folderCount > 1000) { return "Folder hierarchy is too complex. (" + folderCount + " folders)"; } if (processedFolders > 4000) { return "Too many folders to process in this folder."; } for (const folderName in this.folders) { const folder = this.folders[folderName]; if (folder) { const result = await folder.getFirstUnsafeError(depth === undefined ? 1 : depth + 1, processedFolders); if (result !== undefined) { return result; } } } return undefined; } ensureFile(name, file) { const nameCanon = StorageUtilities_1.default.canonicalizeName(name); let candFile = this.files[nameCanon]; if (candFile == null) { candFile = new FileSystemFile_1.default(this, name); this.files[nameCanon] = candFile; this.storage.notifyFileAdded(candFile); } if (file) { candFile.handle = file; candFile.writeHandle = file; } return candFile; } async exists() { return true; } async ensureExists() { return true; } ensureFolder(name, handle) { const nameCanon = StorageUtilities_1.default.canonicalizeName(name); let candFolder = this.folders[nameCanon]; if (!candFolder) { candFolder = new FileSystemFolder(this._storage, this, this.fullPath, name); this.folders[nameCanon] = candFolder; } if (handle) { candFolder.handle = handle; } return candFolder; } _removeFile(file) { const nameCanon = StorageUtilities_1.default.canonicalizeName(file.name); const candFile = this.files[nameCanon]; Log_1.default.assert(candFile === file, "Files don't match."); this.files[nameCanon] = undefined; this.storage.notifyFileRemoved(this.storageRelativePath + file.name); } async deleteThisFolder() { throw new Error("Deletion of this folder " + this.fullPath + " is not supported."); } async deleteAllFolderContents() { throw new Error("Deletion of all folder contents at " + this.fullPath + " is not supported."); } async _removeFileExistence(fileName) { const handle = await this.getHandle(); await handle?.removeEntry(fileName, { recursive: false, }); } _addExistingFile(file) { const nameCanon = StorageUtilities_1.default.canonicalizeName(file.name); this.files[nameCanon] = file; } _addExistingFolder(folder) { const nameCanon = StorageUtilities_1.default.canonicalizeName(folder.name); this.folders[nameCanon] = folder; } async moveTo(newStorageRelativePath) { const newFolderPath = StorageUtilities_1.default.getFolderPath(newStorageRelativePath); const newFolderName = StorageUtilities_1.default.getLeafName(newStorageRelativePath); if (newFolderName.length < 2) { throw new Error("New path is not correct."); } if (this.isSameFolder(newStorageRelativePath)) { return false; } if (this._parentFolder !== null) { const newParentFolder = await this._parentFolder.storage.ensureFolderFromStorageRelativePath(newFolderPath); if (newParentFolder.folders[newFolderName] !== undefined) { throw new Error("Folder exists at specified path."); } this._parentFolder._clearExistingFolder(this); this._parentFolder = newParentFolder; this._name = newFolderName; newParentFolder._addExistingFolder(this); } this._name = newFolderName; if (this._parentFolder !== null) { await this._parentFolder.save(true); } throw new Error("Not implemented."); //return true; } async createFile(name) { const file = this.ensureFile(name); this.storage.notifyFileAdded(file); return file; } async getHandle() { if (!this._handle) { if (this._writeHandle) { return this._writeHandle; } if (this.parentFolder) { const parentFolderHandle = await this.parentFolder.getHandle(); if (parentFolderHandle) { try { this._handle = await parentFolderHandle.getDirectoryHandle(this.name, { create: false, }); } catch (e) { // Log.debugAlert("Folder r/o retrieval: " + e); return undefined; } } } } return this._handle; } async ensureWriteHandle() { if (!this._writeHandle) { if (this.parentFolder) { await this.parentFolder.ensureWriteHandle(); if (this.parentFolder.writeHandle) { try { this._writeHandle = await this.parentFolder.writeHandle.getDirectoryHandle(this.name, { create: true, }); } catch (e) { Log_1.default.debugAlert("Folder r/w retrieval: " + e); } } } } Log_1.default.assert(this._writeHandle !== undefined, "No folder handle."); return this._writeHandle; } async load(force) { if (this.lastLoadedOrSaved != null && !force) { return this.lastLoadedOrSaved; } const handle = await this.getHandle(); if (handle) { for await (const [key, value] of handle.entries()) { if (value.kind === "file") { this.ensureFile(key, value); } else if (value.kind === "directory") { const keyLower = key.toLowerCase(); if (keyLower !== ".git" && keyLower !== "node_modules") { this.ensureFolder(key, value); } } } } this.updateLastLoadedOrSaved(); return this.lastLoadedOrSaved; } async save(force) { this.updateLastLoadedOrSaved(); const folderState = { updated: this.lastLoadedOrSaved, files: [], folders: [], }; for (const fileName in this.files) { const file = this.files[fileName]; if (file !== undefined) { const fileState = { name: file.name, size: file.size, modified: file.latestModified == null ? new Date() : file.latestModified, }; folderState.files.push(fileState); } } for (const folderName in this.folders) { const childFolder = this.folders[folderName]; if (childFolder !== undefined && !childFolder.errorStatus) { const childFolderState = { name: childFolder.name, fileCount: Utilities_1.default.lengthOfDictionary(childFolder.files), modified: childFolder.modifiedAtLoad == null ? new Date() : childFolder.modifiedAtLoad, }; folderState.folders.push(childFolderState); } } const saveContent = JSON.stringify(folderState); if (this._lastSavedContent !== saveContent || force) { // await localforage.setItem<string>(this.fullPath + FileSystemStorage.folderDelimiter, saveContent); } return this.lastLoadedOrSaved; } } exports.default = FileSystemFolder; //# sourceMappingURL=../maps/storage/FileSystemFolder.js.map