Skip to content

Commit 1516e46

Browse files
committed
feat: improve resolve exports with conditional exports
1 parent ed76bb8 commit 1516e46

File tree

2 files changed

+106
-6
lines changed

2 files changed

+106
-6
lines changed

src/package-types.test.ts

Lines changed: 102 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ test("types from exports for root `.` subpath", async () => {
5656
).resolves.toBe("index.d.ts");
5757
});
5858

59-
test("types from exports for root `foo` subpath", async () => {
59+
test("types from exports for root `foo` package name subpath", async () => {
6060
await expect(
6161
_packageTypes(
6262
{
@@ -137,3 +137,104 @@ test("types not from `typings` fallback if not root subpath", async () => {
137137
),
138138
).rejects.toThrow();
139139
});
140+
141+
test("ts-api-utils@2.1.0", async () => {
142+
await expect(
143+
_packageTypes(
144+
{
145+
name: "ts-api-utils",
146+
version: "2.1.0",
147+
type: "module",
148+
exports: {
149+
".": {
150+
types: {
151+
import: "./lib/index.d.ts",
152+
require: "./lib/index.d.cts",
153+
},
154+
import: "./lib/index.js",
155+
require: "./lib/index.cjs",
156+
},
157+
},
158+
},
159+
".",
160+
),
161+
).resolves.toBe("./lib/index.d.ts");
162+
});
163+
164+
// https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-7.html#packagejson-exports-imports-and-self-referencing
165+
test("ts 4.7 release", async () => {
166+
await expect(
167+
_packageTypes(
168+
{
169+
name: "my-package",
170+
type: "module",
171+
exports: {
172+
".": {
173+
// Entry-point for `import "my-package"` in ESM
174+
import: {
175+
// Where TypeScript will look.
176+
types: "./types/esm/index.d.ts",
177+
// Where Node.js will look.
178+
default: "./esm/index.js",
179+
},
180+
// Entry-point for `require("my-package") in CJS
181+
require: {
182+
// Where TypeScript will look.
183+
types: "./types/commonjs/index.d.cts",
184+
// Where Node.js will look.
185+
default: "./commonjs/index.cjs",
186+
},
187+
},
188+
},
189+
// Fall-back for older versions of TypeScript
190+
types: "./types/index.d.ts",
191+
// CJS fall-back for older versions of Node.js
192+
main: "./commonjs/index.cjs",
193+
},
194+
".",
195+
),
196+
).resolves.toBe("./types/esm/index.d.ts");
197+
});
198+
199+
// https://www.typescriptlang.org/docs/handbook/modules/reference.html#example-explicit-types-condition
200+
test("ts module handbook explicit types", async () => {
201+
await expect(
202+
_packageTypes(
203+
{
204+
name: "pkg",
205+
exports: {
206+
"./subpath": {
207+
import: {
208+
types: "./types/subpath/index.d.mts",
209+
default: "./es/subpath/index.mjs",
210+
},
211+
require: {
212+
types: "./types/subpath/index.d.cts",
213+
default: "./cjs/subpath/index.cjs",
214+
},
215+
},
216+
},
217+
},
218+
"subpath",
219+
),
220+
).resolves.toBe("./types/subpath/index.d.mts");
221+
});
222+
223+
// https://www.typescriptlang.org/docs/handbook/modules/reference.html#example-subpath-patterns
224+
test("ts module handbook subpath patterns", async () => {
225+
await expect(
226+
_packageTypes(
227+
{
228+
name: "pkg",
229+
type: "module",
230+
exports: {
231+
"./*.js": {
232+
types: "./types/*.d.ts",
233+
default: "./dist/*.js",
234+
},
235+
},
236+
},
237+
"wildcard.js",
238+
),
239+
).resolves.toBe("./types/wildcard.d.ts");
240+
});

src/package-types.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,7 @@ export class PackageTypesError extends Data.TaggedError("PackageTypesError") {}
1515
*/
1616
export const packageTypes = (pkgJson: Partial<NormalizedPackageJson>, subpath: string) =>
1717
Effect.gen(function* () {
18-
const resolvedPaths = yield* resolveExports(pkgJson, subpath);
19-
const firstPath = resolvedPaths[0];
18+
const firstPath = yield* resolveExports(pkgJson, subpath);
2019
if (firstPath && isTypesFile(firstPath)) {
2120
return firstPath;
2221
}
@@ -34,12 +33,12 @@ const resolveExports = (pkgJson: Partial<NormalizedPackageJson>, subpath: string
3433
try {
3534
const resolvedPaths =
3635
exports(pkgJson, subpath, {
37-
conditions: ["types"],
36+
conditions: ["types", "import", "node"],
3837
unsafe: true,
3938
}) ?? [];
40-
return Effect.succeed(resolvedPaths as string[]);
39+
return Effect.succeed(resolvedPaths[0] as string | undefined);
4140
} catch {
42-
return Effect.succeed([]);
41+
return Effect.succeed(undefined);
4342
}
4443
};
4544

0 commit comments

Comments
 (0)