Skip to content

Commit 88c6447

Browse files
committed
feat: extended the bundler to compiling TypeScript declaration files only, now you can compile and .d.ts, .d.cts and .d.mts file without a .ts file
1 parent 402a46d commit 88c6447

File tree

5 files changed

+255
-2
lines changed

5 files changed

+255
-2
lines changed

packages/packem/__tests__/intigration/__snapshots__/typescript.test.ts.snap

+35
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,41 @@ exports.deepKeysFromList = deeksExports.deepKeysFromList;
414414
"
415415
`;
416416
417+
exports[`packem typescript > should compile a .d.ts file into .d.cts and .d.mts > .d.cts type code output 1`] = `
418+
"declare global {
419+
interface String {
420+
421+
}
422+
}
423+
424+
type NativeStringTypes = string;
425+
426+
export type { NativeStringTypes };
427+
"
428+
`;
429+
430+
exports[`packem typescript > should compile a .d.ts file into .d.cts and .d.mts > .d.mts type code output 1`] = `
431+
"declare global {
432+
interface String {
433+
434+
}
435+
}
436+
437+
type NativeStringTypes = string;
438+
439+
export type { NativeStringTypes };
440+
"
441+
`;
442+
443+
exports[`packem typescript > should compile only a type file > .d.ts type code output 1`] = `
444+
"declare global {
445+
interface String {
446+
447+
}
448+
}
449+
"
450+
`;
451+
417452
exports[`packem typescript > should support typescript decorator > cjs code output 1`] = `
418453
"'use strict';
419454

packages/packem/__tests__/intigration/typescript.test.ts

+85
Original file line numberDiff line numberDiff line change
@@ -2914,4 +2914,89 @@ export { type DeeksOptions as DeepKeysOptions, deepKeys, deepKeysFromList };
29142914

29152915
expect(mtsContent).toMatchSnapshot("mjs content");
29162916
});
2917+
2918+
it("should compile only a type file", async () => {
2919+
expect.assertions(3);
2920+
2921+
await writeFile(`${temporaryDirectoryPath}/src/native-string-types.d.ts`, `
2922+
declare global {
2923+
interface String {
2924+
2925+
}
2926+
}
2927+
`);
2928+
2929+
await installPackage(temporaryDirectoryPath, "typescript");
2930+
await createTsConfig(temporaryDirectoryPath);
2931+
await createPackageJson(temporaryDirectoryPath, {
2932+
devDependencies: {
2933+
typescript: "*",
2934+
},
2935+
exports: {
2936+
"./native-string-types": {
2937+
types: "./native-string-types.d.ts",
2938+
},
2939+
},
2940+
});
2941+
await createPackemConfig(temporaryDirectoryPath);
2942+
2943+
const binProcess = await execPackemSync("build", [], {
2944+
cwd: temporaryDirectoryPath,
2945+
});
2946+
2947+
expect(binProcess.stderr).toBe("");
2948+
expect(binProcess.exitCode).toBe(0);
2949+
2950+
const dTsContent = await readFile(`${temporaryDirectoryPath}/dist/native-string-types.d.ts`);
2951+
2952+
expect(dTsContent).toMatchSnapshot(".d.ts type code output");
2953+
});
2954+
2955+
it("should compile a .d.ts file into .d.cts and .d.mts", async () => {
2956+
expect.assertions(4);
2957+
2958+
await writeFile(`${temporaryDirectoryPath}/src/native-string-types.d.ts`, `
2959+
declare global {
2960+
interface String {
2961+
2962+
}
2963+
}
2964+
2965+
export type NativeStringTypes = string;
2966+
`);
2967+
2968+
await installPackage(temporaryDirectoryPath, "typescript");
2969+
await createTsConfig(temporaryDirectoryPath);
2970+
await createPackageJson(temporaryDirectoryPath, {
2971+
devDependencies: {
2972+
typescript: "*",
2973+
},
2974+
exports: {
2975+
"./native-string-types": {
2976+
import: {
2977+
types: "./native-string-types.d.mts",
2978+
},
2979+
require: {
2980+
types: "./native-string-types.d.cts",
2981+
},
2982+
},
2983+
},
2984+
});
2985+
await createPackemConfig(temporaryDirectoryPath);
2986+
2987+
const binProcess = await execPackemSync("build", [], {
2988+
cwd: temporaryDirectoryPath,
2989+
});
2990+
console.log(binProcess.stdout);
2991+
expect(binProcess.stderr).toBe("");
2992+
expect(binProcess.exitCode).toBe(0);
2993+
2994+
const dCtsContent = await readFile(`${temporaryDirectoryPath}/dist/native-string-types.d.cts`);
2995+
2996+
expect(dCtsContent).toMatchSnapshot(".d.cts type code output");
2997+
2998+
const dMtsContent = await readFile(`${temporaryDirectoryPath}/dist/native-string-types.d.mts`);
2999+
3000+
expect(dMtsContent).toMatchSnapshot(".d.mts type code output");
3001+
});
29173002
});

packages/packem/__tests__/unit/hooks/preset/utils/infer-entries.test.ts

+103
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,109 @@ describe("inferEntries", () => {
363363
} satisfies InferEntriesResult);
364364
});
365365

