@@ -29,6 +29,7 @@ import {
2929 addOutDirToChunks ,
3030 type RolldownChunk ,
3131 type TsdownBundle ,
32+ type TsdownHandle ,
3233} from './utils/chunks.ts'
3334import { debounce , typeAssert } from './utils/general.ts'
3435import { globalLogger } from './utils/logger.ts'
@@ -39,11 +40,37 @@ import { styleText } from './utils/style.ts'
3940 */
4041export async function build (
4142 inlineConfig : InlineConfig = { } ,
42- ) : Promise < TsdownBundle [ ] > {
43+ ) : Promise < TsdownHandle > {
4344 globalLogger . level = inlineConfig . logLevel || 'info'
44- const { configs, deps : configDeps } = await resolveConfig ( inlineConfig )
4545
46- return buildWithConfigs ( configs , configDeps , ( ) => build ( inlineConfig ) )
46+ let isConfigResolved = false
47+ const { configs, deps } = await resolveConfig ( inlineConfig , {
48+ restart,
49+ close,
50+ } )
51+ const handlePromise = buildWithConfigs ( configs , deps , ( ) =>
52+ build ( inlineConfig ) ,
53+ )
54+ isConfigResolved = true
55+ return await handlePromise
56+
57+ async function restart ( ) {
58+ if ( ! isConfigResolved ) {
59+ throw new Error (
60+ '`watch.restart` cannot be called before config resolution is complete.' ,
61+ )
62+ }
63+ return ( await handlePromise ) . watch . restart ( )
64+ }
65+
66+ async function close ( ) {
67+ if ( ! isConfigResolved ) {
68+ throw new Error (
69+ '`watch.close` cannot be called before config resolution is complete.' ,
70+ )
71+ }
72+ return ( await handlePromise ) . watch . close ( )
73+ }
4774}
4875
4976/**
@@ -55,23 +82,37 @@ export async function build(
5582export async function buildWithConfigs (
5683 configs : ResolvedConfig [ ] ,
5784 configDeps : Set < string > ,
58- _restart : ( ) => void ,
59- ) : Promise < TsdownBundle [ ] > {
85+ rebuild : ( ) => Promise < TsdownHandle > ,
86+ ) : Promise < TsdownHandle > {
87+ const hasWatchConfig = configs . some ( ( config ) => config . watch )
6088 let cleanPromise : Promise < void > | undefined
6189 const clean = ( ) => {
6290 if ( cleanPromise ) return cleanPromise
6391 return ( cleanPromise = cleanOutDir ( configs ) )
6492 }
6593
6694 const disposeCbs : Array < ( ) => void | PromiseLike < void > > = [ ]
67- let restarting = false
68- async function restart ( ) {
69- if ( restarting ) return
70- restarting = true
95+ let restarted = false
7196
97+ function assertWatchMode ( ) {
98+ if ( ! hasWatchConfig ) {
99+ throw new Error ( '`watch` is only available in watch mode.' )
100+ }
101+ }
102+ async function close ( ) {
103+ assertWatchMode ( )
72104 await Promise . all ( disposeCbs . map ( ( cb ) => cb ( ) ) )
105+ }
106+
107+ async function restart ( ) {
108+ assertWatchMode ( )
109+ if ( restarted ) {
110+ throw new Error ( '`watch.restart` can only be called once per handle.' )
111+ }
112+ restarted = true
113+ await close ( )
73114 clearRequireCache ( )
74- _restart ( )
115+ return rebuild ( )
75116 }
76117
77118 const configChunksByPkg = initBundleByPkg ( configs )
@@ -91,7 +132,10 @@ export async function buildWithConfigs(
91132 configDeps ,
92133 isDualFormat ,
93134 clean ,
94- restart ,
135+ ( ) => {
136+ if ( restarted ) return
137+ restart ( ) . catch ( ( error ) => globalLogger . error ( error ) )
138+ } ,
95139 done ,
96140 )
97141 } ) ,
@@ -101,7 +145,6 @@ export async function buildWithConfigs(
101145 ( config ) => config . devtools && config . devtools . ui ,
102146 )
103147
104- const hasWatchConfig = configs . some ( ( config ) => config . watch )
105148 if ( hasWatchConfig ) {
106149 // Watch mode with shortcuts
107150 disposeCbs . push ( shortcuts ( restart ) )
@@ -114,7 +157,10 @@ export async function buildWithConfigs(
114157 startDevtoolsUI ( firstDevtoolsConfig . devtools )
115158 }
116159
117- return bundles
160+ return {
161+ bundles,
162+ watch : { restart, close } ,
163+ }
118164}
119165
120166/**
@@ -164,7 +210,7 @@ async function buildSingle(
164210 const configs = await initBuildOptions ( )
165211 if ( watch ) {
166212 watcher = rolldownWatch ( configs )
167- handleWatcher ( watcher )
213+ await handleWatcher ( watcher )
168214 } else {
169215 const outputs = await config . runBuild ( ( ) => rolldownBuild ( configs ) )
170216 for ( const { output } of outputs ) {
@@ -183,6 +229,7 @@ async function buildSingle(
183229 return bundle
184230
185231 function handleWatcher ( watcher : RolldownWatcher ) {
232+ const ready = Promise . withResolvers < void > ( )
186233 const changedFile : string [ ] = [ ]
187234 let hasError = false
188235
@@ -226,6 +273,7 @@ async function buildSingle(
226273
227274 chunks . length = 0
228275 hasError = false
276+ ready . resolve ( )
229277 break
230278 }
231279
@@ -261,6 +309,8 @@ async function buildSingle(
261309 }
262310 }
263311 } )
312+
313+ return ready . promise
264314 }
265315
266316 async function initBuildOptions ( ) {
0 commit comments