tsconfig-paths
Advanced tools
Comparing version 3.4.0 to 3.4.1
@@ -10,2 +10,8 @@ # Change Log | ||
## [3.4.1] - 2018-06-24 | ||
### Fixed | ||
Ignore field name mappings in package.json files that are not paths of existing files [#46](https://github.com/dividab/tsconfig-paths/pull/45). Thanks to [@christoffer](https://github.com/christoffer) for this fix! | ||
## [3.4.0] - 2018-06-12 | ||
@@ -243,3 +249,5 @@ | ||
[unreleased]: https://github.com/dividab/tsconfig-paths/compare/3.3.2...master | ||
[unreleased]: https://github.com/dividab/tsconfig-paths/compare/3.4.1...master | ||
[3.4.1]: https://github.com/dividab/tsconfig-paths/compare/3.4.0...3.4.1 | ||
[3.4.0]: https://github.com/dividab/tsconfig-paths/compare/3.3.2...3.4.0 | ||
[3.3.2]: https://github.com/dividab/tsconfig-paths/compare/3.3.1...3.3.2 | ||
@@ -246,0 +254,0 @@ [3.3.1]: https://github.com/dividab/tsconfig-paths/compare/3.3.0...3.3.1 |
@@ -7,3 +7,2 @@ "use strict"; | ||
var Filesystem = require("./filesystem"); | ||
var match_path_sync_1 = require("./match-path-sync"); | ||
/** | ||
@@ -35,2 +34,26 @@ * See the sync version for docs. | ||
exports.matchFromAbsolutePathsAsync = matchFromAbsolutePathsAsync; | ||
function findFirstExistingMainFieldMappedFile(packageJson, mainFields, packageJsonPath, fileExistsAsync, doneCallback, index) { | ||
if (index === void 0) { index = 0; } | ||
if (index >= mainFields.length) { | ||
return doneCallback(undefined, undefined); | ||
} | ||
var tryNext = function () { | ||
return findFirstExistingMainFieldMappedFile(packageJson, mainFields, packageJsonPath, fileExistsAsync, doneCallback, index + 1); | ||
}; | ||
var mainFieldMapping = packageJson[mainFields[index]]; | ||
if (typeof mainFieldMapping !== "string") { | ||
// Skip mappings that are not pointers to replacement files | ||
return tryNext(); | ||
} | ||
var mappedFilePath = path.join(path.dirname(packageJsonPath), mainFieldMapping); | ||
fileExistsAsync(mappedFilePath, function (err, exists) { | ||
if (err) { | ||
return doneCallback(err); | ||
} | ||
if (exists) { | ||
return doneCallback(undefined, mappedFilePath); | ||
} | ||
return tryNext(); | ||
}); | ||
} | ||
// Recursive loop to probe for physical files | ||
@@ -64,24 +87,24 @@ function findFirstExistingPath(tryPaths, readJson, fileExists, doneCallback, index, mainFields) { | ||
} | ||
var mainFieldName = match_path_sync_1.getPrioritizedMainFieldName(packageJson, mainFields); | ||
if (mainFieldName) { | ||
var file_1 = path.join(path.dirname(tryPath.path), packageJson[mainFieldName]); | ||
fileExists(file_1, function (err2, exists) { | ||
if (err2) { | ||
return doneCallback(err2); | ||
if (packageJson) { | ||
return findFirstExistingMainFieldMappedFile(packageJson, mainFields, tryPath.path, fileExists, function (mainFieldErr, mainFieldMappedFile) { | ||
if (mainFieldErr) { | ||
return doneCallback(mainFieldErr); | ||
} | ||
if (exists) { | ||
if (mainFieldMappedFile) { | ||
// Not sure why we don't just return the full path? Why strip it? | ||
return doneCallback(undefined, Filesystem.removeExtension(file_1)); | ||
return doneCallback(undefined, Filesystem.removeExtension(mainFieldMappedFile)); | ||
} | ||
// Continue with the next path | ||
// No field in package json was a valid option. Continue with the next path. | ||
return findFirstExistingPath(tryPaths, readJson, fileExists, doneCallback, index + 1, mainFields); | ||
}); | ||
} | ||
else { | ||
// This is async code, we need to return in an else-branch otherwise the code still falls through and keeps recursing. | ||
// While this might work in general, libraries that use neo-async like Webpack will actually not allow you to call the same callback twice. | ||
// An example of where this caused issues: https://github.com/dividab/tsconfig-paths-webpack-plugin/issues/11 | ||
// Continue with the next path | ||
return findFirstExistingPath(tryPaths, readJson, fileExists, doneCallback, index + 1, mainFields); | ||
} | ||
// This is async code, we need to return unconditionally, otherwise the code still falls | ||
// through and keeps recursing. While this might work in general, libraries that use neo-async | ||
// like Webpack will actually not allow you to call the same callback twice. | ||
// | ||
// An example of where this caused issues: | ||
// https://github.com/dividab/tsconfig-paths-webpack-plugin/issues/11 | ||
// | ||
// Continue with the next path | ||
return findFirstExistingPath(tryPaths, readJson, fileExists, doneCallback, index + 1, mainFields); | ||
}); | ||
@@ -88,0 +111,0 @@ } |
@@ -30,10 +30,1 @@ import * as Filesystem from "./filesystem"; | ||
export declare function matchFromAbsolutePaths(absolutePathMappings: ReadonlyArray<MappingEntry.MappingEntry>, requestedModule: string, readJson?: Filesystem.ReadJsonSync, fileExists?: Filesystem.FileExistsSync, extensions?: Array<string>, mainFields?: string[]): string | undefined; | ||
/** | ||
* Given a parsed package.json object, get the first field name that is defined | ||
* in a list of prioritized field names to try. | ||
* | ||
* @param packageJson Parsed JSON object from package.json. May be undefined. | ||
* @param mainFields A list of field names to try (in order) | ||
* @returns The first matched field name in packageJson, or undefined. | ||
*/ | ||
export declare function getPrioritizedMainFieldName(packageJson: Filesystem.PackageJson | undefined, mainFields: string[]): string | undefined; |
@@ -44,16 +44,10 @@ "use strict"; | ||
exports.matchFromAbsolutePaths = matchFromAbsolutePaths; | ||
/** | ||
* Given a parsed package.json object, get the first field name that is defined | ||
* in a list of prioritized field names to try. | ||
* | ||
* @param packageJson Parsed JSON object from package.json. May be undefined. | ||
* @param mainFields A list of field names to try (in order) | ||
* @returns The first matched field name in packageJson, or undefined. | ||
*/ | ||
function getPrioritizedMainFieldName(packageJson, mainFields) { | ||
if (packageJson) { | ||
for (var index = 0; index < mainFields.length; index++) { | ||
var mainFieldName = mainFields[index]; | ||
if (packageJson[mainFieldName]) { | ||
return mainFieldName; | ||
function findFirstExistingMainFieldMappedFile(packageJson, mainFields, packageJsonPath, fileExists) { | ||
for (var index = 0; index < mainFields.length; index++) { | ||
var mainFieldName = mainFields[index]; | ||
var candidateMapping = packageJson[mainFieldName]; | ||
if (candidateMapping && typeof candidateMapping === "string") { | ||
var candidateFilePath = path.join(path.dirname(packageJsonPath), candidateMapping); | ||
if (fileExists(candidateFilePath)) { | ||
return candidateFilePath; | ||
} | ||
@@ -64,3 +58,2 @@ } | ||
} | ||
exports.getPrioritizedMainFieldName = getPrioritizedMainFieldName; | ||
function findFirstExistingPath(tryPaths, readJson, fileExists, mainFields) { | ||
@@ -81,8 +74,7 @@ if (readJson === void 0) { readJson = Filesystem.readJsonFromDiskSync; } | ||
var packageJson = readJson(tryPath.path); | ||
var mainFieldName = getPrioritizedMainFieldName(packageJson, mainFields); | ||
if (mainFieldName) { | ||
var file = path.join(path.dirname(tryPath.path), packageJson[mainFieldName]); | ||
if (fileExists(file)) { | ||
if (packageJson) { | ||
var mainFieldMappedFile = findFirstExistingMainFieldMappedFile(packageJson, mainFields, tryPath.path, fileExists); | ||
if (mainFieldMappedFile) { | ||
// Not sure why we don't just return the full path? Why strip it? | ||
return Filesystem.removeExtension(file); | ||
return Filesystem.removeExtension(mainFieldMappedFile); | ||
} | ||
@@ -89,0 +81,0 @@ } |
{ | ||
"name": "tsconfig-paths", | ||
"version": "3.4.0", | ||
"version": "3.4.1", | ||
"description": "Load node modules according to tsconfig paths, in run-time or via API.", | ||
@@ -5,0 +5,0 @@ "main": "lib/index.js", |
@@ -0,0 +0,0 @@ # tsconfig-paths |
@@ -190,3 +190,6 @@ import { assert } from "chai"; | ||
); | ||
const existingPath = join("/root", "location", "mylib", "christoffer.ts"); | ||
const mainFilePath = join("/root", "location", "mylib", "kalle.ts"); | ||
const browserFilePath = join("/root", "location", "mylib", "browser.ts"); | ||
const existingFiles = [mainFilePath, browserFilePath]; | ||
matchPath( | ||
@@ -197,8 +200,9 @@ "lib/mylib", | ||
main: "./kalle.ts", | ||
browser: "./christoffer.ts" | ||
browser: "./browser.ts" | ||
}), | ||
(path, callback) => callback(undefined, path === existingPath), | ||
(path, callback) => | ||
callback(undefined, existingFiles.indexOf(path) !== -1), | ||
undefined, | ||
(_err, result) => { | ||
assert.equal(result, removeExtension(existingPath), result); | ||
assert.equal(result, removeExtension(browserFilePath), result); | ||
done(); | ||
@@ -209,2 +213,62 @@ } | ||
it("should not resolve field name mapped file that doesn't exist", done => { | ||
const matchPath = createMatchPathAsync( | ||
"/root/", | ||
{ | ||
"lib/*": ["location/*"] | ||
}, | ||
["browser", "main"] | ||
); | ||
const existingFile = join("/root", "location", "mylib", "kalle.ts"); | ||
matchPath( | ||
"lib/mylib", | ||
(_path, callback) => | ||
callback(undefined, { | ||
main: "./kalle.ts", | ||
browser: "./missing-file.ts" | ||
}), | ||
(path, callback) => callback(undefined, path === existingFile), | ||
undefined, | ||
(_err, result) => { | ||
assert.equal(result, removeExtension(existingFile), result); | ||
done(); | ||
} | ||
); | ||
}); | ||
it("should not resolve advanced field name mappings", done => { | ||
const matchPath = createMatchPathAsync( | ||
"/root/", | ||
{ | ||
"lib/*": ["location/*"] | ||
}, | ||
["browser", "main"] | ||
); | ||
const mainFilePath = join("/root", "location", "mylib", "kalle.ts"); | ||
const browserFilePath = join( | ||
"/root", | ||
"location", | ||
"mylib", | ||
"advanced-replacement.ts" | ||
); | ||
const existingFiles = [mainFilePath, browserFilePath]; | ||
matchPath( | ||
"lib/mylib", | ||
(_path, callback) => | ||
callback(undefined, { | ||
main: "./kalle.ts", | ||
browser: { mylib: "./advanced-replacement.ts" } | ||
}), | ||
(path, callback) => | ||
callback(undefined, existingFiles.indexOf(path) !== -1), | ||
undefined, | ||
(_err, result) => { | ||
assert.equal(result, removeExtension(mainFilePath), result); | ||
done(); | ||
} | ||
); | ||
}); | ||
it("should resolve to with the help of baseUrl when not explicitly set", done => { | ||
@@ -211,0 +275,0 @@ const matchPath = createMatchPathAsync("/root/", {}); |
@@ -121,7 +121,7 @@ import { assert } from "chai"; | ||
const matchPath = createMatchPath("/root/", { "lib/*": ["location/*"] }); | ||
const existingPath = join("/root", "location", "mylibjs", "kallejs"); | ||
const existingPath = join("/root", "location", "mylibjs", "kalle.js"); | ||
// Make sure we escape the "." | ||
const result = matchPath( | ||
"lib/mylibjs", | ||
(_: string) => ({ main: "./kallejs" }), | ||
(_: string) => ({ main: "./kalle.js" }), | ||
(name: string) => name === existingPath, | ||
@@ -131,3 +131,3 @@ [".ts", ".js"] | ||
assert.equal(result, existingPath); | ||
assert.equal(result, removeExtension(existingPath)); | ||
}); | ||
@@ -141,7 +141,30 @@ | ||
]); | ||
const existingPath = join("/root", "location", "mylibjs", "christofferjs"); | ||
const mainFilePath = join("/root", "location", "mylibjs", "main.js"); | ||
const browserFilePath = join("/root", "location", "mylibjs", "browser.js"); | ||
const existingPaths = [mainFilePath, browserFilePath]; | ||
// Make sure we escape the "." | ||
const result = matchPath( | ||
"lib/mylibjs", | ||
(_: string) => ({ main: "./kallejs", browser: "./christofferjs" }), | ||
(_: string) => ({ main: "./main.js", browser: "./browser.js" }), | ||
(name: string) => existingPaths.indexOf(name) !== -1, | ||
[".ts", ".js"] | ||
); | ||
assert.equal(result, removeExtension(browserFilePath)); | ||
}); | ||
it("should ignore field mappings to missing files in package.json", () => { | ||
const matchPath = createMatchPath("/root/", { "lib/*": ["location/*"] }, [ | ||
"browser", | ||
"main" | ||
]); | ||
const existingPath = join("/root", "location", "mylibjs", "kalle.js"); | ||
// Make sure we escape the "." | ||
const result = matchPath( | ||
"lib/mylibjs", | ||
(_: string) => ({ | ||
main: "./kalle.js", | ||
browser: "./nope.js" | ||
}), | ||
(name: string) => name === existingPath, | ||
@@ -151,5 +174,28 @@ [".ts", ".js"] | ||
assert.equal(result, existingPath); | ||
assert.equal(result, removeExtension(existingPath)); | ||
}); | ||
it("should ignore advanced field mappings in package.json", () => { | ||
const matchPath = createMatchPath("/root/", { "lib/*": ["location/*"] }, [ | ||
"browser", | ||
"main" | ||
]); | ||
const mainFilePath = join("/root", "location", "mylibjs", "kalle.js"); | ||
const browserFilePath = join("/root", "location", "mylibjs", "browser.js"); | ||
const existingPaths = [mainFilePath, browserFilePath]; | ||
// Make sure we escape the "." | ||
const result = matchPath( | ||
"lib/mylibjs", | ||
(_: string) => ({ | ||
main: "./kalle.js", | ||
browser: { mylibjs: "./browser.js", "./kalle.js": "./browser.js" } | ||
}), | ||
(name: string) => existingPaths.indexOf(name) !== -1, | ||
[".ts", ".js"] | ||
); | ||
assert.equal(result, removeExtension(mainFilePath)); | ||
}); | ||
it("should resolve to with the help of baseUrl when not explicitly set", () => { | ||
@@ -156,0 +202,0 @@ const matchPath = createMatchPath("/root/", {}); |
158822
1778