@@ -15,6 +15,7 @@ import {
1515 tsTransform ,
1616 type TransformResult ,
1717} from './core/transformer'
18+ import type { PluginBuild } from 'esbuild'
1819import type { Plugin , PluginContext } from 'rollup'
1920
2021export type { Options }
@@ -43,11 +44,15 @@ export const IsolatedDecl: UnpluginInstance<Options | undefined, false> =
4344 return this . error ( 'entryFileNames must be a string' )
4445 }
4546
46- const entryFileNames = outputOptions . entryFileNames . replace (
47+ let entryFileNames = outputOptions . entryFileNames . replace (
4748 / \. ( .) ? [ j t ] s $ / ,
4849 ( _ , s ) => `.d.${ s || '' } ts` ,
4950 )
5051
52+ if ( options . extraOutdir ) {
53+ entryFileNames = path . join ( options . extraOutdir , entryFileNames )
54+ }
55+
5156 for ( const [ filename , source ] of Object . entries ( outputFiles ) ) {
5257 this . emitFile ( {
5358 type : 'asset' ,
@@ -69,66 +74,11 @@ export const IsolatedDecl: UnpluginInstance<Options | undefined, false> =
6974 } ,
7075
7176 transform ( code , id ) : Promise < undefined > {
72- return transform . call ( this , code , id )
77+ return transform ( this , code , id )
7378 } ,
7479
7580 esbuild : {
76- setup ( build ) {
77- build . onEnd ( async ( result ) => {
78- const esbuildOptions = build . initialOptions
79-
80- const entries = esbuildOptions . entryPoints
81- if (
82- ! (
83- entries &&
84- Array . isArray ( entries ) &&
85- entries . every ( ( entry ) => typeof entry === 'string' )
86- )
87- )
88- throw new Error ( 'unsupported entryPoints, must be an string[]' )
89-
90- const outBase = lowestCommonAncestor ( ...entries )
91- const jsExt = esbuildOptions . outExtension ?. [ '.js' ]
92- let outExt : string
93- switch ( jsExt ) {
94- case '.cjs' :
95- outExt = 'cts'
96- break
97- case '.mjs' :
98- outExt = 'mts'
99- break
100- default :
101- outExt = 'ts'
102- break
103- }
104-
105- const write = build . initialOptions . write ?? true
106- if ( write ) {
107- if ( ! build . initialOptions . outdir )
108- throw new Error ( 'outdir is required when write is true' )
109- } else {
110- result . outputFiles ||= [ ]
111- }
112-
113- const textEncoder = new TextEncoder ( )
114- for ( const [ filename , source ] of Object . entries ( outputFiles ) ) {
115- const outDir = build . initialOptions . outdir
116- const outFile = `${ path . relative ( outBase , filename ) } .d.${ outExt } `
117- const filePath = outDir ? path . resolve ( outDir , outFile ) : outFile
118- if ( write ) {
119- await mkdir ( path . dirname ( filePath ) , { recursive : true } )
120- await writeFile ( filePath , source )
121- } else {
122- result . outputFiles ! . push ( {
123- path : filePath ,
124- contents : textEncoder . encode ( source ) ,
125- hash : '' ,
126- text : source ,
127- } )
128- }
129- }
130- } )
131- } ,
81+ setup : esbuildSetup ,
13282 } ,
13383 rollup,
13484 rolldown : rollup as any ,
@@ -140,7 +90,7 @@ export const IsolatedDecl: UnpluginInstance<Options | undefined, false> =
14090 }
14191
14292 async function transform (
143- this : UnpluginBuildContext & UnpluginContext ,
93+ context : UnpluginBuildContext & UnpluginContext ,
14494 code : string ,
14595 id : string ,
14696 ) : Promise < undefined > {
@@ -162,9 +112,9 @@ export const IsolatedDecl: UnpluginInstance<Options | undefined, false> =
162112 const { code : sourceText , errors } = result
163113 if ( errors . length ) {
164114 if ( options . ignoreErrors ) {
165- this . warn ( errors [ 0 ] )
115+ context . warn ( errors [ 0 ] )
166116 } else {
167- this . error ( errors [ 0 ] )
117+ context . error ( errors [ 0 ] )
168118 return
169119 }
170120 }
@@ -187,34 +137,99 @@ export const IsolatedDecl: UnpluginInstance<Options | undefined, false> =
187137 )
188138 } )
189139
190- const resolve = async ( id : string , importer : string ) => {
191- const context = this . getNativeBuildContext ?.( )
192- if ( context ?. framework === 'esbuild' ) {
193- return (
194- await context . build . resolve ( id , {
195- importer,
196- resolveDir : path . dirname ( importer ) ,
197- kind : 'import-statement' ,
198- } )
199- ) . path
200- }
201- return ( await ( this as any as PluginContext ) . resolve ( id , importer ) ) ?. id
202- }
203140 for ( const i of typeImports ) {
204- const resolved = await resolve ( i . source . value , id )
141+ const resolved = await resolve ( context , i . source . value , id )
205142 if ( resolved && filter ( resolved ) && ! outputFiles [ stripExt ( resolved ) ] ) {
206143 let source : string
207144 try {
208145 source = await readFile ( resolved , 'utf8' )
209146 } catch {
210147 continue
211148 }
212- await transform . call ( this , source , resolved )
149+ await transform ( context , source , resolved )
213150 }
214151 }
215152 }
153+
154+ function esbuildSetup ( build : PluginBuild ) {
155+ build . onEnd ( async ( result ) => {
156+ const esbuildOptions = build . initialOptions
157+
158+ const entries = esbuildOptions . entryPoints
159+ if (
160+ ! (
161+ entries &&
162+ Array . isArray ( entries ) &&
163+ entries . every ( ( entry ) => typeof entry === 'string' )
164+ )
165+ )
166+ throw new Error ( 'unsupported entryPoints, must be an string[]' )
167+
168+ const outBase = lowestCommonAncestor ( ...entries )
169+ const jsExt = esbuildOptions . outExtension ?. [ '.js' ]
170+ let outExt : string
171+ switch ( jsExt ) {
172+ case '.cjs' :
173+ outExt = 'cts'
174+ break
175+ case '.mjs' :
176+ outExt = 'mts'
177+ break
178+ default :
179+ outExt = 'ts'
180+ break
181+ }
182+
183+ const write = build . initialOptions . write ?? true
184+ if ( write ) {
185+ if ( ! build . initialOptions . outdir )
186+ throw new Error ( 'outdir is required when write is true' )
187+ } else {
188+ result . outputFiles ||= [ ]
189+ }
190+
191+ const textEncoder = new TextEncoder ( )
192+ for ( const [ filename , source ] of Object . entries ( outputFiles ) ) {
193+ const outDir = build . initialOptions . outdir
194+ let outFile = `${ path . relative ( outBase , filename ) } .d.${ outExt } `
195+ if ( options . extraOutdir ) {
196+ outFile = path . join ( options . extraOutdir , outFile )
197+ }
198+ const filePath = outDir ? path . resolve ( outDir , outFile ) : outFile
199+ if ( write ) {
200+ await mkdir ( path . dirname ( filePath ) , { recursive : true } )
201+ await writeFile ( filePath , source )
202+ } else {
203+ result . outputFiles ! . push ( {
204+ path : filePath ,
205+ contents : textEncoder . encode ( source ) ,
206+ hash : '' ,
207+ text : source ,
208+ } )
209+ }
210+ }
211+ } )
212+ }
216213 } )
217214
215+ const resolve = async (
216+ context : UnpluginBuildContext ,
217+ id : string ,
218+ importer : string ,
219+ ) => {
220+ const nativeContext = context . getNativeBuildContext ?.( )
221+ if ( nativeContext ?. framework === 'esbuild' ) {
222+ return (
223+ await nativeContext . build . resolve ( id , {
224+ importer,
225+ resolveDir : path . dirname ( importer ) ,
226+ kind : 'import-statement' ,
227+ } )
228+ ) . path
229+ }
230+ return ( await ( context as PluginContext ) . resolve ( id , importer ) ) ?. id
231+ }
232+
218233function stripExt ( filename : string ) {
219234 return filename . replace ( / \. ( .? ) [ j t ] s $ / , '' )
220235}
0 commit comments