UNPKG

@nomiclabs/buidler

Version:

Buidler is an extensible developer tool that helps smart contract developers increase productivity by reliably bringing together the tools they want.

166 lines 7.82 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const fs_extra_1 = __importDefault(require("fs-extra")); const path_1 = __importDefault(require("path")); const slash_1 = __importDefault(require("slash")); const errors_1 = require("../core/errors"); const errors_list_1 = require("../core/errors-list"); class ResolvedFile { constructor(globalName, absolutePath, content, // IMPORTANT: Mapped to ctime, NOT mtime. mtime isn't updated when the file // properties (e.g. its name) are changed, only when it's content changes. lastModificationDate, libraryName, libraryVersion) { this.globalName = globalName; this.absolutePath = absolutePath; this.content = content; this.lastModificationDate = lastModificationDate; this.globalName = globalName; this.absolutePath = absolutePath; this.content = content; this.lastModificationDate = lastModificationDate; if (libraryName !== undefined && libraryVersion !== undefined) { this.library = { name: libraryName, version: libraryVersion, }; } } getVersionedName() { return (this.globalName + (this.library !== undefined ? `@v${this.library.version}` : "")); } } exports.ResolvedFile = ResolvedFile; class Resolver { constructor(projectRoot) { this._projectRoot = projectRoot; } async resolveProjectSourceFile(pathToResolve) { if (!(await fs_extra_1.default.pathExists(pathToResolve))) { throw new errors_1.BuidlerError(errors_list_1.ERRORS.RESOLVER.FILE_NOT_FOUND, { file: pathToResolve, }); } const absolutePath = await fs_extra_1.default.realpath(pathToResolve); if (!absolutePath.startsWith(this._projectRoot)) { throw new errors_1.BuidlerError(errors_list_1.ERRORS.RESOLVER.FILE_OUTSIDE_PROJECT, { file: pathToResolve, }); } if (absolutePath.includes("node_modules")) { throw new errors_1.BuidlerError(errors_list_1.ERRORS.RESOLVER.LIBRARY_FILE_NOT_LOCAL, { file: pathToResolve, }); } const globalName = slash_1.default(absolutePath.slice(this._projectRoot.length + 1)); return this._resolveFile(globalName, absolutePath); } async resolveLibrarySourceFile(globalName) { const libraryName = this._getLibraryName(globalName); let packagePath; try { packagePath = this._resolveFromProjectRoot(path_1.default.join(libraryName, "package.json")); } catch (error) { // if the project is using a dependency from buidler itself but it can't be found, this means that a global // installation is being used, so we resolve the dependency relative to this file if (libraryName === "@nomiclabs/buidler") { return this._resolveBuidlerDependency(globalName, libraryName); } throw new errors_1.BuidlerError(errors_list_1.ERRORS.RESOLVER.LIBRARY_NOT_INSTALLED, { library: libraryName, }, error); } let absolutePath; try { absolutePath = this._resolveFromProjectRoot(globalName); } catch (error) { throw new errors_1.BuidlerError(errors_list_1.ERRORS.RESOLVER.LIBRARY_FILE_NOT_FOUND, { file: globalName, }, error); } const libraryPath = path_1.default.dirname(packagePath); if (!absolutePath.startsWith(libraryPath)) { // If it's still from a library with the same name what is happening is // that the package.json and the file are being resolved to different // installations of the library. This can lead to very confusing // situations, so we only use the closes installation if (absolutePath.includes(path_1.default.join("node_modules", libraryName))) { throw new errors_1.BuidlerError(errors_list_1.ERRORS.RESOLVER.LIBRARY_FILE_NOT_FOUND, { file: globalName, }); } throw new errors_1.BuidlerError(errors_list_1.ERRORS.RESOLVER.FILE_OUTSIDE_LIB, { file: globalName, library: libraryName, }); } const packageInfo = await fs_extra_1.default.readJson(packagePath); const libraryVersion = packageInfo.version; return this._resolveFile(globalName, absolutePath, libraryName, libraryVersion); } async resolveImport(from, imported) { try { if (this._isRelativeImport(imported)) { if (from.library === undefined) { return await this.resolveProjectSourceFile(path_1.default.normalize(path_1.default.join(path_1.default.dirname(from.absolutePath), imported))); } const globalName = slash_1.default(path_1.default.normalize(path_1.default.join(path_1.default.dirname(from.globalName), imported))); const isIllegal = !globalName.startsWith(`${from.library.name}/`); if (isIllegal) { throw new errors_1.BuidlerError(errors_list_1.ERRORS.RESOLVER.ILLEGAL_IMPORT, { imported, from: from.globalName, }); } imported = globalName; } return await this.resolveLibrarySourceFile(imported); } catch (error) { if (error.number === errors_list_1.ERRORS.RESOLVER.FILE_NOT_FOUND.number || error.number === errors_list_1.ERRORS.RESOLVER.LIBRARY_FILE_NOT_FOUND.number) { throw new errors_1.BuidlerError(errors_list_1.ERRORS.RESOLVER.IMPORTED_FILE_NOT_FOUND, { imported, from: from.globalName, }, error); } // tslint:disable-next-line only-buidler-error throw error; } } async _resolveFile(globalName, absolutePath, libraryName, libraryVersion) { const content = await fs_extra_1.default.readFile(absolutePath, { encoding: "utf8" }); const stats = await fs_extra_1.default.stat(absolutePath); const lastModificationDate = new Date(stats.ctime); return new ResolvedFile(globalName, absolutePath, content, lastModificationDate, libraryName, libraryVersion); } async _resolveBuidlerDependency(globalName, libraryName) { const buidlerCoreDir = path_1.default.join(__dirname, "..", ".."); const packagePath = path_1.default.join(buidlerCoreDir, "package.json"); const absolutePath = path_1.default.join(buidlerCoreDir, path_1.default.relative(libraryName, globalName)); const packageInfo = await fs_extra_1.default.readJson(packagePath); const libraryVersion = packageInfo.version; return this._resolveFile(globalName, absolutePath, libraryName, libraryVersion); } _isRelativeImport(imported) { return imported.startsWith("./") || imported.startsWith("../"); } _resolveFromProjectRoot(fileName) { return require.resolve(fileName, { paths: [this._projectRoot], }); } _getLibraryName(globalName) { if (globalName.startsWith("@")) { return globalName.slice(0, globalName.indexOf("/", globalName.indexOf("/") + 1)); } return globalName.slice(0, globalName.indexOf("/")); } } exports.Resolver = Resolver; //# sourceMappingURL=resolver.js.map