@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
JavaScript
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
;