Skip to content

Commit 9680ff0

Browse files
authored
Merge pull request #149 from Codex-/upgrade_jiti
Upgrade to Jiti 2
2 parents 8e46d2c + 0056629 commit 9680ff0

File tree

15 files changed

+474
-1000
lines changed

15 files changed

+474
-1000
lines changed

.github/workflows/build.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,15 @@ jobs:
4242
- name: Import with both CJS and ESM
4343
if: ${{ always() }}
4444
run: node smoke-tests/smoke-test.js
45+
- name: Import synchronously with CJS
46+
if: ${{ always() }}
47+
run: node smoke-tests/smoke-test-cjs-sync.cjs
48+
- name: Import synchronously with ESM
49+
if: ${{ always() }}
50+
run: node smoke-tests/smoke-test-esm-sync.mjs
51+
- name: Import synchronously with both CJS and ESM
52+
if: ${{ always() }}
53+
run: node smoke-tests/smoke-test-sync.js
4554
- name: lint
4655
if: ${{ always() }}
4756
run: pnpm lint

.release-it.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
{
22
"git": {
3-
"changelog": "npx auto-changelog --stdout --commit-limit false --unreleased --template https://raw.githubusercontent.com/release-it/release-it/master/templates/changelog-compact.hbs"
3+
"changelog": "pnpm exec auto-changelog --stdout --commit-limit false --unreleased --template https://raw.githubusercontent.com/release-it/release-it/master/templates/changelog-compact.hbs"
44
},
55
"github": {
66
"release": true
77
},
88
"hooks": {
9-
"after:bump": "npx auto-changelog -p"
9+
"after:bump": "pnpm exec auto-changelog -p"
1010
}
1111
}

README.md

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
## Usage
1010

11-
Simply add `TypeScriptLoader` to the list of loaders for the `.ts` file type:
11+
Simply add `TypeScriptLoader` to the list of loaders for the `.ts` file type, and `await` loading:
1212

1313
```ts
1414
import { cosmiconfig } from "cosmiconfig";
@@ -34,7 +34,7 @@ const explorer = cosmiconfig("test", {
3434
},
3535
});
3636

37-
const cfg = explorer.load("./");
37+
const cfg = await explorer.load("./");
3838
```
3939

4040
Or more simply if you only support loading of a TypeScript based configuration file:
@@ -50,6 +50,24 @@ const explorer = cosmiconfig("test", {
5050
},
5151
});
5252

