Skip to content

Commit c7079ee

Browse files
authored
feat: add entry option with glob support (#214)
1 parent bf0cd5d commit c7079ee

File tree

5 files changed

+93
-2
lines changed

5 files changed

+93
-2
lines changed

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,14 +82,16 @@
8282
"birpc": "^4.0.0",
8383
"dts-resolver": "^2.1.3",
8484
"get-tsconfig": "^4.13.7",
85-
"obug": "^2.1.1"
85+
"obug": "^2.1.1",
86+
"picomatch": "^4.0.4"
8687
},
8788
"devDependencies": {
8889
"@jridgewell/source-map": "^0.3.11",
8990
"@sxzz/eslint-config": "^7.8.3",
9091
"@sxzz/prettier-config": "^2.3.1",
9192
"@sxzz/test-utils": "^0.5.15",
9293
"@types/node": "^25.5.0",
94+
"@types/picomatch": "^4.0.2",
9395
"@typescript/native-preview": "7.0.0-dev.20260325.1",
9496
"@volar/typescript": "^2.4.28",
9597
"@vue/language-core": "^3.2.6",

pnpm-lock.yaml

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/generate.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { readFile, rm } from 'node:fs/promises'
44
import path from 'node:path'
55
import { parse } from '@babel/parser'
66
import { createDebug } from 'obug'
7+
import picomatch from 'picomatch'
78
import { isolatedDeclarationSync } from 'rolldown/experimental'
89
import {
910
filename_to_dts,
@@ -47,6 +48,7 @@ export interface TsModule {
4748
export type DtsMap = Map<string, TsModule>
4849

4950
export function createGeneratePlugin({
51+
entry,
5052
tsconfig,
5153
tsconfigRaw,
5254
build,
@@ -64,6 +66,7 @@ export function createGeneratePlugin({
6466
sourcemap,
6567
}: Pick<
6668
OptionsResolved,
69+
| 'entry'
6770
| 'cwd'
6871
| 'tsconfig'
6972
| 'tsconfigRaw'
@@ -80,6 +83,13 @@ export function createGeneratePlugin({
8083
| 'emitJs'
8184
| 'sourcemap'
8285
>): Plugin {
86+
const entryMatcher = entry
87+
? picomatch(entry, {
88+
ignore: entry
89+
.filter((p: string) => p.startsWith('!'))
90+
.map((p: string) => p.slice(1)),
91+
})
92+
: undefined
8393
const dtsMap: DtsMap = new Map<string, TsModule>()
8494

8595
/**
@@ -185,7 +195,9 @@ export function createGeneratePlugin({
185195

186196
if (shouldEmit) {
187197
const mod = this.getModuleInfo(id)
188-
const isEntry = !!mod?.isEntry
198+
const isEntry = entryMatcher
199+
? entryMatcher(path.relative(cwd, id))
200+
: !!mod?.isEntry
189201
const dtsId = filename_to_dts(id)
190202
dtsMap.set(dtsId, { code, id, isEntry })
191203
debug('register dts source: %s', id)

src/options.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,21 @@ import type { IsolatedDeclarationsOptions } from 'rolldown/experimental'
1010

1111
//#region General Options
1212
export interface GeneralOptions {
13+
/**
14+
* Glob pattern(s) to filter which entry files get `.d.ts` generation.
15+
*
16+
* When specified, only entry files matching these patterns will emit `.d.ts` chunks.
17+
* When not specified, all entries get `.d.ts` generation.
18+
*
19+
* Supports negation patterns (e.g., `['**', '!src/icons/**']`) for exclusion.
20+
* Patterns are matched against file paths relative to `cwd`.
21+
*
22+
* @example
23+
* entry: 'src/index.ts'
24+
* entry: ['src/*.ts', '!src/internal/**']
25+
*/
26+
entry?: string | string[]
27+
1328
/**
1429
* The directory in which the plugin will search for the `tsconfig.json` file.
1530
*/
@@ -224,6 +239,7 @@ type Overwrite<T, U> = Pick<T, Exclude<keyof T, keyof U>> & U
224239
export type OptionsResolved = Overwrite<
225240
Required<Omit<Options, 'compilerOptions'>>,
226241
{
242+
entry?: string[]
227243
tsconfig?: string
228244
oxc: IsolatedDeclarationsOptions | false
229245
tsconfigRaw: TsConfigJson
@@ -234,6 +250,7 @@ export type OptionsResolved = Overwrite<
234250
let warnedTsgo = false
235251

236252
export function resolveOptions({
253+
entry,
237254
cwd = process.cwd(),
238255
dtsInput = false,
239256
emitDtsOnly = false,
@@ -340,7 +357,14 @@ export function resolveOptions({
340357
warnedTsgo = true
341358
}
342359

360+
const resolvedEntry = entry
361+
? Array.isArray(entry)
362+
? entry
363+
: [entry]
364+
: undefined
365+
343366
return {
367+
entry: resolvedEntry,
344368
cwd,
345369
dtsInput,
346370
emitDtsOnly,

tests/index.test.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,48 @@ test('input alias', async () => {
7070
expect(snapshot).toMatchSnapshot()
7171
})
7272

73+
test('entry option - include glob', async () => {
74+
const root = path.resolve(dirname, 'fixtures/alias')
75+
const { chunks } = await rolldownBuild(
76+
{
77+
output1: 'input1.ts',
78+
'output2/index': 'input2.ts',
79+
},
80+
[dts({ entry: 'input1.ts', emitDtsOnly: false, cwd: root })],
81+
{ cwd: root },
82+
)
83+
const fileNames = chunks.map((chunk) => chunk.fileName).toSorted()
84+
85+
expect(fileNames).toContain('output1.d.ts')
86+
expect(fileNames).toContain('output1.js')
87+
expect(fileNames).toContain('output2/index.js')
88+
expect(fileNames).not.toContain('output2/index.d.ts')
89+
})
90+
91+
test('entry option - negation glob', async () => {
92+
const root = path.resolve(dirname, 'fixtures/alias')
93+
const { chunks } = await rolldownBuild(
94+
{
95+
output1: 'input1.ts',
96+
'output2/index': 'input2.ts',
97+
},
98+
[
99+
dts({
100+
entry: ['**/*.ts', '!input2.ts'],
101+
emitDtsOnly: false,
102+
cwd: root,
103+
}),
104+
],
105+
{ cwd: root },
106+
)
107+
const fileNames = chunks.map((chunk) => chunk.fileName).toSorted()
108+
109+
expect(fileNames).toContain('output1.d.ts')
110+
expect(fileNames).toContain('output1.js')
111+
expect(fileNames).toContain('output2/index.js')
112+
expect(fileNames).not.toContain('output2/index.d.ts')
113+
})
114+
73115
test('isolated declaration error', async () => {
74116
const error = await rolldownBuild(
75117
path.resolve(dirname, 'fixtures/isolated-decl-error.ts'),

0 commit comments

Comments
 (0)