@@ -73,23 +73,13 @@ export async function resolveUi(options: RemoteUiOptions): Promise<UiResolution>
7373 const previousDir = path . join ( uiRoot , "previous" )
7474
7575 if ( ! options . autoUpdate ) {
76- const local = await resolveStaticUiDir ( currentDir )
77- if ( local ) {
78- return {
79- uiStaticDir : local ,
80- source : "downloaded" ,
81- uiVersion : await readUiVersion ( local ) ,
82- supported : true ,
83- }
84- }
85-
86- const bundled = await resolveStaticUiDir ( options . bundledUiDir )
87- return {
88- uiStaticDir : bundled ?? options . bundledUiDir ,
89- source : bundled ? "bundled" : "missing" ,
90- uiVersion : bundled ? await readUiVersion ( bundled ) : undefined ,
76+ return await resolveFromCacheOrBundled ( {
77+ logger : options . logger ,
78+ bundledUiDir : options . bundledUiDir ,
79+ currentDir,
80+ previousDir,
9181 supported : true ,
92- }
82+ } )
9383 }
9484
9585 let manifest : RemoteUiManifest | null = null
@@ -125,20 +115,28 @@ export async function resolveUi(options: RemoteUiOptions): Promise<UiResolution>
125115 } )
126116 }
127117
128- const currentVersion = await readUiVersion ( currentDir )
129- if ( currentVersion && currentVersion === manifest . latestUIVersion ) {
130- const currentResolved = await resolveStaticUiDir ( currentDir )
131- if ( currentResolved ) {
132- return {
133- uiStaticDir : currentResolved ,
134- source : "downloaded" ,
135- uiVersion : currentVersion ,
136- supported : true ,
137- latestServerVersion : manifest . latestServerVersion ,
138- latestServerUrl : manifest . latestServerUrl ,
139- minServerVersion : manifest . minServerVersion ,
140- }
141- }
118+ const bestLocal = await pickBestLocalUi ( {
119+ logger : options . logger ,
120+ bundledUiDir : options . bundledUiDir ,
121+ currentDir,
122+ previousDir,
123+ } )
124+
125+ const remoteIsNewer =
126+ ! bestLocal ||
127+ compareSemverMaybe ( manifest . latestUIVersion , bestLocal . uiVersion ) > 0
128+
129+ if ( ! remoteIsNewer ) {
130+ return await resolveFromCacheOrBundled ( {
131+ logger : options . logger ,
132+ bundledUiDir : options . bundledUiDir ,
133+ currentDir,
134+ previousDir,
135+ supported : true ,
136+ latestServerVersion : manifest . latestServerVersion ,
137+ latestServerUrl : manifest . latestServerUrl ,
138+ minServerVersion : manifest . minServerVersion ,
139+ } )
142140 }
143141
144142 try {
@@ -206,40 +204,18 @@ async function resolveFromCacheOrBundled(args: {
206204 latestServerUrl ?: string
207205 minServerVersion ?: string
208206} ) : Promise < UiResolution > {
209- const currentResolved = await resolveStaticUiDir ( args . currentDir )
210- if ( currentResolved ) {
211- return {
212- uiStaticDir : currentResolved ,
213- source : "downloaded" ,
214- uiVersion : await readUiVersion ( currentResolved ) ,
215- supported : args . supported ,
216- message : args . message ,
217- latestServerVersion : args . latestServerVersion ,
218- latestServerUrl : args . latestServerUrl ,
219- minServerVersion : args . minServerVersion ,
220- }
221- }
222-
223- const previousResolved = await resolveStaticUiDir ( args . previousDir )
224- if ( previousResolved ) {
225- return {
226- uiStaticDir : previousResolved ,
227- source : "previous" ,
228- uiVersion : await readUiVersion ( previousResolved ) ,
229- supported : args . supported ,
230- message : args . message ,
231- latestServerVersion : args . latestServerVersion ,
232- latestServerUrl : args . latestServerUrl ,
233- minServerVersion : args . minServerVersion ,
234- }
235- }
207+ const bestLocal = await pickBestLocalUi ( {
208+ logger : args . logger ,
209+ bundledUiDir : args . bundledUiDir ,
210+ currentDir : args . currentDir ,
211+ previousDir : args . previousDir ,
212+ } )
236213
237- const bundledResolved = await resolveStaticUiDir ( args . bundledUiDir )
238- if ( bundledResolved ) {
214+ if ( bestLocal ) {
239215 return {
240- uiStaticDir : bundledResolved ,
241- source : "bundled" ,
242- uiVersion : await readUiVersion ( bundledResolved ) ,
216+ uiStaticDir : bestLocal . uiStaticDir ,
217+ source : bestLocal . source ,
218+ uiVersion : bestLocal . uiVersion ,
243219 supported : args . supported ,
244220 message : args . message ,
245221 latestServerVersion : args . latestServerVersion ,
@@ -260,6 +236,66 @@ async function resolveFromCacheOrBundled(args: {
260236 }
261237}
262238
239+ async function pickBestLocalUi ( args : {
240+ logger : Logger
241+ bundledUiDir : string
242+ currentDir : string
243+ previousDir : string
244+ } ) : Promise < { uiStaticDir : string ; source : UiSource ; uiVersion ?: string } | null > {
245+ const candidates : Array < { uiStaticDir : string ; source : UiSource ; uiVersion ?: string ; priority : number } > = [ ]
246+
247+ const currentResolved = await resolveStaticUiDir ( args . currentDir )
248+ if ( currentResolved ) {
249+ candidates . push ( {
250+ uiStaticDir : currentResolved ,
251+ source : "downloaded" ,
252+ uiVersion : await readUiVersion ( currentResolved ) ,
253+ priority : 2 ,
254+ } )
255+ }
256+
257+ const bundledResolved = await resolveStaticUiDir ( args . bundledUiDir )
258+ if ( bundledResolved ) {
259+ candidates . push ( {
260+ uiStaticDir : bundledResolved ,
261+ source : "bundled" ,
262+ uiVersion : await readUiVersion ( bundledResolved ) ,
263+ priority : 1 ,
264+ } )
265+ }
266+
267+ const previousResolved = await resolveStaticUiDir ( args . previousDir )
268+ if ( previousResolved ) {
269+ candidates . push ( {
270+ uiStaticDir : previousResolved ,
271+ source : "previous" ,
272+ uiVersion : await readUiVersion ( previousResolved ) ,
273+ priority : 0 ,
274+ } )
275+ }
276+
277+ if ( candidates . length === 0 ) {
278+ return null
279+ }
280+
281+ candidates . sort ( ( a , b ) => {
282+ const versionCmp = compareSemverMaybe ( a . uiVersion , b . uiVersion )
283+ if ( versionCmp !== 0 ) return - versionCmp
284+ return b . priority - a . priority
285+ } )
286+
287+ const best = candidates [ 0 ]
288+ if ( ! best ) return null
289+ return { uiStaticDir : best . uiStaticDir , source : best . source , uiVersion : best . uiVersion }
290+ }
291+
292+ function compareSemverMaybe ( a : string | undefined , b : string | undefined ) : number {
293+ if ( ! a && ! b ) return 0
294+ if ( ! a ) return - 1
295+ if ( ! b ) return 1
296+ return compareSemverCore ( a , b )
297+ }
298+
263299async function resolveStaticUiDir ( uiDir : string ) : Promise < string | null > {
264300 try {
265301 const indexPath = path . join ( uiDir , "index.html" )
0 commit comments