UNPKG

novaparse

Version:
216 lines 9.92 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); const fs = require("fs"); const path = require("path"); const readNovaFile_1 = require("./readNovaFile"); const ResourceHolderBase_1 = require("./ResourceHolderBase"); class BadDirectoryStructureError extends Error { } exports.BadDirectoryStructureError = BadDirectoryStructureError; ; //const log = console.log; const log = (_m) => { }; // Parses Nova Files and Plug-ins into resources // without dealing with the interactions that resources might // have with one another. A resource that references another resource // will not use a globalID to do so. Also, ships, which, if they don't have // a PICT available, will instead use the pict of the last ship to // have the same baseImage, are not linked to the correct PICT at this stage. // All interactions are handled by NovaParse.ts class IDSpaceHandler { constructor(novaPath) { this.tmpBuildingResources = ResourceHolderBase_1.getEmptyNovaResources(); this.globalResources = this.build(novaPath).catch((e) => { // Catch all promise rejections. They are instead handled when getting ID spaces. return e; }); } build(novaPath) { return __awaiter(this, void 0, void 0, function* () { var novaFilesPath = path.join(novaPath, "Nova\ Files/"); var novaPluginsPath = path.join(novaPath, "Plug-ins/"); yield this.addNovaFilesDirectory(novaFilesPath); yield this.addNovaPluginsDirectory(novaPluginsPath); return this.tmpBuildingResources; }); } // Returns the IDSpace of namespace 'prefix' getIDSpace(prefix = null) { return __awaiter(this, void 0, void 0, function* () { var result = yield this.globalResources; // May be an error if (result instanceof Error) { throw result; } return this.getIDSpaceUnsafe(prefix); }); } // Gets the ID Space without requiring that everything be parsed // An ID space is a NovaResource that is constrained to a specific namespace, such as "plugin 1." // When it's asked for resources, it prepends all IDs given to it with // either "plugin 1:" or "nova:" depending on whether or not the ID already exists in the "nova" // namespace. It is used by nova resource parsers to reference other nova resources because those // references must occur in the correct namespace. getIDSpaceUnsafe(prefix = null) { var globalResources = this.tmpBuildingResources; if (prefix == null) { return globalResources; } return new Proxy(globalResources, { get: (target, resourceType) => { if (typeof resourceType === "symbol") { console.warn("accessing resources by symbol"); return Reflect.get(target, resourceType); } var idList = Reflect.get(target, resourceType); if (!idList) { Reflect.set(target, resourceType, {}); var idList = Reflect.get(target, resourceType); } return new Proxy(idList, { // Replace requests for 324 with prefix:324 // or nova:324 if nova:324 exists get: (target, localID) => { if (typeof localID === "symbol") { console.warn("accessing ids by symbol"); return Reflect.get(target, localID); } var novaScopeValue = Reflect.get(target, "nova:" + localID); if (novaScopeValue) { return novaScopeValue; } else { var globalID = prefix + ":" + localID; return Reflect.get(target, globalID); } }, // Replace setting 324 with setting prefix:324 // or nova:324 if nova:324 exists set: (target, localID, value) => { if (typeof localID === "symbol") { throw new Error("Can't set by symbol"); } // Assume it exists in the nova prefix var usedPrefix = "nova"; var globalID = usedPrefix + ":" + localID; if (!Reflect.get(target, globalID)) { // It doesn't, so use its own prefix. usedPrefix = prefix; globalID = usedPrefix + ":" + localID; } // Setting the globalID here is necessary because // this is the only place where it is known whether the prefix // is "nova" or prefix. It's not the best practice... value.globalID = globalID; value.prefix = usedPrefix; return Reflect.set(target, globalID, value); } }); } }); } // Adds the Nova Plug-ins directory addNovaPluginsDirectory(pluginsPath) { return __awaiter(this, void 0, void 0, function* () { if (!(yield isDirectory(pluginsPath))) { throw new BadDirectoryStructureError("Plug-ins must be a directory. Got " + pluginsPath + " instead"); } if (!(path.basename(pluginsPath) == "Plug-ins")) { console.warn("Plug-ins parser given a directory called " + path.basename(pluginsPath) + " instead of Plug-ins"); } var fileNames = (yield readdir(pluginsPath)).reverse(); for (let i in fileNames) { var name = fileNames[i]; var currentPath = path.join(pluginsPath, name); var prefix = name.split(".")[0]; // Cut off extensions if (yield isDirectory(currentPath)) { log(currentPath + " is a directory"); yield this.addDirectory(currentPath, prefix); } else { yield this.addPlugin(currentPath, prefix); } } }); } // Adds the Nova Files directory addNovaFilesDirectory(filePath) { return __awaiter(this, void 0, void 0, function* () { if (!(yield isDirectory(filePath))) { throw new BadDirectoryStructureError("Nova Files must be a directory. Got " + filePath + " instead"); } yield this.addDirectory(filePath, "nova"); }); } // Adds a directory under a single ID prefix addDirectory(dirPath, prefix) { return __awaiter(this, void 0, void 0, function* () { if (!(yield isDirectory(dirPath))) { throw new BadDirectoryStructureError("Must be a directory. Got " + dirPath + " instead"); } log("Adding Directory of plugins " + dirPath); var fileNames = yield readdir(dirPath); for (let i in fileNames) { var name = fileNames[i]; var currentPath = path.join(dirPath, name); yield this.addPlugin(currentPath, prefix); } }); } // Adds a Nova Plug-in addPlugin(filePath, prefix) { return __awaiter(this, void 0, void 0, function* () { // Can't await this.getIDSpace because that causes an infinite loop // (getIDSpace awaits this.globalResources which depends on this function) var disallowedExtensions = new Set([".mp3", ".mov"]); if (disallowedExtensions.has(path.extname(filePath))) { return false; } log("Parsing " + filePath + " under prefix " + prefix); // This is the correct ID space because even though a plugin named, // for example, "cats", might have a resource that overwrites a nova resource, // that resource should still have access to all the other stuff in "cats" yield readNovaFile_1.readNovaFile(filePath, this.getIDSpaceUnsafe(prefix)); return true; }); } } exports.IDSpaceHandler = IDSpaceHandler; function isDirectory(path) { return new Promise(function (fulfill, reject) { fs.stat(path, (err, stats) => { if (err) { if (err.code == "ENOENT") { fulfill(false); } reject(err); } else { fulfill(stats.isDirectory()); } }); }); } // Returns a list of files or directories in a directory. function readdir(path) { return new Promise(function (fulfill, reject) { fs.readdir(path, function (err, files) { if (err) { reject(err); } else { fulfill(files.filter(function (p) { return p[0] !== '.'; })); } }); }); } //# sourceMappingURL=IDSpaceHandler.js.map