366+
it("should handle types only within exports`", () => {
367+
expect.assertions(3);
368+
369+
createFiles(["src/test.d.ts"], temporaryDirectoryPath);
370+
371+
const result = inferEntries(
372+
{
373+
exports: {
374+
import: {
375+
types: "dist/test.d.mts",
376+
},
377+
require: {
378+
types: "dist/test.d.cts",
379+
},
380+
},
381+
},
382+
["src/", "src/test.d.ts"].map((file) => join(temporaryDirectoryPath, file)),
383+
{
384+
environment: defaultContext.environment,
385+
options: { ...defaultContext.options, declaration: true },
386+
pkg: defaultContext.pkg,
387+
} as unknown as BuildContext,
388+
);
389+
expect(result).toStrictEqual({
390+
entries: [
391+
{
392+
cjs: true,
393+
declaration: true,
394+
environment: "development",
395+
esm: true,
396+
exportKey: new Set<string>(["import", "require"]),
397+
input: join(temporaryDirectoryPath, "src/test.d.ts"),
398+
runtime: "node",
399+
},
400+
],
401+
warnings: [],
402+
} satisfies InferEntriesResult);
403+
404+
const result2 = inferEntries(
405+
{
406+
exports: {
407+
"./test": {
408+
import: {
409+
types: "dist/test.d.mts",
410+
},
411+
require: {
412+
types: "dist/test.d.cts",
413+
},
414+
},
415+
},
416+
},
417+
["src/", "src/test.d.ts"].map((file) => join(temporaryDirectoryPath, file)),
418+
{
419+
environment: defaultContext.environment,
420+
options: { ...defaultContext.options, declaration: true },
421+
pkg: defaultContext.pkg,
422+
} as unknown as BuildContext,
423+
);
424+
expect(result2).toStrictEqual({
425+
entries: [
426+
{
427+
cjs: true,
428+
declaration: true,
429+
environment: "development",
430+
esm: true,
431+
exportKey: new Set<string>(["test"]),
432+
input: join(temporaryDirectoryPath, "src/test.d.ts"),
433+
runtime: "node",
434+
},
435+
],
436+
warnings: [],
437+
} satisfies InferEntriesResult);
438+
439+
const result3 = inferEntries(
440+
{
441+
exports: {
442+
"./test": {
443+
types: "dist/test.d.ts",
444+
},
445+
},
446+
},
447+
["src/", "src/test.d.ts"].map((file) => join(temporaryDirectoryPath, file)),
448+
{
449+
environment: defaultContext.environment,
450+
options: { ...defaultContext.options, declaration: true },
451+
pkg: defaultContext.pkg,
452+
} as unknown as BuildContext,
453+
);
454+
expect(result3).toStrictEqual({
455+
entries: [
456+
{
457+
cjs: true,
458+
declaration: true,
459+
environment: "development",
460+
exportKey: new Set<string>(["test"]),
461+
input: join(temporaryDirectoryPath, "src/test.d.ts"),
462+
runtime: "node",
463+
},
464+
],
465+
warnings: [],
466+
} satisfies InferEntriesResult);
467+
});
468+
366469
it("should gracefully handles unknown entries", () => {
367470
expect.assertions(1);
368471

packages/packem/src/config/preset/utils/infer-entries.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ const inferEntries = (
210210
const sourceSlug = outputSlug.replace(new RegExp("(./)?" + context.options.outDir), context.options.sourceDir).replace("./", "");
211211

212212
const beforeSourceRegex = "(?<=/|$)";
213-
const fileExtensionRegex = isDirectory ? "" : "(\\.[cm]?[tj]sx?)$";
213+
const fileExtensionRegex = isDirectory ? "" : "(\\.d\\.[cm]?ts|(\\.[cm]?[tj]sx?))$";
214214

215215
// @see https://nodejs.org/docs/latest-v16.x/api/packages.html#subpath-patterns
216216
if (output.file.includes("/*") && output.key === "exports") {

packages/packem/src/packem/build.ts

+31-1
Original file line numberDiff line numberDiff line change
@@ -330,9 +330,12 @@ const prepareRollupConfig = (
330330
const esmEntries: BuildEntry[] = [];
331331
const cjsEntries: BuildEntry[] = [];
332332
const dtsEntries: BuildEntry[] = [];
333+
const dtsOnlyEntries: BuildEntry[] = [];
333334

334335
for (const entry of entries) {
335-
if (entry.cjs && entry.esm) {
336+
if (/\.d\.[cm]?ts$/.test(entry.input)) {
337+
dtsOnlyEntries.push(entry);
338+
} else if (entry.cjs && entry.esm) {
336339
esmAndCjsEntries.push(entry);
337340
} else if (entry.cjs) {
338341
cjsEntries.push(entry);
@@ -512,6 +515,33 @@ const prepareRollupConfig = (
512515
subDirectory,
513516
});
514517
}
518+
519+
if (environmentRuntimeContext.options.declaration && dtsOnlyEntries.length > 0) {
520+
typeBuilders.add({
521+
context: {
522+
...environmentRuntimeContext,
523+
options: {
524+
...environmentRuntimeContext.options,
525+
entries: dtsOnlyEntries,
526+
minify,
527+
rollup: {
528+
...environmentRuntimeContext.options.rollup,
529+
replace: environmentRuntimeContext.options.rollup.replace
530+
? {
531+
...environmentRuntimeContext.options.rollup.replace,
532+
values: {
533+
...environmentRuntimeContext.options.rollup.replace.values,
534+
...replaceValues,
535+
},
536+
}
537+
: false,
538+
},
539+
},
540+
},
541+
fileCache,
542+
subDirectory,
543+
});
544+
}
515545
}
516546
}
517547

0 commit comments

Comments
 (0)