tsconfig-paths
Advanced tools
Comparing version 4.1.2 to 4.2.0
@@ -10,2 +10,14 @@ # Change Log | ||
## [4.2.0] - 2023-03-29 | ||
### Added | ||
- Add support for tsconfig extends as array of strings. #. See PR [#245](https://github.com/dividab/tsconfig-paths/pull/245). Thanks to [@DanielSidhion](https://github.com/DanielSidhion) for this PR! | ||
## [3.14.2] - 2023-02-25 | ||
### Fixed | ||
- bump JSON5 from v1.0.1 to v1.0.2 in tsconfig-paths v3.14.1 to fix CVE-2022-46175 #234. See PR [#234](https://github.com/dividab/tsconfig-paths/pull/234). Thanks to [@mihaiplesa](https://github.com/mihaiplesa) for this PR! | ||
## [4.1.2] - 2023-01-02 | ||
@@ -12,0 +24,0 @@ |
@@ -138,3 +138,3 @@ "use strict"; | ||
describe("loadConfig", function () { | ||
it("It should load a config", function () { | ||
it("should load a config", function () { | ||
var config = { compilerOptions: { baseUrl: "hej" } }; | ||
@@ -144,3 +144,3 @@ var res = (0, tsconfig_loader_1.loadTsconfig)("/root/dir1/tsconfig.json", function (path) { return path === "/root/dir1/tsconfig.json"; }, function (_) { return JSON.stringify(config); }); | ||
}); | ||
it("It should load a config with comments", function () { | ||
it("should load a config with comments", function () { | ||
var config = { compilerOptions: { baseUrl: "hej" } }; | ||
@@ -150,3 +150,3 @@ var res = (0, tsconfig_loader_1.loadTsconfig)("/root/dir1/tsconfig.json", function (path) { return path === "/root/dir1/tsconfig.json"; }, function (_) { return "{\n // my comment\n \"compilerOptions\": { \n \"baseUrl\": \"hej\"\n }\n }"; }); | ||
}); | ||
it("It should load a config with trailing commas", function () { | ||
it("should load a config with trailing commas", function () { | ||
var config = { compilerOptions: { baseUrl: "hej" } }; | ||
@@ -156,3 +156,3 @@ var res = (0, tsconfig_loader_1.loadTsconfig)("/root/dir1/tsconfig.json", function (path) { return path === "/root/dir1/tsconfig.json"; }, function (_) { return "{\n \"compilerOptions\": { \n \"baseUrl\": \"hej\",\n },\n }"; }); | ||
}); | ||
it("It should throw an error including the file path when encountering invalid JSON5", function () { | ||
it("should throw an error including the file path when encountering invalid JSON5", function () { | ||
expect(function () { | ||
@@ -162,3 +162,3 @@ return (0, tsconfig_loader_1.loadTsconfig)("/root/dir1/tsconfig.json", function (path) { return path === "/root/dir1/tsconfig.json"; }, function (_) { return "{\n \"compilerOptions\": {\n }"; }); | ||
}); | ||
it("It should load a config with extends and overwrite all options", function () { | ||
it("should load a config with string extends and overwrite all options", function () { | ||
var firstConfig = { | ||
@@ -195,3 +195,3 @@ extends: "../base-config.json", | ||
}); | ||
it("It should load a config with extends from node_modules and overwrite all options", function () { | ||
it("should load a config with string extends from node_modules and overwrite all options", function () { | ||
var firstConfig = { | ||
@@ -228,3 +228,3 @@ extends: "my-package/base-config.json", | ||
}); | ||
it("Should use baseUrl relative to location of extended tsconfig", function () { | ||
it("should use baseUrl relative to location of extended tsconfig", function () { | ||
var firstConfig = { compilerOptions: { baseUrl: "." } }; | ||
@@ -257,3 +257,80 @@ var firstConfigPath = (0, path_1.join)("/root", "first-config.json"); | ||
}); | ||
it("should load a config with array extends and overwrite all options", function () { | ||
var baseConfig1 = { | ||
compilerOptions: { baseUrl: ".", paths: { foo: ["bar"] } }, | ||
}; | ||
var baseConfig1Path = (0, path_1.join)("/root", "base-config-1.json"); | ||
var baseConfig2 = { compilerOptions: { baseUrl: "." } }; | ||
var baseConfig2Path = (0, path_1.join)("/root", "dir1", "base-config-2.json"); | ||
var baseConfig3 = { | ||
compilerOptions: { baseUrl: ".", paths: { foo: ["bar2"] } }, | ||
}; | ||
var baseConfig3Path = (0, path_1.join)("/root", "dir1", "dir2", "base-config-3.json"); | ||
var actualConfig = { | ||
extends: [ | ||
"./base-config-1.json", | ||
"./dir1/base-config-2.json", | ||
"./dir1/dir2/base-config-3.json", | ||
], | ||
}; | ||
var actualConfigPath = (0, path_1.join)("/root", "tsconfig.json"); | ||
var res = (0, tsconfig_loader_1.loadTsconfig)((0, path_1.join)("/root", "tsconfig.json"), function (path) { | ||
return [ | ||
baseConfig1Path, | ||
baseConfig2Path, | ||
baseConfig3Path, | ||
actualConfigPath, | ||
].indexOf(path) >= 0; | ||
}, function (path) { | ||
if (path === baseConfig1Path) { | ||
return JSON.stringify(baseConfig1); | ||
} | ||
if (path === baseConfig2Path) { | ||
return JSON.stringify(baseConfig2); | ||
} | ||
if (path === baseConfig3Path) { | ||
return JSON.stringify(baseConfig3); | ||
} | ||
if (path === actualConfigPath) { | ||
return JSON.stringify(actualConfig); | ||
} | ||
return ""; | ||
}); | ||
expect(res).toEqual({ | ||
extends: [ | ||
"./base-config-1.json", | ||
"./dir1/base-config-2.json", | ||
"./dir1/dir2/base-config-3.json", | ||
], | ||
compilerOptions: { | ||
baseUrl: (0, path_1.join)("dir1", "dir2"), | ||
paths: { foo: ["bar2"] }, | ||
}, | ||
}); | ||
}); | ||
it("should load a config with array extends without .json extension", function () { | ||
var baseConfig = { | ||
compilerOptions: { baseUrl: ".", paths: { foo: ["bar"] } }, | ||
}; | ||
var baseConfigPath = (0, path_1.join)("/root", "base-config-1.json"); | ||
var actualConfig = { extends: ["./base-config-1"] }; | ||
var actualConfigPath = (0, path_1.join)("/root", "tsconfig.json"); | ||
var res = (0, tsconfig_loader_1.loadTsconfig)((0, path_1.join)("/root", "tsconfig.json"), function (path) { return [baseConfigPath, actualConfigPath].indexOf(path) >= 0; }, function (path) { | ||
if (path === baseConfigPath) { | ||
return JSON.stringify(baseConfig); | ||
} | ||
if (path === actualConfigPath) { | ||
return JSON.stringify(actualConfig); | ||
} | ||
return ""; | ||
}); | ||
expect(res).toEqual({ | ||
extends: ["./base-config-1"], | ||
compilerOptions: { | ||
baseUrl: ".", | ||
paths: { foo: ["bar"] }, | ||
}, | ||
}); | ||
}); | ||
}); | ||
//# sourceMappingURL=tsconfig-loader.test.js.map |
@@ -5,3 +5,3 @@ /** | ||
export interface Tsconfig { | ||
extends?: string; | ||
extends?: string | string[]; | ||
compilerOptions?: { | ||
@@ -8,0 +8,0 @@ baseUrl?: string; |
@@ -101,21 +101,12 @@ "use strict"; | ||
if (extendedConfig) { | ||
if (typeof extendedConfig === "string" && | ||
extendedConfig.indexOf(".json") === -1) { | ||
extendedConfig += ".json"; | ||
var base = void 0; | ||
if (Array.isArray(extendedConfig)) { | ||
base = extendedConfig.reduce(function (currBase, extendedConfigElement) { | ||
return mergeTsconfigs(currBase, loadTsconfigFromExtends(configFilePath, extendedConfigElement, existsSync, readFileSync)); | ||
}, {}); | ||
} | ||
var currentDir = path.dirname(configFilePath); | ||
var extendedConfigPath = path.join(currentDir, extendedConfig); | ||
if (extendedConfig.indexOf("/") !== -1 && | ||
extendedConfig.indexOf(".") !== -1 && | ||
!existsSync(extendedConfigPath)) { | ||
extendedConfigPath = path.join(currentDir, "node_modules", extendedConfig); | ||
else { | ||
base = loadTsconfigFromExtends(configFilePath, extendedConfig, existsSync, readFileSync); | ||
} | ||
var base = loadTsconfig(extendedConfigPath, existsSync, readFileSync) || {}; | ||
// baseUrl should be interpreted as relative to the base tsconfig, | ||
// but we need to update it so it is relative to the original tsconfig being loaded | ||
if (base.compilerOptions && base.compilerOptions.baseUrl) { | ||
var extendsDir = path.dirname(extendedConfig); | ||
base.compilerOptions.baseUrl = path.join(extendsDir, base.compilerOptions.baseUrl); | ||
} | ||
return __assign(__assign(__assign({}, base), config), { compilerOptions: __assign(__assign({}, base.compilerOptions), config.compilerOptions) }); | ||
return mergeTsconfigs(base, config); | ||
} | ||
@@ -125,2 +116,35 @@ return config; | ||
exports.loadTsconfig = loadTsconfig; | ||
/** | ||
* Intended to be called only from loadTsconfig. | ||
* Parameters don't have defaults because they should use the same as loadTsconfig. | ||
*/ | ||
function loadTsconfigFromExtends(configFilePath, extendedConfigValue, | ||
// eslint-disable-next-line no-shadow | ||
existsSync, readFileSync) { | ||
var _a; | ||
if (typeof extendedConfigValue === "string" && | ||
extendedConfigValue.indexOf(".json") === -1) { | ||
extendedConfigValue += ".json"; | ||
} | ||
var currentDir = path.dirname(configFilePath); | ||
var extendedConfigPath = path.join(currentDir, extendedConfigValue); | ||
if (extendedConfigValue.indexOf("/") !== -1 && | ||
extendedConfigValue.indexOf(".") !== -1 && | ||
!existsSync(extendedConfigPath)) { | ||
extendedConfigPath = path.join(currentDir, "node_modules", extendedConfigValue); | ||
} | ||
var config = loadTsconfig(extendedConfigPath, existsSync, readFileSync) || {}; | ||
// baseUrl should be interpreted as relative to extendedConfigPath, | ||
// but we need to update it so it is relative to the original tsconfig being loaded | ||
if ((_a = config.compilerOptions) === null || _a === void 0 ? void 0 : _a.baseUrl) { | ||
var extendsDir = path.dirname(extendedConfigValue); | ||
config.compilerOptions.baseUrl = path.join(extendsDir, config.compilerOptions.baseUrl); | ||
} | ||
return config; | ||
} | ||
function mergeTsconfigs(base, config) { | ||
base = base || {}; | ||
config = config || {}; | ||
return __assign(__assign(__assign({}, base), config), { compilerOptions: __assign(__assign({}, base.compilerOptions), config.compilerOptions) }); | ||
} | ||
//# sourceMappingURL=tsconfig-loader.js.map |
{ | ||
"name": "tsconfig-paths", | ||
"version": "4.1.2", | ||
"version": "4.2.0", | ||
"description": "Load node modules according to tsconfig paths, in run-time or via API.", | ||
@@ -5,0 +5,0 @@ "main": "lib/index.js", |
@@ -171,3 +171,3 @@ import { | ||
describe("loadConfig", () => { | ||
it("It should load a config", () => { | ||
it("should load a config", () => { | ||
const config = { compilerOptions: { baseUrl: "hej" } }; | ||
@@ -182,3 +182,3 @@ const res = loadTsconfig( | ||
it("It should load a config with comments", () => { | ||
it("should load a config with comments", () => { | ||
const config = { compilerOptions: { baseUrl: "hej" } }; | ||
@@ -198,3 +198,3 @@ const res = loadTsconfig( | ||
it("It should load a config with trailing commas", () => { | ||
it("should load a config with trailing commas", () => { | ||
const config = { compilerOptions: { baseUrl: "hej" } }; | ||
@@ -213,3 +213,3 @@ const res = loadTsconfig( | ||
it("It should throw an error including the file path when encountering invalid JSON5", () => { | ||
it("should throw an error including the file path when encountering invalid JSON5", () => { | ||
expect(() => | ||
@@ -228,3 +228,3 @@ loadTsconfig( | ||
it("It should load a config with extends and overwrite all options", () => { | ||
it("should load a config with string extends and overwrite all options", () => { | ||
const firstConfig = { | ||
@@ -267,3 +267,3 @@ extends: "../base-config.json", | ||
it("It should load a config with extends from node_modules and overwrite all options", () => { | ||
it("should load a config with string extends from node_modules and overwrite all options", () => { | ||
const firstConfig = { | ||
@@ -312,3 +312,3 @@ extends: "my-package/base-config.json", | ||
it("Should use baseUrl relative to location of extended tsconfig", () => { | ||
it("should use baseUrl relative to location of extended tsconfig", () => { | ||
const firstConfig = { compilerOptions: { baseUrl: "." } }; | ||
@@ -345,2 +345,92 @@ const firstConfigPath = join("/root", "first-config.json"); | ||
}); | ||
it("should load a config with array extends and overwrite all options", () => { | ||
const baseConfig1 = { | ||
compilerOptions: { baseUrl: ".", paths: { foo: ["bar"] } }, | ||
}; | ||
const baseConfig1Path = join("/root", "base-config-1.json"); | ||
const baseConfig2 = { compilerOptions: { baseUrl: "." } }; | ||
const baseConfig2Path = join("/root", "dir1", "base-config-2.json"); | ||
const baseConfig3 = { | ||
compilerOptions: { baseUrl: ".", paths: { foo: ["bar2"] } }, | ||
}; | ||
const baseConfig3Path = join("/root", "dir1", "dir2", "base-config-3.json"); | ||
const actualConfig = { | ||
extends: [ | ||
"./base-config-1.json", | ||
"./dir1/base-config-2.json", | ||
"./dir1/dir2/base-config-3.json", | ||
], | ||
}; | ||
const actualConfigPath = join("/root", "tsconfig.json"); | ||
const res = loadTsconfig( | ||
join("/root", "tsconfig.json"), | ||
(path) => | ||
[ | ||
baseConfig1Path, | ||
baseConfig2Path, | ||
baseConfig3Path, | ||
actualConfigPath, | ||
].indexOf(path) >= 0, | ||
(path) => { | ||
if (path === baseConfig1Path) { | ||
return JSON.stringify(baseConfig1); | ||
} | ||
if (path === baseConfig2Path) { | ||
return JSON.stringify(baseConfig2); | ||
} | ||
if (path === baseConfig3Path) { | ||
return JSON.stringify(baseConfig3); | ||
} | ||
if (path === actualConfigPath) { | ||
return JSON.stringify(actualConfig); | ||
} | ||
return ""; | ||
} | ||
); | ||
expect(res).toEqual({ | ||
extends: [ | ||
"./base-config-1.json", | ||
"./dir1/base-config-2.json", | ||
"./dir1/dir2/base-config-3.json", | ||
], | ||
compilerOptions: { | ||
baseUrl: join("dir1", "dir2"), | ||
paths: { foo: ["bar2"] }, | ||
}, | ||
}); | ||
}); | ||
it("should load a config with array extends without .json extension", () => { | ||
const baseConfig = { | ||
compilerOptions: { baseUrl: ".", paths: { foo: ["bar"] } }, | ||
}; | ||
const baseConfigPath = join("/root", "base-config-1.json"); | ||
const actualConfig = { extends: ["./base-config-1"] }; | ||
const actualConfigPath = join("/root", "tsconfig.json"); | ||
const res = loadTsconfig( | ||
join("/root", "tsconfig.json"), | ||
(path) => [baseConfigPath, actualConfigPath].indexOf(path) >= 0, | ||
(path) => { | ||
if (path === baseConfigPath) { | ||
return JSON.stringify(baseConfig); | ||
} | ||
if (path === actualConfigPath) { | ||
return JSON.stringify(actualConfig); | ||
} | ||
return ""; | ||
} | ||
); | ||
expect(res).toEqual({ | ||
extends: ["./base-config-1"], | ||
compilerOptions: { | ||
baseUrl: ".", | ||
paths: { foo: ["bar"] }, | ||
}, | ||
}); | ||
}); | ||
}); |
@@ -12,3 +12,3 @@ import * as path from "path"; | ||
export interface Tsconfig { | ||
extends?: string; | ||
extends?: string | string[]; | ||
compilerOptions?: { | ||
@@ -135,48 +135,97 @@ baseUrl?: string; | ||
} | ||
let extendedConfig = config.extends; | ||
if (extendedConfig) { | ||
let base: Tsconfig; | ||
if (extendedConfig) { | ||
if ( | ||
typeof extendedConfig === "string" && | ||
extendedConfig.indexOf(".json") === -1 | ||
) { | ||
extendedConfig += ".json"; | ||
} | ||
const currentDir = path.dirname(configFilePath); | ||
let extendedConfigPath = path.join(currentDir, extendedConfig); | ||
if ( | ||
extendedConfig.indexOf("/") !== -1 && | ||
extendedConfig.indexOf(".") !== -1 && | ||
!existsSync(extendedConfigPath) | ||
) { | ||
extendedConfigPath = path.join( | ||
currentDir, | ||
"node_modules", | ||
extendedConfig | ||
if (Array.isArray(extendedConfig)) { | ||
base = extendedConfig.reduce( | ||
(currBase, extendedConfigElement) => | ||
mergeTsconfigs( | ||
currBase, | ||
loadTsconfigFromExtends( | ||
configFilePath, | ||
extendedConfigElement, | ||
existsSync, | ||
readFileSync | ||
) | ||
), | ||
{} | ||
); | ||
} else { | ||
base = loadTsconfigFromExtends( | ||
configFilePath, | ||
extendedConfig, | ||
existsSync, | ||
readFileSync | ||
); | ||
} | ||
const base = | ||
loadTsconfig(extendedConfigPath, existsSync, readFileSync) || {}; | ||
return mergeTsconfigs(base, config); | ||
} | ||
return config; | ||
} | ||
// baseUrl should be interpreted as relative to the base tsconfig, | ||
// but we need to update it so it is relative to the original tsconfig being loaded | ||
if (base.compilerOptions && base.compilerOptions.baseUrl) { | ||
const extendsDir = path.dirname(extendedConfig); | ||
base.compilerOptions.baseUrl = path.join( | ||
extendsDir, | ||
base.compilerOptions.baseUrl | ||
); | ||
} | ||
/** | ||
* Intended to be called only from loadTsconfig. | ||
* Parameters don't have defaults because they should use the same as loadTsconfig. | ||
*/ | ||
function loadTsconfigFromExtends( | ||
configFilePath: string, | ||
extendedConfigValue: string, | ||
// eslint-disable-next-line no-shadow | ||
existsSync: (path: string) => boolean, | ||
readFileSync: (filename: string) => string | ||
): Tsconfig { | ||
if ( | ||
typeof extendedConfigValue === "string" && | ||
extendedConfigValue.indexOf(".json") === -1 | ||
) { | ||
extendedConfigValue += ".json"; | ||
} | ||
const currentDir = path.dirname(configFilePath); | ||
let extendedConfigPath = path.join(currentDir, extendedConfigValue); | ||
if ( | ||
extendedConfigValue.indexOf("/") !== -1 && | ||
extendedConfigValue.indexOf(".") !== -1 && | ||
!existsSync(extendedConfigPath) | ||
) { | ||
extendedConfigPath = path.join( | ||
currentDir, | ||
"node_modules", | ||
extendedConfigValue | ||
); | ||
} | ||
return { | ||
...base, | ||
...config, | ||
compilerOptions: { | ||
...base.compilerOptions, | ||
...config.compilerOptions, | ||
}, | ||
}; | ||
const config = | ||
loadTsconfig(extendedConfigPath, existsSync, readFileSync) || {}; | ||
// baseUrl should be interpreted as relative to extendedConfigPath, | ||
// but we need to update it so it is relative to the original tsconfig being loaded | ||
if (config.compilerOptions?.baseUrl) { | ||
const extendsDir = path.dirname(extendedConfigValue); | ||
config.compilerOptions.baseUrl = path.join( | ||
extendsDir, | ||
config.compilerOptions.baseUrl | ||
); | ||
} | ||
return config; | ||
} | ||
function mergeTsconfigs( | ||
base: Tsconfig | undefined, | ||
config: Tsconfig | undefined | ||
): Tsconfig { | ||
base = base || {}; | ||
config = config || {}; | ||
return { | ||
...base, | ||
...config, | ||
compilerOptions: { | ||
...base.compilerOptions, | ||
...config.compilerOptions, | ||
}, | ||
}; | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
216221
3818