diff --git a/packages/plugin-dts/src/tsc.ts b/packages/plugin-dts/src/tsc.ts index df52e4f23..7b58f6d52 100644 --- a/packages/plugin-dts/src/tsc.ts +++ b/packages/plugin-dts/src/tsc.ts @@ -178,13 +178,42 @@ export async function emitDts( if (bundle) { return fileName; } + + if (fileName.endsWith('.d.ts.map')) { + return fileName.replace(/\.d\.ts\.map$/, `${dtsExtension}.map`); + } + return fileName.replace(/\.d\.ts$/, dtsExtension); }; + const updateDeclarationMapContent = ( + fileName: string, + content: string, + ): string => { + if (bundle || !compilerOptions.declarationMap) { + return content; + } + + if (fileName.endsWith('.d.ts')) { + return content.replace( + /(\/\/# sourceMappingURL=.+)\.d\.ts\.map/g, + `$1${dtsExtension}.map`, + ); + } + + if (fileName.endsWith('.d.ts.map')) { + return content.replace(/("file":"[^"]*)\.d\.ts"/g, `$1${dtsExtension}"`); + } + + return content; + }; + const system: ts.System = { ...ts.sys, writeFile: (fileName, contents, writeByteOrderMark) => { - ts.sys.writeFile(renameDtsFile(fileName), contents, writeByteOrderMark); + const newFileName = renameDtsFile(fileName); + const newContents = updateDeclarationMapContent(fileName, contents); + ts.sys.writeFile(newFileName, newContents, writeByteOrderMark); }, }; @@ -203,9 +232,11 @@ export async function emitDts( onError, sourceFiles, ) => { + const newFileName = renameDtsFile(fileName); + const newContents = updateDeclarationMapContent(fileName, contents); originHost.writeFile( - renameDtsFile(fileName), - contents, + newFileName, + newContents, writeByteOrderMark, onError, sourceFiles, @@ -254,9 +285,11 @@ export async function emitDts( onError, sourceFiles, ) => { + const newFileName = renameDtsFile(fileName); + const newContents = updateDeclarationMapContent(fileName, contents); originHost.writeFile( - renameDtsFile(fileName), - contents, + newFileName, + newContents, writeByteOrderMark, onError, sourceFiles, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 30bc60df4..ead9ad0a9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -718,6 +718,8 @@ importers: tests/integration/dts/build/clean: {} + tests/integration/dts/build/declaration-map: {} + tests/integration/dts/build/dist-path: {} tests/integration/dts/build/process-files: {} @@ -736,6 +738,8 @@ importers: tests/integration/dts/bundle-false/declaration-dir: {} + tests/integration/dts/bundle-false/declaration-map: {} + tests/integration/dts/bundle-false/dist-path: {} tests/integration/dts/bundle-false/false: {} @@ -788,6 +792,8 @@ importers: tests/integration/dts/composite/clean: {} + tests/integration/dts/composite/declaration-map: {} + tests/integration/dts/composite/dist-path: {} tests/integration/dts/composite/process-files: {} diff --git a/tests/integration/dts/build/declaration-map/package.json b/tests/integration/dts/build/declaration-map/package.json new file mode 100644 index 000000000..b03389c74 --- /dev/null +++ b/tests/integration/dts/build/declaration-map/package.json @@ -0,0 +1,6 @@ +{ + "name": "dts-build-declaration-map-test", + "version": "1.0.0", + "private": true, + "type": "module" +} diff --git a/tests/integration/dts/build/declaration-map/rslib.config.ts b/tests/integration/dts/build/declaration-map/rslib.config.ts new file mode 100644 index 000000000..4eeb9a36a --- /dev/null +++ b/tests/integration/dts/build/declaration-map/rslib.config.ts @@ -0,0 +1,27 @@ +import { defineConfig } from '@rslib/core'; +import { generateBundleCjsConfig, generateBundleEsmConfig } from 'test-helper'; + +export default defineConfig({ + lib: [ + generateBundleEsmConfig({ + bundle: false, + dts: { + autoExtension: true, + build: true, + }, + source: { + tsconfigPath: './tsconfig.esm.json', + }, + }), + generateBundleCjsConfig({ + bundle: false, + dts: { + autoExtension: true, + build: true, + }, + source: { + tsconfigPath: './tsconfig.cjs.json', + }, + }), + ], +}); diff --git a/tests/integration/dts/build/declaration-map/src/index.ts b/tests/integration/dts/build/declaration-map/src/index.ts new file mode 100644 index 000000000..cc798ff50 --- /dev/null +++ b/tests/integration/dts/build/declaration-map/src/index.ts @@ -0,0 +1 @@ +export const a = 1; diff --git a/tests/integration/dts/build/declaration-map/tsconfig.cjs.json b/tests/integration/dts/build/declaration-map/tsconfig.cjs.json new file mode 100644 index 000000000..0f1a77420 --- /dev/null +++ b/tests/integration/dts/build/declaration-map/tsconfig.cjs.json @@ -0,0 +1,16 @@ +{ + "extends": "@rslib/tsconfig/base", + "compilerOptions": { + "baseUrl": "./", + "rootDir": "src", + "declaration": true, + "declarationMap": true, + "declarationDir": "./dist/cjs" + }, + "include": ["src"], + "references": [ + { + "path": "../__references__" + } + ] +} diff --git a/tests/integration/dts/build/declaration-map/tsconfig.esm.json b/tests/integration/dts/build/declaration-map/tsconfig.esm.json new file mode 100644 index 000000000..bd1f7aa33 --- /dev/null +++ b/tests/integration/dts/build/declaration-map/tsconfig.esm.json @@ -0,0 +1,16 @@ +{ + "extends": "@rslib/tsconfig/base", + "compilerOptions": { + "baseUrl": "./", + "rootDir": "src", + "declaration": true, + "declarationMap": true, + "declarationDir": "./dist/esm" + }, + "include": ["src"], + "references": [ + { + "path": "../__references__" + } + ] +} diff --git a/tests/integration/dts/bundle-false/declaration-map/package.json b/tests/integration/dts/bundle-false/declaration-map/package.json new file mode 100644 index 000000000..c666c0007 --- /dev/null +++ b/tests/integration/dts/bundle-false/declaration-map/package.json @@ -0,0 +1,6 @@ +{ + "name": "dts-bundle-false-declaration-map-test", + "version": "1.0.0", + "private": true, + "type": "module" +} diff --git a/tests/integration/dts/bundle-false/declaration-map/rslib.config.ts b/tests/integration/dts/bundle-false/declaration-map/rslib.config.ts new file mode 100644 index 000000000..cd0dbfdfd --- /dev/null +++ b/tests/integration/dts/bundle-false/declaration-map/rslib.config.ts @@ -0,0 +1,19 @@ +import { defineConfig } from '@rslib/core'; +import { generateBundleCjsConfig, generateBundleEsmConfig } from 'test-helper'; + +export default defineConfig({ + lib: [ + generateBundleEsmConfig({ + bundle: false, + dts: { + autoExtension: true, + }, + }), + generateBundleCjsConfig({ + bundle: false, + dts: { + autoExtension: true, + }, + }), + ], +}); diff --git a/tests/integration/dts/bundle-false/declaration-map/src/index.ts b/tests/integration/dts/bundle-false/declaration-map/src/index.ts new file mode 100644 index 000000000..cc798ff50 --- /dev/null +++ b/tests/integration/dts/bundle-false/declaration-map/src/index.ts @@ -0,0 +1 @@ +export const a = 1; diff --git a/tests/integration/dts/bundle-false/declaration-map/tsconfig.json b/tests/integration/dts/bundle-false/declaration-map/tsconfig.json new file mode 100644 index 000000000..430d1cb64 --- /dev/null +++ b/tests/integration/dts/bundle-false/declaration-map/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "@rslib/tsconfig/base", + "compilerOptions": { + "baseUrl": "./", + "declaration": true, + "declarationMap": true + }, + "include": ["src"] +} diff --git a/tests/integration/dts/composite/declaration-map/package.json b/tests/integration/dts/composite/declaration-map/package.json new file mode 100644 index 000000000..f36bee617 --- /dev/null +++ b/tests/integration/dts/composite/declaration-map/package.json @@ -0,0 +1,6 @@ +{ + "name": "dts-composite-declaration-map-test", + "version": "1.0.0", + "private": true, + "type": "module" +} diff --git a/tests/integration/dts/composite/declaration-map/rslib.config.ts b/tests/integration/dts/composite/declaration-map/rslib.config.ts new file mode 100644 index 000000000..cd0dbfdfd --- /dev/null +++ b/tests/integration/dts/composite/declaration-map/rslib.config.ts @@ -0,0 +1,19 @@ +import { defineConfig } from '@rslib/core'; +import { generateBundleCjsConfig, generateBundleEsmConfig } from 'test-helper'; + +export default defineConfig({ + lib: [ + generateBundleEsmConfig({ + bundle: false, + dts: { + autoExtension: true, + }, + }), + generateBundleCjsConfig({ + bundle: false, + dts: { + autoExtension: true, + }, + }), + ], +}); diff --git a/tests/integration/dts/composite/declaration-map/src/index.ts b/tests/integration/dts/composite/declaration-map/src/index.ts new file mode 100644 index 000000000..cc798ff50 --- /dev/null +++ b/tests/integration/dts/composite/declaration-map/src/index.ts @@ -0,0 +1 @@ +export const a = 1; diff --git a/tests/integration/dts/composite/declaration-map/tsconfig.json b/tests/integration/dts/composite/declaration-map/tsconfig.json new file mode 100644 index 000000000..c723ba999 --- /dev/null +++ b/tests/integration/dts/composite/declaration-map/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "@rslib/tsconfig/base", + "compilerOptions": { + "baseUrl": "./", + "rootDir": "./src", + "composite": true, + "declarationMap": true + }, + "include": ["src"] +} diff --git a/tests/integration/dts/index.test.ts b/tests/integration/dts/index.test.ts index ebb973eaa..1db5a0e23 100644 --- a/tests/integration/dts/index.test.ts +++ b/tests/integration/dts/index.test.ts @@ -191,6 +191,53 @@ describe('dts when bundle: false', () => { } `); }); + + test('declarationMap', async () => { + const fixturePath = join(__dirname, 'bundle-false', 'declaration-map'); + const { files, contents } = await buildAndGetResults({ + fixturePath, + type: 'dts', + }); + + expect(files.esm).toMatchInlineSnapshot(` + [ + "/tests/integration/dts/bundle-false/declaration-map/dist/esm/index.d.ts", + "/tests/integration/dts/bundle-false/declaration-map/dist/esm/index.d.ts.map", + ] + `); + + expect(files.cjs).toMatchInlineSnapshot(` + [ + "/tests/integration/dts/bundle-false/declaration-map/dist/cjs/index.d.cts", + "/tests/integration/dts/bundle-false/declaration-map/dist/cjs/index.d.cts.map", + ] + `); + + const { content: indexDtsEsm } = queryContent(contents.esm, 'index.d.ts', { + basename: true, + }); + const { content: indexDtsCjs } = queryContent(contents.cjs, 'index.d.cts', { + basename: true, + }); + const { content: indexMapEsm } = queryContent( + contents.esm, + 'index.d.ts.map', + { + basename: true, + }, + ); + const { content: indexMapCjs } = queryContent( + contents.cjs, + 'index.d.cts.map', + { + basename: true, + }, + ); + expect(indexDtsEsm).toContain('//# sourceMappingURL=index.d.ts.map'); + expect(indexDtsCjs).toContain('//# sourceMappingURL=index.d.cts.map'); + expect(indexMapEsm).toContain('"file":"index.d.ts"'); + expect(indexMapCjs).toContain('"file":"index.d.cts"'); + }); }); describe('dts when bundle: true', () => { @@ -597,6 +644,69 @@ describe('dts when build: true', () => { const esmBuildInfoPath = join(fixturePath, 'tsconfig.esm.tsbuildinfo'); expect(existsSync(esmBuildInfoPath)).toBeTruthy(); }); + + test('declarationMap', async () => { + const fixturePath = join(__dirname, 'build', 'declaration-map'); + const { files, contents } = await buildAndGetResults({ + fixturePath, + type: 'dts', + }); + + expect(files.esm).toMatchInlineSnapshot(` + [ + "/tests/integration/dts/build/declaration-map/dist/esm/index.d.ts", + "/tests/integration/dts/build/declaration-map/dist/esm/index.d.ts.map", + ] + `); + + expect(files.cjs).toMatchInlineSnapshot(` + [ + "/tests/integration/dts/build/declaration-map/dist/cjs/index.d.cts", + "/tests/integration/dts/build/declaration-map/dist/cjs/index.d.cts.map", + ] + `); + + const { content: indexDtsEsm } = queryContent(contents.esm, 'index.d.ts', { + basename: true, + }); + const { content: indexDtsCjs } = queryContent(contents.cjs, 'index.d.cts', { + basename: true, + }); + const { content: indexMapEsm } = queryContent( + contents.esm, + 'index.d.ts.map', + { + basename: true, + }, + ); + const { content: indexMapCjs } = queryContent( + contents.cjs, + 'index.d.cts.map', + { + basename: true, + }, + ); + expect(indexDtsEsm).toContain('//# sourceMappingURL=index.d.ts.map'); + expect(indexDtsCjs).toContain('//# sourceMappingURL=index.d.cts.map'); + expect(indexMapEsm).toContain('"file":"index.d.ts"'); + expect(indexMapCjs).toContain('"file":"index.d.cts"'); + + const referenceEsmDistPath = join( + fixturePath, + '../__references__/dist/index.d.ts', + ); + const referenceCjsDistPath = join( + fixturePath, + '../__references__/dist/index.d.cts', + ); + expect(existsSync(referenceEsmDistPath)).toBeTruthy(); + expect(existsSync(referenceCjsDistPath)).toBeTruthy(); + + const esmBuildInfoPath = join(fixturePath, 'tsconfig.esm.tsbuildinfo'); + const cjsBuildInfoPath = join(fixturePath, 'tsconfig.cjs.tsbuildinfo'); + expect(existsSync(esmBuildInfoPath)).toBeTruthy(); + expect(existsSync(cjsBuildInfoPath)).toBeTruthy(); + }); }); describe('dts when composite: true', () => { @@ -736,6 +846,56 @@ describe('dts when composite: true', () => { const buildInfoPath = join(fixturePath, 'tsconfig.tsbuildinfo'); expect(existsSync(buildInfoPath)).toBeTruthy(); }); + + test('declarationMap', async () => { + const fixturePath = join(__dirname, 'composite', 'declaration-map'); + const { files, contents } = await buildAndGetResults({ + fixturePath, + type: 'dts', + }); + + expect(files.esm).toMatchInlineSnapshot(` + [ + "/tests/integration/dts/composite/declaration-map/dist/esm/index.d.ts", + "/tests/integration/dts/composite/declaration-map/dist/esm/index.d.ts.map", + ] + `); + + expect(files.cjs).toMatchInlineSnapshot(` + [ + "/tests/integration/dts/composite/declaration-map/dist/cjs/index.d.cts", + "/tests/integration/dts/composite/declaration-map/dist/cjs/index.d.cts.map", + ] + `); + + const { content: indexDtsEsm } = queryContent(contents.esm, 'index.d.ts', { + basename: true, + }); + const { content: indexDtsCjs } = queryContent(contents.cjs, 'index.d.cts', { + basename: true, + }); + const { content: indexMapEsm } = queryContent( + contents.esm, + 'index.d.ts.map', + { + basename: true, + }, + ); + const { content: indexMapCjs } = queryContent( + contents.cjs, + 'index.d.cts.map', + { + basename: true, + }, + ); + expect(indexDtsEsm).toContain('//# sourceMappingURL=index.d.ts.map'); + expect(indexDtsCjs).toContain('//# sourceMappingURL=index.d.cts.map'); + expect(indexMapEsm).toContain('"file":"index.d.ts"'); + expect(indexMapCjs).toContain('"file":"index.d.cts"'); + + const buildInfoPath = join(fixturePath, 'tsconfig.tsbuildinfo'); + expect(existsSync(buildInfoPath)).toBeTruthy(); + }); }); describe('use with other features', async () => {