UNPKG

@minecraft/creator-tools

Version:

Minecraft Creator Tools command line and libraries.

274 lines (272 loc) 11.3 kB
"use strict"; // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. Object.defineProperty(exports, "__esModule", { value: true }); const BrowserFile_1 = require("./BrowserFile"); const BrowserStorage_1 = require("./BrowserStorage"); const StorageUtilities_1 = require("./StorageUtilities"); const Utilities_1 = require("./../core/Utilities"); const Log_1 = require("./../core/Log"); const localforage_1 = require("localforage"); const FolderBase_1 = require("./FolderBase"); class BrowserFolder extends FolderBase_1.default { get storage() { return this._storage; } get parentFolder() { return this._parentFolder; } get name() { return this._name; } get fullPath() { return this._parentPath + BrowserStorage_1.default.slashFolderDelimiter + StorageUtilities_1.default.canonicalizeName(this.name); } constructor(storage, parentFolder, parentPath, folderName) { super(); this._storage = storage; this._parentFolder = parentFolder; this._parentPath = parentPath; this._name = folderName; this._lastSavedContent = ""; this.lastSavedFileCount = 0; this.folders = {}; this.files = {}; } ensureFile(name) { const nameCanon = StorageUtilities_1.default.canonicalizeName(name); let candFile = this.files[nameCanon]; if (candFile == null) { candFile = new BrowserFile_1.default(this, name); this.files[nameCanon] = candFile; this.storage.notifyFileAdded(candFile); } return candFile; } async exists() { return true; } async ensureExists() { return true; } async deleteThisFolder() { if (this.storage.readOnly) { throw new Error("Can't save read-only file."); } let result = await this.recursiveDeleteThisFolder(); await localforage_1.default.removeItem(this.fullPath + BrowserStorage_1.default.slashFolderDelimiter); return result; } async deleteAllFolderContents() { throw new Error("Deletion of all folder contents at " + this.fullPath + " is not supported."); } ensureFolder(name) { const nameCanon = StorageUtilities_1.default.canonicalizeName(name); let candFolder = this.folders[nameCanon]; if (!candFolder) { candFolder = new BrowserFolder(this._storage, this, this.fullPath, name); this.folders[nameCanon] = candFolder; } 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); } _addExistingFile(file) { const nameCanon = StorageUtilities_1.default.canonicalizeName(file.name); this.files[nameCanon] = file; } async moveTo(newStorageRelativePath, ignoreParentSave) { 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; } await this.load(); const oldPath = this._lastLoadedPath; 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; for (const fileName in this.files) { const file = this.files[fileName]; if (file) { await file.resaveAfterMove(); } } for (const folderName in this.folders) { const folder = this.folders[folderName]; if (folder) { await folder.resaveAfterMove(this.fullPath); } } await this.save(true); if (oldPath) { await localforage_1.default.removeItem(oldPath); } if (this._parentFolder !== null && !ignoreParentSave) { await this._parentFolder.save(true); } if (!ignoreParentSave) { this.notifyFolderMoved({ previousStoragePath: oldPath, newStoragePath: this.fullPath, folder: this }); } return true; } async createFile(name) { const file = this.ensureFile(name); this.storage.notifyFileAdded(file); return file; } async load(force) { if (this.lastLoadedOrSaved != null && !force) { return this.lastLoadedOrSaved; } this._lastLoadedPath = this.fullPath + BrowserStorage_1.default.slashFolderDelimiter; const listingContent = await localforage_1.default.getItem(this.fullPath + BrowserStorage_1.default.slashFolderDelimiter); if (listingContent != null) { this._lastSavedContent = listingContent; let folderState; try { folderState = JSON.parse(listingContent); } catch (e) { Log_1.default.debugAlert("Failure to parse browser folder content JSON:" + e.toString()); } if (folderState) { for (var i = 0; i < folderState.files.length; i++) { const fileMeta = folderState.files[i]; // JSON.parse doesn't fix up dates produced by JSON.stringify, so do that here. if (fileMeta.modified != null && !(fileMeta.modified instanceof Date)) { fileMeta.modified = new Date(fileMeta.modified); } const newFile = this.ensureFile(fileMeta.name); newFile.modifiedAtLoad = fileMeta.modified == null ? null : fileMeta.modified; if (newFile.sizeAtLoad === undefined) { newFile.sizeAtLoad = fileMeta.size; } } for (var j = 0; j < folderState.folders.length; j++) { const folderMeta = folderState.folders[j]; // JSON.parse doesn't fix up dates produced by JSON.stringify, so do that here. if (folderMeta.modified != null && !(folderMeta.modified instanceof Date)) { folderMeta.modified = new Date(folderMeta.modified); } const newFolder = this.ensureFolder(folderMeta.name); newFolder.modifiedAtLoad = folderMeta.modified; newFolder.lastSavedFileCount = folderMeta.fileCount; } } } this.updateLastLoadedOrSaved(); return this.lastLoadedOrSaved; } async resaveAfterMove(newParentPath) { this._parentPath = newParentPath; for (const fileName in this.files) { const file = this.files[fileName]; if (file) { await file.resaveAfterMove(); } } for (const folderName in this.folders) { const folder = this.folders[folderName]; if (folder) { await folder.resaveAfterMove(this.fullPath); } } if (this._lastLoadedPath === undefined) { return; } if (this._lastLoadedPath !== StorageUtilities_1.default.ensureEndsWithDelimiter(this.fullPath)) { const oldPath = this._lastLoadedPath; await this.save(true); await localforage_1.default.removeItem(oldPath); } } async save(force) { // we need to load before we save if the only thing this folder has seen is a bunch of // /ensures/ if (!this.isLoaded) { await this.load(false); } 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) { this._lastSavedContent = saveContent; this._lastLoadedPath = this.fullPath + BrowserStorage_1.default.slashFolderDelimiter; await localforage_1.default.setItem(this.fullPath + BrowserStorage_1.default.slashFolderDelimiter, saveContent); } return this.lastLoadedOrSaved; } async saveAll(force) { // Log.verbose("Saving all at " + this.storageRelativePath); if (this.isDisposed) { Log_1.default.throwIsDisposed(); } const initialDateTime = new Date().getTime(); let needsContentSave = false; for (const fileName in this.files) { const file = this.files[fileName]; if (file !== undefined && (file.needsSave || force)) { let newContentSaveDate = await file.saveContent(force, true); if (newContentSaveDate.getTime() > initialDateTime) { needsContentSave = true; } } } for (const folderName in this.folders) { const folder = this.folders[folderName]; if (folder !== undefined && !folder.errorStatus) { needsContentSave = true; await folder.saveAll(force); } } if (needsContentSave || this._lastSavedContent === undefined || force === true) { await this.save(force); } return true; } } exports.default = BrowserFolder; //# sourceMappingURL=../maps/storage/BrowserFolder.js.map