-
Notifications
You must be signed in to change notification settings - Fork 192
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fixes #168 Co-authored-by: Maël Nison <nison.mael@gmail.com>
- Loading branch information
Showing
11 changed files
with
216 additions
and
1 deletion.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
/* | ||
MIT License http://www.opensource.org/licenses/mit-license.php | ||
Author Maël Nison @arcanis | ||
*/ | ||
|
||
"use strict"; | ||
|
||
module.exports = class PnpPlugin { | ||
constructor(source, pnpApi, target) { | ||
this.source = source; | ||
this.pnpApi = pnpApi; | ||
this.target = target; | ||
} | ||
|
||
apply(resolver) { | ||
const target = resolver.ensureHook(this.target); | ||
resolver | ||
.getHook(this.source) | ||
.tapAsync("PnpPlugin", (request, resolveContext, callback) => { | ||
const req = request.request; | ||
|
||
// The trailing slash indicates to PnP that this value is a folder rather than a file | ||
const issuer = `${request.path}/`; | ||
|
||
let resolution; | ||
try { | ||
resolution = this.pnpApi.resolveToUnqualified(req, issuer, { | ||
considerBuiltins: false | ||
}); | ||
} catch (error) { | ||
return callback(error); | ||
} | ||
|
||
if (resolution === req) return callback(); | ||
|
||
const obj = { | ||
...request, | ||
path: resolution, | ||
request: undefined, | ||
ignoreSymlinks: true | ||
}; | ||
resolver.doResolve( | ||
target, | ||
obj, | ||
`resolved by pnp to ${resolution}`, | ||
resolveContext, | ||
(err, result) => { | ||
if (err) return callback(err); | ||
if (result) return callback(null, result); | ||
// Skip alternatives | ||
return callback(null, null); | ||
} | ||
); | ||
}); | ||
} | ||
}; |
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
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
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,7 @@ | ||
{ | ||
"main": "main.js", | ||
"browser": { | ||
"./package-alias/index.js": "./package-alias/browser.js", | ||
"module": "pkg/dir/index" | ||
} | ||
} |
Empty file.
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,137 @@ | ||
const path = require("path"); | ||
const fs = require("fs"); | ||
require("should"); | ||
const ResolverFactory = require("../lib/ResolverFactory"); | ||
const CachedInputFileSystem = require("../lib/CachedInputFileSystem"); | ||
|
||
const nodeFileSystem = new CachedInputFileSystem(fs, 4000); | ||
|
||
const fixture = path.resolve(__dirname, "fixtures", "pnp"); | ||
|
||
let isAdmin = false; | ||
try { | ||
fs.symlinkSync("dir", path.resolve(fixture, "pkg/symlink"), "dir"); | ||
isAdmin = true; | ||
} catch (e) { | ||
// ignore | ||
} | ||
try { | ||
fs.unlinkSync(path.resolve(fixture, "pkg/symlink")); | ||
} catch (e) { | ||
isAdmin = false; | ||
// ignore | ||
} | ||
|
||
describe("pnp", () => { | ||
let pnpApi; | ||
let resolver; | ||
if (isAdmin) { | ||
before(() => { | ||
fs.symlinkSync("dir", path.resolve(fixture, "pkg/symlink"), "dir"); | ||
}); | ||
after(() => { | ||
fs.unlinkSync(path.resolve(fixture, "pkg/symlink")); | ||
}); | ||
} | ||
beforeEach(() => { | ||
pnpApi = { | ||
mocks: new Map(), | ||
resolveToUnqualified(request, issuer) { | ||
if (pnpApi.mocks.has(request)) { | ||
return pnpApi.mocks.get(request); | ||
} else { | ||
throw new Error(`No way`); | ||
} | ||
} | ||
}; | ||
resolver = ResolverFactory.createResolver({ | ||
extensions: [".ts", ".js"], | ||
aliasFields: ["browser"], | ||
fileSystem: nodeFileSystem, | ||
pnpApi | ||
}); | ||
}); | ||
it("should resolve by going through the pnp api", done => { | ||
pnpApi.mocks.set( | ||
"pkg/dir/index.js", | ||
path.resolve(fixture, "pkg/dir/index.js") | ||
); | ||
resolver.resolve({}, __dirname, "pkg/dir/index.js", {}, (err, result) => { | ||
if (err) return done(err); | ||
result.should.equal(path.resolve(fixture, "pkg/dir/index.js")); | ||
done(); | ||
}); | ||
}); | ||
it("should resolve module names with package.json", done => { | ||
pnpApi.mocks.set("pkg", path.resolve(fixture, "pkg")); | ||
resolver.resolve({}, __dirname, "pkg", {}, (err, result) => { | ||
if (err) return done(err); | ||
result.should.equal(path.resolve(fixture, "pkg/main.js")); | ||
done(); | ||
}); | ||
}); | ||
it("should resolve namespaced module names", done => { | ||
pnpApi.mocks.set("@user/pkg", path.resolve(fixture, "pkg")); | ||
resolver.resolve({}, __dirname, "@user/pkg", {}, (err, result) => { | ||
if (err) return done(err); | ||
result.should.equal(path.resolve(fixture, "pkg/main.js")); | ||
done(); | ||
}); | ||
}); | ||
it( | ||
"should not resolve symlinks", | ||
isAdmin | ||
? done => { | ||
pnpApi.mocks.set("pkg/symlink", path.resolve(fixture, "pkg/symlink")); | ||
resolver.resolve({}, __dirname, "pkg/symlink", {}, (err, result) => { | ||
if (err) return done(err); | ||
result.should.equal(path.resolve(fixture, "pkg/symlink/index.js")); | ||
done(); | ||
}); | ||
} | ||
: undefined | ||
); | ||
it("should properly deal with other extensions", done => { | ||
pnpApi.mocks.set( | ||
"@user/pkg/typescript", | ||
path.resolve(fixture, "pkg/typescript") | ||
); | ||
resolver.resolve( | ||
{}, | ||
__dirname, | ||
"@user/pkg/typescript", | ||
{}, | ||
(err, result) => { | ||
if (err) return done(err); | ||
result.should.equal(path.resolve(fixture, "pkg/typescript/index.ts")); | ||
done(); | ||
} | ||
); | ||
}); | ||
it("should properly deal package.json alias", done => { | ||
pnpApi.mocks.set( | ||
"pkg/package-alias", | ||
path.resolve(fixture, "pkg/package-alias") | ||
); | ||
resolver.resolve({}, __dirname, "pkg/package-alias", {}, (err, result) => { | ||
if (err) return done(err); | ||
result.should.equal( | ||
path.resolve(fixture, "pkg/package-alias/browser.js") | ||
); | ||
done(); | ||
}); | ||
}); | ||
it("should skip normal modules when pnp resolves", done => { | ||
pnpApi.mocks.set("m1/a.js", path.resolve(fixture, "pkg/a.js")); | ||
resolver.resolve( | ||
{}, | ||
path.resolve(__dirname, "fixtures"), | ||
"m1/a.js", | ||
{}, | ||
(err, result) => { | ||
if (!err) return done(new Error("Resolving should fail")); | ||
done(); | ||
} | ||
); | ||
}); | ||
}); |