Skip to content

Commit

Permalink
fix: use get-tsconfig to handle tsconfig file resolution
Browse files Browse the repository at this point in the history
  • Loading branch information
effervescentia committed Apr 4, 2023
1 parent 11b774d commit 834b4b5
Show file tree
Hide file tree
Showing 7 changed files with 943 additions and 1,377 deletions.
7 changes: 7 additions & 0 deletions example/inherited/tsconfig.base.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"compilerOptions": {
"paths": {
"@": []
}
}
}
3 changes: 3 additions & 0 deletions example/inherited/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"extends": "./tsconfig.preset.json"
}
3 changes: 3 additions & 0 deletions example/inherited/tsconfig.preset.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"extends": "./tsconfig.base.json"
}
13 changes: 6 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"node": ">=6"
},
"devDependencies": {
"@types/jest": "^27.0.3",
"@types/jest": "^29.5.0",
"@types/minimist": "^1.2.2",
"@types/node": "^6.0.54",
"@types/strip-bom": "^3.0.0",
Expand All @@ -32,18 +32,17 @@
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-jsdoc": "^39.2.9",
"husky": "^4.2.5",
"jest": "^27.3.1",
"jest": "^29.5.0",
"lint-staged": "^10.2.11",
"prettier": "^2.0.5",
"rimraf": "^2.6.2",
"ts-jest": "^27.0.7",
"ts-jest": "^29.1.0",
"ts-node": "^10.7.0",
"typescript": "^4.5.2"
"typescript": "^5.0.3"
},
"dependencies": {
"json5": "^2.2.2",
"minimist": "^1.2.6",
"strip-bom": "^3.0.0"
"get-tsconfig": "^4.5.0",
"minimist": "^1.2.6"
},
"scripts": {
"start": "cd src && ts-node index.ts",
Expand Down
272 changes: 12 additions & 260 deletions src/__tests__/tsconfig-loader.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
import {
loadTsconfig,
tsConfigLoader,
walkForTsConfig,
} from "../tsconfig-loader";
import { join } from "path";
import { tsConfigLoader, walkForTsConfig } from "../tsconfig-loader";
import { join, resolve } from "path";

describe("tsconfig-loader", () => {
it("should find tsconfig in cwd", () => {
Expand Down Expand Up @@ -167,262 +163,18 @@ describe("walkForTsConfig", () => {
});
});

describe("loadConfig", () => {
it("should load a config", () => {
const config = { compilerOptions: { baseUrl: "hej" } };
const res = loadTsconfig(
"/root/dir1/tsconfig.json",
(path) => path === "/root/dir1/tsconfig.json",
(_) => JSON.stringify(config)
);
expect(res).toStrictEqual(config);
});

it("should load a config with comments", () => {
const config = { compilerOptions: { baseUrl: "hej" } };
const res = loadTsconfig(
"/root/dir1/tsconfig.json",
(path) => path === "/root/dir1/tsconfig.json",
(_) => `{
// my comment
"compilerOptions": {
"baseUrl": "hej"
}
}`
);
expect(res).toStrictEqual(config);
});

it("should load a config with trailing commas", () => {
const config = { compilerOptions: { baseUrl: "hej" } };
const res = loadTsconfig(
"/root/dir1/tsconfig.json",
(path) => path === "/root/dir1/tsconfig.json",
(_) => `{
"compilerOptions": {
"baseUrl": "hej",
},
}`
);
expect(res).toStrictEqual(config);
});

it("should throw an error including the file path when encountering invalid JSON5", () => {
expect(() =>
loadTsconfig(
"/root/dir1/tsconfig.json",
(path) => path === "/root/dir1/tsconfig.json",
(_) => `{
"compilerOptions": {
}`
)
).toThrowError(
"/root/dir1/tsconfig.json is malformed JSON5: invalid end of input at 3:12"
);
});

it("should load a config with string extends and overwrite all options", () => {
const firstConfig = {
extends: "../base-config.json",
compilerOptions: { baseUrl: "kalle", paths: { foo: ["bar2"] } },
};
const firstConfigPath = join("/root", "dir1", "tsconfig.json");
const baseConfig = {
compilerOptions: {
baseUrl: "olle",
paths: { foo: ["bar1"] },
strict: true,
},
};
const baseConfigPath = join("/root", "base-config.json");
const res = loadTsconfig(
join("/root", "dir1", "tsconfig.json"),
(path) => path === firstConfigPath || path === baseConfigPath,
(path) => {
if (path === firstConfigPath) {
return JSON.stringify(firstConfig);
}
if (path === baseConfigPath) {
return JSON.stringify(baseConfig);
}
return "";
}
);

expect(res).toEqual({
extends: "../base-config.json",
compilerOptions: {
baseUrl: "kalle",
paths: { foo: ["bar2"] },
strict: true,
},
});
});

it("should load a config with string extends from node_modules and overwrite all options", () => {
const firstConfig = {
extends: "my-package/base-config.json",
compilerOptions: { baseUrl: "kalle", paths: { foo: ["bar2"] } },
};
const firstConfigPath = join("/root", "dir1", "tsconfig.json");
const baseConfig = {
compilerOptions: {
baseUrl: "olle",
paths: { foo: ["bar1"] },
strict: true,
},
};
const baseConfigPath = join(
"/root",
"dir1",
"node_modules",
"my-package",
"base-config.json"
);
const res = loadTsconfig(
join("/root", "dir1", "tsconfig.json"),
(path) => path === firstConfigPath || path === baseConfigPath,
(path) => {
if (path === firstConfigPath) {
return JSON.stringify(firstConfig);
}
if (path === baseConfigPath) {
return JSON.stringify(baseConfig);
}
return "";
}
);

expect(res).toEqual({
extends: "my-package/base-config.json",
compilerOptions: {
baseUrl: "kalle",
paths: { foo: ["bar2"] },
strict: true,
},
});
});

it("should use baseUrl relative to location of extended tsconfig", () => {
const firstConfig = { compilerOptions: { baseUrl: "." } };
const firstConfigPath = join("/root", "first-config.json");
const secondConfig = { extends: "../first-config.json" };
const secondConfigPath = join("/root", "dir1", "second-config.json");
const thirdConfig = { extends: "../second-config.json" };
const thirdConfigPath = join("/root", "dir1", "dir2", "third-config.json");
const res = loadTsconfig(
join("/root", "dir1", "dir2", "third-config.json"),
(path) =>
path === firstConfigPath ||
path === secondConfigPath ||
path === thirdConfigPath,
(path) => {
if (path === firstConfigPath) {
return JSON.stringify(firstConfig);
}
if (path === secondConfigPath) {
return JSON.stringify(secondConfig);
}
if (path === thirdConfigPath) {
return JSON.stringify(thirdConfig);
}
return "";
}
);

expect(res).toEqual({
extends: "../second-config.json",
compilerOptions: { baseUrl: join("..", "..") },
});
});

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"] },
},
describe("loadSyncDefault", () => {
it("should result multiple levels of tsconfig extension", () => {
const cwd = resolve(__dirname, "../../example/inherited");
const result = tsConfigLoader({
cwd,
getEnv: (_: string) => undefined,
});
});

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"] },
},
expect(result).toEqual({
baseUrl: undefined,
paths: { "@": [] },
tsConfigPath: resolve(cwd, "tsconfig.json"),
});
});
});
Loading

0 comments on commit 834b4b5

Please sign in to comment.