This repository has been archived by the owner on Feb 26, 2024. It is now read-only.
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1851 from tagomaru/support-global-npm
Improvement: Support globally installed npm
- Loading branch information
Showing
8 changed files
with
257 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
const path = require("path"); | ||
const fs = require("fs"); | ||
const detectInstalled = require("detect-installed"); | ||
const get_installed_path = require("get-installed-path"); | ||
function GlobalNPM() {} | ||
|
||
GlobalNPM.prototype.require = function(import_path) { | ||
if (import_path.indexOf(".") === 0 || path.isAbsolute(import_path)) { | ||
return null; | ||
} | ||
const contract_name = path.basename(import_path, ".sol"); | ||
|
||
let [package_name] = import_path.split("/", 1); | ||
if (detectInstalled.sync(package_name)) { | ||
const regex = new RegExp(`/${package_name}$`); | ||
const global_package_path = get_installed_path | ||
.getInstalledPathSync(package_name) | ||
.replace(regex, ""); | ||
const expected_path = path.join( | ||
global_package_path, | ||
package_name, | ||
"build", | ||
"contracts", | ||
contract_name + ".json" | ||
); | ||
try { | ||
const result = fs.readFileSync(expected_path, "utf8"); | ||
return JSON.parse(result); | ||
} catch (e) { | ||
return null; | ||
} | ||
} | ||
}; | ||
|
||
GlobalNPM.prototype.resolve = function(import_path, imported_from, callback) { | ||
let [package_name] = import_path.split("/", 1); | ||
let body; | ||
if (detectInstalled.sync(package_name)) { | ||
const regex = new RegExp(`/${package_name}$`); | ||
const global_package_path = get_installed_path | ||
.getInstalledPathSync(package_name) | ||
.replace(regex, ""); | ||
const expected_path = path.join(global_package_path, import_path); | ||
try { | ||
body = fs.readFileSync(expected_path, { encoding: "utf8" }); | ||
} catch (err) {} | ||
} | ||
|
||
// If nothing's found, body returns `undefined` | ||
return callback(null, body, import_path); | ||
}; | ||
|
||
// We're resolving package paths to other package paths, not absolute paths. | ||
// This will ensure the source fetcher conintues to use the correct sources for packages. | ||
// i.e., if some_module/contracts/MyContract.sol imported "./AnotherContract.sol", | ||
// we're going to resolve it to some_module/contracts/AnotherContract.sol, ensuring | ||
// that when this path is evaluated this source is used again. | ||
GlobalNPM.prototype.resolve_dependency_path = function( | ||
import_path, | ||
dependency_path | ||
) { | ||
var dirname = path.dirname(import_path); | ||
return path.join(dirname, dependency_path); | ||
}; | ||
|
||
GlobalNPM.prototype.provision_contracts = function(callback) { | ||
// TODO: Fill this out! | ||
callback(null, {}); | ||
}; | ||
|
||
module.exports = GlobalNPM; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
1 change: 1 addition & 0 deletions
1
...s/truffle-resolver/test/fixtures/globalnpm/node_modules/package/build/contracts/Test.json
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
1 change: 1 addition & 0 deletions
1
packages/truffle-resolver/test/fixtures/globalnpm/node_modules/package/contracts/Test.sol
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
const assert = require("assert"); | ||
const GlobalNPM = require("../globalnpm"); | ||
const global_npm = new GlobalNPM(); | ||
const detectInstalled = require("detect-installed"); | ||
const get_installed_path = require("get-installed-path"); | ||
const sinon = require("sinon"); | ||
const path = require("path"); | ||
const fs = require("fs"); | ||
|
||
describe("globalnpm", () => { | ||
describe("require function", () => { | ||
let sync_stub; | ||
let get_installed_path_sync_stub; | ||
|
||
beforeEach(() => { | ||
sync_stub = sinon.stub(detectInstalled, "sync"); | ||
get_installed_path_sync_stub = sinon.stub( | ||
get_installed_path, | ||
"getInstalledPathSync" | ||
); | ||
}); | ||
|
||
afterEach(() => { | ||
sync_stub.restore(); | ||
get_installed_path_sync_stub.restore(); | ||
}); | ||
|
||
it("should return null if the import_path starts with '.'", () => { | ||
const result = global_npm.require("./A.sol"); | ||
assert.deepEqual(result, null); | ||
}); | ||
|
||
it("should return null if the import_path is absolute path", () => { | ||
const result = global_npm.require("/A.sol"); | ||
assert.deepEqual(result, null); | ||
}); | ||
|
||
it("should return the contents of json if the import_path exists", () => { | ||
sync_stub.withArgs("package").returns(true); | ||
get_installed_path_sync_stub | ||
.withArgs("package") | ||
.returns( | ||
path.resolve(__dirname, "fixtures/globalnpm/node_modules/package") | ||
); | ||
|
||
const result = global_npm.require("package/contracts/Test.sol"); | ||
|
||
assert.deepEqual(result, {}); | ||
}); | ||
|
||
it("should return undefined if the import_path does not exist", () => { | ||
const read_file_sync_stub = sinon.stub(fs, "readFileSync"); | ||
|
||
sync_stub.withArgs("package").returns(false); | ||
|
||
const result = global_npm.require("package/contracts/Test.sol"); | ||
|
||
assert.ok(!get_installed_path_sync_stub.called); | ||
assert.deepEqual(result, undefined); | ||
|
||
read_file_sync_stub.restore(); | ||
}); | ||
|
||
it("should return null if readFileSync throws Error", () => { | ||
const read_file_sync_stub = sinon.stub(fs, "readFileSync"); | ||
|
||
sync_stub.withArgs("package").returns(true); | ||
get_installed_path_sync_stub | ||
.withArgs("package") | ||
.returns( | ||
path.resolve(__dirname, "fixtures/globalnpm/node_modules/package") | ||
); | ||
read_file_sync_stub.throws("some error"); | ||
|
||
const result = global_npm.require("package/contracts/Test.sol"); | ||
|
||
assert.deepEqual(result, null); | ||
|
||
read_file_sync_stub.restore(); | ||
}); | ||
}); | ||
|
||
describe("resolve function", () => { | ||
let sync_stub; | ||
let get_installed_path_sync_stub; | ||
|
||
beforeEach(() => { | ||
sync_stub = sinon.stub(detectInstalled, "sync"); | ||
get_installed_path_sync_stub = sinon.stub( | ||
get_installed_path, | ||
"getInstalledPathSync" | ||
); | ||
}); | ||
|
||
afterEach(() => { | ||
sync_stub.restore(); | ||
get_installed_path_sync_stub.restore(); | ||
}); | ||
|
||
it("should return the contents of solidity file if the import_path exists", () => { | ||
sync_stub.withArgs("package").returns(true); | ||
get_installed_path_sync_stub | ||
.withArgs("package") | ||
.returns( | ||
path.resolve(__dirname, "fixtures/globalnpm/node_modules/package") | ||
); | ||
|
||
const callback = (err, body, import_path) => { | ||
assert.strictEqual(err, null); | ||
assert.strictEqual(body, "contract Test {}\n"); | ||
assert.strictEqual(import_path, "package/contracts/Test.sol"); | ||
}; | ||
|
||
global_npm.resolve( | ||
"package/contracts/Test.sol", | ||
"imported_from", | ||
callback | ||
); | ||
}); | ||
|
||
it("should return undefined body if the package does not exist", () => { | ||
sync_stub.withArgs("package").returns(false); | ||
get_installed_path_sync_stub | ||
.withArgs("package") | ||
.returns( | ||
path.resolve(__dirname, "fixtures/globalnpm/node_modules/package") | ||
); | ||
|
||
const callback = (err, body, import_path) => { | ||
assert.strictEqual(err, null); | ||
assert.strictEqual(body, undefined); | ||
assert.strictEqual(import_path, "package/contracts/Test.sol"); | ||
}; | ||
|
||
global_npm.resolve( | ||
"package/contracts/Test.sol", | ||
"imported_from", | ||
callback | ||
); | ||
}); | ||
|
||
it("should return undefined body if readFileSync throws Error", () => { | ||
const read_file_sync_stub = sinon.stub(fs, "readFileSync"); | ||
|
||
sync_stub.withArgs("package").returns(true); | ||
get_installed_path_sync_stub | ||
.withArgs("package") | ||
.returns( | ||
path.resolve(__dirname, "fixtures/globalnpm/node_modules/package") | ||
); | ||
read_file_sync_stub.throws("some error"); | ||
|
||
const callback = (err, body, import_path) => { | ||
assert.strictEqual(err, null); | ||
assert.strictEqual(body, undefined); | ||
assert.strictEqual(import_path, "package/contracts/Test.sol"); | ||
}; | ||
|
||
global_npm.resolve( | ||
"package/contracts/Test.sol", | ||
"imported_from", | ||
callback | ||
); | ||
|
||
read_file_sync_stub.restore(); | ||
}); | ||
}); | ||
}); |