53+
const cfg = await explorer.load("./amazing.config.ts");
54+
```
55+
56+
### Synchronously loading
57+
58+
With the release of Jiti 2, the synchronous loader has now been deprecated. It can still be used by using the `TypeScriptLoaderSync` export:
59+
60+
```ts
61+
import { cosmiconfig } from "cosmiconfig";
62+
import { TypeScriptLoaderSync } from "cosmiconfig-typescript-loader";
63+
64+
const moduleName = "module";
65+
const explorer = cosmiconfig("test", {
66+
loaders: {
67+
".ts": TypeScriptLoaderSync(),
68+
},
69+
});
70+
5371
const cfg = explorer.load("./amazing.config.ts");
5472
```
5573

lib/index.spec.ts

Lines changed: 6 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
1+
/* eslint-disable @typescript-eslint/no-deprecated */
2+
13
import path from "node:path";
24

35
import { cosmiconfig, cosmiconfigSync } from "cosmiconfig";
46

5-
import { TypeScriptLoader } from ".";
7+
import { TypeScriptLoader, TypeScriptLoaderSync } from ".";
68

79
describe("TypeScriptLoader", () => {
810
const fixturesPath = path.resolve(__dirname, "__fixtures__");
911

1012
describe("exports", () => {
1113
it("should export the loader function as a default", () => {
1214
expect(typeof TypeScriptLoader).toStrictEqual("function");
15+
expect(typeof TypeScriptLoaderSync).toStrictEqual("function");
1316
});
1417
});
1518

@@ -18,7 +21,7 @@ describe("TypeScriptLoader", () => {
1821
it("should load a valid TS file", () => {
1922
const cfg = cosmiconfigSync("test", {
2023
loaders: {
21-
".ts": TypeScriptLoader(),
24+
".ts": TypeScriptLoaderSync(),
2225
},
2326
});
2427
const loadedCfg = cfg.load(
@@ -33,7 +36,7 @@ describe("TypeScriptLoader", () => {
3336
it("should throw an error on loading an invalid TS file", () => {
3437
const cfg = cosmiconfigSync("test", {
3538
loaders: {
36-
".ts": TypeScriptLoader(),
39+
".ts": TypeScriptLoaderSync(),
3740
},
3841
});
3942

@@ -80,33 +83,4 @@ describe("TypeScriptLoader", () => {
8083
});
8184
});
8285
});
83-
84-
describe("cosmiconfigSync", () => {
85-
it("should load a valid TS file", () => {
86-
const cfg = cosmiconfigSync("test", {
87-
loaders: {
88-
".ts": TypeScriptLoader(),
89-
},
90-
});
91-
const loadedCfg = cfg.load(
92-
path.resolve(fixturesPath, "valid.fixture.ts"),
93-
);
94-
95-
expect(typeof loadedCfg!.config).toStrictEqual("object");
96-
expect(typeof loadedCfg!.config.test).toStrictEqual("object");
97-
expect(loadedCfg!.config.test.cake).toStrictEqual("a lie");
98-
});
99-
100-
it("should throw an error on loading an invalid TS file", () => {
101-
const cfg = cosmiconfigSync("test", {
102-
loaders: {
103-
".ts": TypeScriptLoader(),
104-
},
105-
});
106-
107-
expect(() =>
108-
cfg.load(path.resolve(fixturesPath, "invalid.fixture.ts")),
109-
).toThrow();
110-
});
111-
});
11286
});

lib/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
export { TypeScriptLoader } from "./loader.js";
1+
export { TypeScriptLoader, TypeScriptLoaderSync } from "./loader.js";
22
export type { TypeScriptCompileError } from "./typescript-compile-error.js";

lib/loader.spec.ts

Lines changed: 115 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,94 +1,156 @@
11
import fs from "node:fs";
22
import path from "node:path";
33

4-
import { Loader } from "cosmiconfig";
4+
import type { LoaderResult, LoaderSync } from "cosmiconfig";
55
import * as jiti from "jiti";
66

7-
import { TypeScriptLoader } from "./loader";
7+
import { TypeScriptLoader, TypeScriptLoaderSync } from "./loader";
88
import { TypeScriptCompileError } from "./typescript-compile-error";
99

1010
// Handle jiti using `export default`
1111
jest.mock("jiti", () => {
1212
const actual = jest.requireActual("jiti");
1313
return {
1414
__esModule: true,
15-
default: jest.fn(actual),
15+
createJiti: actual.createJiti,
1616
};
1717
});
1818

1919
describe("TypeScriptLoader", () => {
2020
const fixturesPath = path.resolve(__dirname, "__fixtures__");
21-
const jitiSpy = jest.spyOn(jiti, "default");
22-
23-
let loader: Loader;
21+
let jitiCreateJitiSpy: jest.SpyInstance<typeof jiti.createJiti>;
2422

2523
function readFixtureContent(file: string): string {
2624
return fs.readFileSync(file).toString();
2725
}
2826

29-
beforeAll(() => {
30-
loader = TypeScriptLoader();
27+
beforeEach(() => {
28+
jitiCreateJitiSpy = jest.spyOn(jiti, "createJiti");
3129
});
3230

33-
it("should parse a valid TS file", () => {
34-
const filePath = path.resolve(fixturesPath, "valid.fixture.ts");
35-
loader(filePath, readFixtureContent(filePath));
31+
afterEach(() => {
32+
jest.restoreAllMocks();
3633
});
3734

38-
it("should fail on parsing an invalid TS file", () => {
39-
const filePath = path.resolve(fixturesPath, "invalid.fixture.ts");
40-
expect((): unknown =>
41-
loader(filePath, readFixtureContent(filePath)),
42-
).toThrow();
43-
});
35+
describe("asynchronous", () => {
36+
let loader: (filepath: string, content: string) => Promise<LoaderResult>;
4437

45-
it("should use the same instance of jiti across multiple calls", () => {
46-
const filePath = path.resolve(fixturesPath, "valid.fixture.ts");
47-
loader(filePath, readFixtureContent(filePath));
48-
loader(filePath, readFixtureContent(filePath));
49-
expect(jitiSpy).toHaveBeenCalledTimes(1);
50-
});
38+
beforeEach(() => {
39+
loader = TypeScriptLoader();
40+
});
41+
42+
it("should parse a valid TS file", async () => {
43+
const filePath = path.resolve(fixturesPath, "valid.fixture.ts");
44+
await loader(filePath, readFixtureContent(filePath));
45+
});
5146

52-
it("should throw a TypeScriptCompileError on error", () => {
53-
try {
47+
it("should fail on parsing an invalid TS file", async () => {
5448
const filePath = path.resolve(fixturesPath, "invalid.fixture.ts");
55-
loader(filePath, readFixtureContent(filePath));
56-
fail(
57-
"Error should be thrown upon failing to transpile an invalid TS file.",
58-
);
59-
} catch (error: unknown) {
60-
expect(error).toBeInstanceOf(TypeScriptCompileError);
61-
}
62-
});
49+
await expect(
50+
loader(filePath, readFixtureContent(filePath)),
51+
).rejects.toThrow();
52+
});
6353

64-
describe("jiti", () => {
65-
const unknownError = "Test Error";
54+
it("should use the same instance of jiti across multiple calls", async () => {
55+
const filePath = path.resolve(fixturesPath, "valid.fixture.ts");
56+
await loader(filePath, readFixtureContent(filePath));
57+
await loader(filePath, readFixtureContent(filePath));
58+
expect(jitiCreateJitiSpy).toHaveBeenCalledTimes(1);
59+
});
6660

67-
let stub: jest.SpyInstance;
61+
it("should throw a TypeScriptCompileError on error", async () => {
62+
const filePath = path.resolve(fixturesPath, "invalid.fixture.ts");
63+
await expect(
64+
loader(filePath, readFixtureContent(filePath)),
65+
).rejects.toThrow(TypeScriptCompileError);
66+
});
67+
68+
describe("jiti", () => {
69+
const unknownError = "Test Error";
70+
71+
beforeEach(() => {
72+
jitiCreateJitiSpy.mockImplementation((() => ({
73+
import: () => {
74+
// eslint-disable-next-line @typescript-eslint/only-throw-error
75+
throw unknownError;
76+
},
77+
})) as never);
78+
79+
loader = TypeScriptLoader();
80+
});
81+
82+
it("rethrows an error if it is not an instance of Error", async () => {
83+
try {
84+
await loader("filePath", "invalidInput");
85+
fail(
86+
"Error should be thrown upon failing to transpile an invalid TS file.",
87+
);
88+
} catch (error: unknown) {
89+
expect(error).not.toBeInstanceOf(TypeScriptCompileError);
90+
expect(error).toStrictEqual(unknownError);
91+
}
92+
});
93+
});
94+
});
95+
96+
describe("synchronous", () => {
97+
let loader: LoaderSync;
6898

6999
beforeEach(() => {
70-
stub = jest.spyOn(jiti, "default").mockImplementation((() => () => {
71-
// eslint-disable-next-line @typescript-eslint/only-throw-error
72-
throw unknownError;
73-
}) as never);
100+
// eslint-disable-next-line @typescript-eslint/no-deprecated
101+
loader = TypeScriptLoaderSync();
102+
});
74103

75-
loader = TypeScriptLoader();
104+
it("should parse a valid TS file", () => {
105+
const filePath = path.resolve(fixturesPath, "valid.fixture.ts");
106+
loader(filePath, readFixtureContent(filePath));
107+
});
108+
109+
it("should fail on parsing an invalid TS file", () => {
110+
const filePath = path.resolve(fixturesPath, "invalid.fixture.ts");
111+
expect((): unknown =>
112+
loader(filePath, readFixtureContent(filePath)),
113+
).toThrow();
76114
});
77115

78-
afterEach(() => {
79-
stub.mockRestore();
116+
it("should use the same instance of jiti across multiple calls", () => {
117+
const filePath = path.resolve(fixturesPath, "valid.fixture.ts");
118+
loader(filePath, readFixtureContent(filePath));
119+
loader(filePath, readFixtureContent(filePath));
120+
expect(jitiCreateJitiSpy).toHaveBeenCalledTimes(1);
121+
});
122+
123+
it("should throw a TypeScriptCompileError on error", () => {
124+
const filePath = path.resolve(fixturesPath, "invalid.fixture.ts");
125+
expect((): unknown =>
126+
loader(filePath, readFixtureContent(filePath)),
127+
).toThrow(TypeScriptCompileError);
80128
});
81129

82-
it("rethrows an error if it is not an instance of Error", () => {
83-
try {
84-
loader("filePath", "readFixtureContent(filePath)");
85-
fail(
86-
"Error should be thrown upon failing to transpile an invalid TS file.",
87-
);
88-
} catch (error: unknown) {
89-
expect(error).not.toBeInstanceOf(TypeScriptCompileError);
90-
expect(error).toStrictEqual(unknownError);
91-
}
130+
describe("jiti", () => {
131+
const unknownError = "Test Error";
132+
133+
beforeEach(() => {
134+
jitiCreateJitiSpy.mockImplementation((() => () => {
135+
// eslint-disable-next-line @typescript-eslint/only-throw-error
136+
throw unknownError;
137+
}) as never);
138+
139+
// eslint-disable-next-line @typescript-eslint/no-deprecated
140+
loader = TypeScriptLoaderSync();
141+
});
142+
143+
it("rethrows an error if it is not an instance of Error", () => {
144+
try {
145+
loader("filePath", "invalidInput");
146+
fail(
147+
"Error should be thrown upon failing to transpile an invalid TS file.",
148+
);
149+
} catch (error: unknown) {
150+
expect(error).not.toBeInstanceOf(TypeScriptCompileError);
151+
expect(error).toStrictEqual(unknownError);
152+
}
153+
});
92154
});
93155
});
94156
});

0 commit comments

Comments
 (0)