Skip to content

Commit

Permalink
Fix outExtension for dts files
Browse files Browse the repository at this point in the history
  • Loading branch information
aryaemami59 committed Oct 22, 2024
1 parent daadbc2 commit e349b33
Show file tree
Hide file tree
Showing 8 changed files with 190 additions and 17 deletions.
4 changes: 3 additions & 1 deletion src/api-extractor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,9 @@ async function rollupDtsFiles(
const declarationDir = ensureTempDeclarationDir()
const outDir = options.outDir || 'dist'
const pkg = await loadPkg(process.cwd())
const dtsExtension = defaultOutExtension({ format, pkgType: pkg.type }).dts
const dtsExtension =
options.outputExtensionMap.get(format)?.dts ||
defaultOutExtension({ format, pkgType: pkg.type }).dts

let dtsInputFilePath = path.join(
declarationDir,
Expand Down
16 changes: 12 additions & 4 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
type MaybePromise,
debouncePromise,
removeFiles,
resolveOutputExtensionMap,
slash,
toObjectEntry,
} from './utils'
Expand Down Expand Up @@ -76,14 +77,17 @@ const normalizeOptions = async (
...optionsOverride,
}

const formats =
typeof _options.format === 'string'
? [_options.format]
: _options.format || ['cjs']

const options: Partial<NormalizedOptions> = {
outDir: 'dist',
removeNodeProtocol: true,
..._options,
format:
typeof _options.format === 'string'
? [_options.format as Format]
: _options.format || ['cjs'],
format: formats,

dts:
typeof _options.dts === 'boolean'
? _options.dts
Expand Down Expand Up @@ -173,6 +177,10 @@ const normalizeOptions = async (
options.target = 'node16'
}

options.outputExtensionMap = await resolveOutputExtensionMap(
options as NormalizedOptions,
)

return options as NormalizedOptions
}

Expand Down
7 changes: 7 additions & 0 deletions src/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -272,4 +272,11 @@ export type NormalizedOptions = Omit<
tsconfigResolvePaths: Record<string, string[]>
tsconfigDecoratorMetadata?: boolean
format: Format[]
/**
* Custom file extension per each
* {@linkcode Format | module format}.
*
* @since 8.4.0
*/
outputExtensionMap: Map<Format, OutExtensionObject>
}
2 changes: 1 addition & 1 deletion src/rollup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ const getRollupConfig = async (
},
outputConfig: options.format.map((format): OutputOptions => {
const outputExtension =
options.outExtension?.({ format, options, pkgType: pkg.type }).dts ||
options.outputExtensionMap.get(format)?.dts ||
defaultOutExtension({ format, pkgType: pkg.type }).dts
return {
dir: options.outDir || 'dist',
Expand Down
40 changes: 39 additions & 1 deletion src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import path from 'node:path'
import resolveFrom from 'resolve-from'
import strip from 'strip-json-comments'
import { glob } from 'tinyglobby'
import type { Entry, Format } from './options'
import { loadPkg } from './load'
import type { Entry, Format, NormalizedOptions } from './options'

export type MaybePromise<T> = T | Promise<T>

Expand Down Expand Up @@ -242,3 +243,40 @@ export function writeFileSync(filePath: string, content: string) {
fs.mkdirSync(path.dirname(filePath), { recursive: true })
fs.writeFileSync(filePath, content)
}

/**
* Resolves the
* {@linkcode NormalizedOptions.outputExtensionMap | output extension map}
* for each specified {@linkcode Format | format}
* in the provided {@linkcode options}.
*
* @param options - The normalized options containing format and output extension details.
* @returns A {@linkcode Promise | promise} that resolves to a {@linkcode Map}, where each key is a {@linkcode Format | format} and each value is an object containing the resolved output extensions for both `js` and `dts` files.
*
* @internal
*/
export const resolveOutputExtensionMap = async (
options: NormalizedOptions,
): Promise<NormalizedOptions['outputExtensionMap']> => {
const pkg = await loadPkg(process.cwd())

const formatOutExtension = new Map(
options.format.map((format) => {
const outputExtensions = options.outExtension?.({
format,
options,
pkgType: pkg.type,
})

return [
format,
{
...defaultOutExtension({ format, pkgType: pkg.type }),
...(outputExtensions || {}),
},
] as const
}),
)

return formatOutExtension
}
71 changes: 63 additions & 8 deletions test/dts.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -258,29 +258,29 @@ test('should emit declaration files with experimentalDts', async () => {
export function sharedFunction<T>(value: T): T | null {
return value || null
}
type sharedType = {
shared: boolean
}
export type { sharedType }
`,
'src/server.ts': `
export * from './shared'
/**
* Comment for server render function
* Comment for server render function
*/
export function render(options: ServerRenderOptions): string {
return JSON.stringify(options)
}
export interface ServerRenderOptions {
/**
* Comment for ServerRenderOptions.stream
*
*
* @public
*
*
* @my_custom_tag
*/
stream: boolean
Expand All @@ -298,7 +298,7 @@ test('should emit declaration files with experimentalDts', async () => {
import * as ServerThirdPartyNamespace from 'react-dom';
export { ServerThirdPartyNamespace }
// Export a third party module
// Export a third party module
export * from 'react-dom/server';
`,
Expand All @@ -308,7 +308,7 @@ test('should emit declaration files with experimentalDts', async () => {
export function render(options: ClientRenderOptions): string {
return JSON.stringify(options)
}
export interface ClientRenderOptions {
document: boolean
}
Expand Down Expand Up @@ -473,3 +473,58 @@ test('declaration files with multiple entrypoints #316', async () => {
'dist/bar/index.d.ts',
).toMatchSnapshot()
})

test('custom dts output extension', async ({ expect, task }) => {
const { outFiles } = await run(
getTestName(),
{
'src/types.ts': `export type Person = { name: string }`,
'src/index.ts': `export const foo = [1, 2, 3]\nexport type { Person } from './types'`,
'tsup.config.ts': `export default {
name: '${task.name}',
entry: { index: 'src/index.ts' },
dts: true,
format: ['esm', 'cjs'],
outExtension({ format }) {
return {
js: format === 'esm' ? '.cjs' : '.mjs',
dts: format === 'esm' ? '.d.cts' : '.d.mts',
}
},
}`,
'package.json': JSON.stringify(
{
name: 'custom-dts-output-extension',
description: task.name,
type: 'module',
},
null,
2,
),
'tsconfig.json': JSON.stringify(
{
compilerOptions: {
outDir: './dist',
rootDir: './src',
moduleResolution: 'Bundler',
module: 'ESNext',
strict: true,
skipLibCheck: true,
},
include: ['src'],
},
null,
2,
),
},
{
entry: [],
},
)
expect(outFiles).toStrictEqual([
'index.cjs',
'index.d.cts',
'index.d.mts',
'index.mjs',
])
})
63 changes: 63 additions & 0 deletions test/experimental-dts.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { test } from 'vitest'
import { getTestName, run } from './utils.js'

test('custom outExtension works with experimentalDts', async ({
expect,
task,
}) => {
const { outFiles } = await run(
getTestName(),
{
'src/types.ts': `export type Person = { name: string }`,
'src/index.ts': `export const foo = [1, 2, 3]\nexport type { Person } from './types'`,
'tsup.config.ts': `export default {
name: '${task.name}',
entry: { index: 'src/index.ts' },
format: ['esm', 'cjs'],
experimentalDts: true,
outExtension({ format }) {
return {
js: format === 'cjs' ? '.cjs' : '.mjs',
dts: format === 'cjs' ? '.d.cts' : '.d.mts',
}
},
}`,
'package.json': JSON.stringify(
{
name: 'custom-dts-output-extension-with-experimental-dts',
description: task.name,
type: 'module',
},
null,
2,
),
'tsconfig.json': JSON.stringify(
{
compilerOptions: {
outDir: './dist',
rootDir: './src',
moduleResolution: 'Bundler',
module: 'ESNext',
strict: true,
skipLibCheck: true,
},
include: ['src'],
},
null,
2,
),
},
{
entry: [],
},
)

expect(outFiles).toStrictEqual([
'_tsup-dts-rollup.d.cts',
'_tsup-dts-rollup.d.mts',
'index.cjs',
'index.d.cts',
'index.d.mts',
'index.mjs',
])
})
4 changes: 2 additions & 2 deletions test/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ test('onSuccess: use a function from config file', async () => {
await new Promise((resolve) => {
setTimeout(() => {
console.log('world')
resolve('')
resolve('')
}, 1_000)
})
}
Expand Down Expand Up @@ -601,7 +601,7 @@ test('use rollup for treeshaking --format cjs', async () => {
}`,
'input.tsx': `
import ReactSelect from 'react-select'
export const Component = (props: {}) => {
return <ReactSelect {...props} />
};
Expand Down

0 comments on commit e349b33

Please sign in to comment.