From 0191789daffa2f1a605b21bc878e99856fe23b74 Mon Sep 17 00:00:00 2001 From: ZHAO JinXiang Date: Sun, 25 Jun 2023 14:32:29 +0800 Subject: [PATCH 1/2] feat: generate index.d.mts and index.d.cts --- README.md | 2 +- package.json | 5 ++--- src/auto.ts | 9 ++++++--- src/builder/rollup.ts | 45 ++++++++++++++++++++++++++++++++----------- test/auto.test.ts | 11 ++++++++--- 5 files changed, 51 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index d58b8e1a..960ffefa 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ Update `package.json`: } }, "main": "./dist/index.cjs", - "types": "./dist/index.d.ts", + "types": "./dist/index.d.cts", "files": [ "dist" ] diff --git a/package.json b/package.json index f654b25d..1ef9fb46 100644 --- a/package.json +++ b/package.json @@ -6,11 +6,10 @@ "license": "MIT", "exports": { ".": { - "types": "./dist/index.d.ts", - "default": "./dist/index.mjs" + "import": "./dist/index.mjs" } }, - "types": "./dist/index.d.ts", + "types": "./dist/index.d.mts", "bin": { "unbuild": "./dist/cli.mjs" }, diff --git a/src/auto.ts b/src/auto.ts index 9bc2809a..74badfe5 100644 --- a/src/auto.ts +++ b/src/auto.ts @@ -111,7 +111,10 @@ export function inferEntries( for (const output of outputs) { // Supported output file extensions are `.d.ts`, `.cjs` and `.mjs` // But we support any file extension here in case user has extended rollup options - const outputSlug = output.file.replace(/(\*[^/\\]*|\.d\.ts|\.\w+)$/, ""); + const outputSlug = output.file.replace( + /(\*[^/\\]*|\.d\.(m|c)?ts|\.\w+)$/, + "" + ); const isDir = outputSlug.endsWith("/"); // Skip top level directory @@ -128,7 +131,7 @@ export function inferEntries( const SOURCE_RE = new RegExp(`(?<=/|$)${d}${isDir ? "" : "\\.\\w+"}$`); return sourceFiles .find((i) => SOURCE_RE.test(i)) - ?.replace(/(\.d\.ts|\.\w+)$/, ""); + ?.replace(/(\.d\.(m|c)?ts|\.\w+)$/, ""); }, undefined as any); if (!input) { @@ -144,7 +147,7 @@ export function inferEntries( entries.find((i) => i.input === input) || entries[entries.push({ input }) - 1]; - if (output.file.endsWith(".d.ts")) { + if (/\.d\.(m|c)?ts$/.test(output.file)) { dts = true; } diff --git a/src/builder/rollup.ts b/src/builder/rollup.ts index ec09a28b..5de56f31 100644 --- a/src/builder/rollup.ts +++ b/src/builder/rollup.ts @@ -179,24 +179,47 @@ export async function rollupBuild(ctx: BuildContext) { await ctx.hooks.callHook("rollup:dts:options", ctx, rollupOptions); const typesBuild = await rollup(rollupOptions); await ctx.hooks.callHook("rollup:dts:build", ctx, typesBuild); + // #region cjs + if (ctx.options.rollup.emitCJS) { + await typesBuild.write({ + dir: resolve(ctx.options.rootDir, ctx.options.outDir), + entryFileNames: "[name].d.cts", + chunkFileNames: (chunk) => getChunkFilename(ctx, chunk, "d.cts"), + }); + } + // #endregion + // #region mjs + await typesBuild.write({ + dir: resolve(ctx.options.rootDir, ctx.options.outDir), + entryFileNames: "[name].d.mts", + chunkFileNames: (chunk) => getChunkFilename(ctx, chunk, "d.mts"), + }); + // #endregion + // #region .d.ts for node10 compatibility await typesBuild.write({ dir: resolve(ctx.options.rootDir, ctx.options.outDir), - format: "esm", + entryFileNames: "[name].d.ts", + chunkFileNames: (chunk) => getChunkFilename(ctx, chunk, "d.ts"), }); + // #endregion } await ctx.hooks.callHook("rollup:done", ctx); } -export function getRollupOptions(ctx: BuildContext): RollupOptions { - const getChunkFilename = (chunk: PreRenderedChunk, ext: string) => { - if (chunk.isDynamicEntry) { - return `chunks/[name].${ext}`; - } - // TODO: Find a way to generate human friendly hash for short groups - return `shared/${ctx.options.name}.[hash].${ext}`; - }; +const getChunkFilename = ( + ctx: BuildContext, + chunk: PreRenderedChunk, + ext: string +) => { + if (chunk.isDynamicEntry) { + return `chunks/[name].${ext}`; + } + // TODO: Find a way to generate human friendly hash for short groups + return `shared/${ctx.options.name}.[hash].${ext}`; +}; +export function getRollupOptions(ctx: BuildContext): RollupOptions { return ({ input: Object.fromEntries( ctx.options.entries @@ -209,7 +232,7 @@ export function getRollupOptions(ctx: BuildContext): RollupOptions { dir: resolve(ctx.options.rootDir, ctx.options.outDir), entryFileNames: "[name].cjs", chunkFileNames: (chunk: PreRenderedChunk) => - getChunkFilename(chunk, "cjs"), + getChunkFilename(ctx, chunk, "cjs"), format: "cjs", exports: "auto", interop: "compat", @@ -221,7 +244,7 @@ export function getRollupOptions(ctx: BuildContext): RollupOptions { dir: resolve(ctx.options.rootDir, ctx.options.outDir), entryFileNames: "[name].mjs", chunkFileNames: (chunk: PreRenderedChunk) => - getChunkFilename(chunk, "mjs"), + getChunkFilename(ctx, chunk, "mjs"), format: "esm", exports: "auto", generatedCode: { constBindings: true }, diff --git a/test/auto.test.ts b/test/auto.test.ts index 76a7e3e3..1fa912d8 100644 --- a/test/auto.test.ts +++ b/test/auto.test.ts @@ -133,9 +133,14 @@ describe("inferEntries", () => { const result = inferEntries( { exports: { - types: "dist/test.d.ts", - import: "dist/test.mjs", - require: "dist/test.cjs", + import: { + types: "dist/test.d.mts", + default: "dist/test.mjs", + }, + require: { + types: "dist/test.d.cts", + default: "dist/test.cjs", + }, }, }, ["src/", "src/test.ts"] From 40d96d561f765e0755acd3ca0ff147bb837a3dce Mon Sep 17 00:00:00 2001 From: ZHAO JinXiang Date: Tue, 4 Jul 2023 18:21:19 +0800 Subject: [PATCH 2/2] feat: add case "compatible" and "node16" to option declaration --- README.md | 14 ++++++++++---- package.json | 2 +- src/builder/mkdist.ts | 2 +- src/builder/rollup.ts | 17 +++++++++++------ src/types.ts | 11 +++++++++-- 5 files changed, 32 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 960ffefa..0c8cc382 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ Update `package.json`: } }, "main": "./dist/index.cjs", - "types": "./dist/index.d.cts", + "types": "./dist/index.d.ts", "files": [ "dist" ] @@ -84,7 +84,7 @@ export default { } ``` -You can either use `unbuild` key in `package.json` or `build.config.{js,ts,json}` to specify configuration. +You can either use `unbuild` key in `package.json` or `build.config.{js,cjs,mjs,ts,mts,cts,json}` to specify configuration. See options [here](./src/types.ts). @@ -109,8 +109,14 @@ export default defineBuildConfig({ // Change outDir, default is 'dist' outDir: 'build', - // Generates .d.ts declaration file - declaration: true, + /** + * * `compatible` means "src/index.ts" will generate "dist/index.d.mts", "dist/index.d.cts" and "dist/index.d.ts". + * * `node16` means "src/index.ts" will generate "dist/index.d.mts" and "dist/index.d.cts". + * * `true` is equivalent to `compatible`. + * * `false` will disable declaration generation. + * * `undefined` will auto detect based on "package.json". If "package.json" has "types" field, it will be `"compatible"`, otherwise `false`. + */ + declaration: 'compatible', }) ``` diff --git a/package.json b/package.json index 1ef9fb46..59a28470 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "import": "./dist/index.mjs" } }, - "types": "./dist/index.d.mts", + "types": "./dist/index.d.ts", "bin": { "unbuild": "./dist/cli.mjs" }, diff --git a/src/builder/mkdist.ts b/src/builder/mkdist.ts index 8a2e0dc3..c1ccc12a 100644 --- a/src/builder/mkdist.ts +++ b/src/builder/mkdist.ts @@ -20,7 +20,7 @@ export async function mkdistBuild(ctx: BuildContext) { distDir, format: entry.format, cleanDist: false, - declaration: entry.declaration, + declaration: !!entry.declaration, pattern: entry.pattern, // @ts-ignore ext: entry.ext, diff --git a/src/builder/rollup.ts b/src/builder/rollup.ts index 5de56f31..fd4185d9 100644 --- a/src/builder/rollup.ts +++ b/src/builder/rollup.ts @@ -195,12 +195,17 @@ export async function rollupBuild(ctx: BuildContext) { chunkFileNames: (chunk) => getChunkFilename(ctx, chunk, "d.mts"), }); // #endregion - // #region .d.ts for node10 compatibility - await typesBuild.write({ - dir: resolve(ctx.options.rootDir, ctx.options.outDir), - entryFileNames: "[name].d.ts", - chunkFileNames: (chunk) => getChunkFilename(ctx, chunk, "d.ts"), - }); + // #region .d.ts for node10 compatibility (TypeScript version < 4.7) + if ( + ctx.options.declaration === true || + ctx.options.declaration === "compatible" + ) { + await typesBuild.write({ + dir: resolve(ctx.options.rootDir, ctx.options.outDir), + entryFileNames: "[name].d.ts", + chunkFileNames: (chunk) => getChunkFilename(ctx, chunk, "d.ts"), + }); + } // #endregion } diff --git a/src/types.ts b/src/types.ts index 677030b8..e1456f20 100644 --- a/src/types.ts +++ b/src/types.ts @@ -20,7 +20,7 @@ export interface BaseBuildEntry { input: string; name?: string; outDir?: string; - declaration?: boolean; + declaration?: "compatible" | "node16" | boolean; } export interface UntypedBuildEntry extends BaseBuildEntry { @@ -64,7 +64,14 @@ export interface BuildOptions { rootDir: string; entries: BuildEntry[]; clean: boolean; - declaration?: boolean; + /** + * * `compatible` means "src/index.ts" will generate "dist/index.d.mts", "dist/index.d.cts" and "dist/index.d.ts". + * * `node16` means "src/index.ts" will generate "dist/index.d.mts" and "dist/index.d.cts". + * * `true` is equivalent to `compatible`. + * * `false` will disable declaration generation. + * * `undefined` will auto detect based on "package.json". If "package.json" has "types" field, it will be `"compatible"`, otherwise `false`. + */ + declaration?: "compatible" | "node16" | boolean; outDir: string; stub: boolean; externals: (string | RegExp)[];