@@ -4,8 +4,6 @@ import chalk from 'chalk';
44import ora from 'ora' ;
55import { Command } from 'commander' ;
66import { glob } from 'glob' ;
7- import { exec } from 'child_process' ;
8- import { promisify } from 'util' ;
97import fsPromises from 'fs/promises' ;
108import type { CompilerOptions , Diagnostic } from 'typescript' ;
119import { loadConfig , resolveConfigPaths } from '../config' ;
@@ -22,12 +20,24 @@ import {
2220 VERSION ,
2321} from '@opensyntaxhq/autodocs-core' ;
2422
25- const execAsync = promisify ( exec ) ;
26-
2723function toCompilerOptions ( options ?: Record < string , unknown > ) : CompilerOptions | undefined {
2824 return options ? ( options as unknown as CompilerOptions ) : undefined ;
2925}
3026
27+ interface UiSourceCandidate {
28+ label : string ;
29+ distDir : string ;
30+ }
31+
32+ async function pathExists ( target : string ) : Promise < boolean > {
33+ try {
34+ await fsPromises . access ( target ) ;
35+ return true ;
36+ } catch {
37+ return false ;
38+ }
39+ }
40+
3141interface BuildOptions {
3242 config ?: string ;
3343 output ?: string ;
@@ -258,50 +268,49 @@ export async function buildReactUI(
258268 siteName ?: string ;
259269 }
260270) : Promise < void > {
261- // Find the UI package using require.resolve - works in monorepo
262- let uiDir : string ;
263- let uiDistDir : string ;
271+ const candidates : UiSourceCandidate [ ] = [ ] ;
272+ const candidateDistDirs = new Set < string > ( ) ;
273+ const addCandidate = ( candidate : UiSourceCandidate ) : void => {
274+ if ( candidateDistDirs . has ( candidate . distDir ) ) {
275+ return ;
276+ }
277+ candidateDistDirs . add ( candidate . distDir ) ;
278+ candidates . push ( candidate ) ;
279+ } ;
264280
265281 if ( options . uiDir ) {
266- uiDir = options . uiDir ;
267- uiDistDir = path . join ( uiDir , 'dist' ) ;
282+ addCandidate ( {
283+ label : `custom uiDir (${ options . uiDir } )` ,
284+ distDir : path . join ( options . uiDir , 'dist' ) ,
285+ } ) ;
268286 } else {
269- try {
270- // Try to resolve the UI package from the monorepo
271- const uiPackageJson = require . resolve ( '@opensyntaxhq/autodocs-ui/package.json' ) ;
272- uiDir = path . dirname ( uiPackageJson ) ;
273- uiDistDir = path . join ( uiDir , 'dist' ) ;
274- } catch {
275- // Fallback: resolve relative to CLI package in monorepo
276- uiDir = path . resolve ( __dirname , '../../ui' ) ;
277- uiDistDir = path . join ( uiDir , 'dist' ) ;
278- }
287+ // Bundled UI assets are the primary source for published CLI packages.
288+ addCandidate ( {
289+ label : 'bundled CLI assets' ,
290+ distDir : path . resolve ( __dirname , '../ui-dist' ) ,
291+ } ) ;
292+ addCandidate ( {
293+ label : 'bundled CLI assets' ,
294+ distDir : path . resolve ( __dirname , '../../ui-dist' ) ,
295+ } ) ;
279296 }
280297
281- // Check if UI package exists
282- try {
283- await fsPromises . access ( uiDir ) ;
284- } catch {
285- // UI package not found, fall back to basic HTML
286- spinner . text = 'React UI not found, using basic HTML generator...' ;
287- const { generateHtml } = await import ( '@opensyntaxhq/autodocs-core' ) ;
288- await generateHtml ( docs , outputDir ) ;
289- return ;
298+ let selectedSource : UiSourceCandidate | null = null ;
299+ for ( const candidate of candidates ) {
300+ if ( await pathExists ( candidate . distDir ) ) {
301+ selectedSource = candidate ;
302+ break ;
303+ }
290304 }
291305
292- // Step 1: Build the React UI
293- spinner . text = 'Building React UI...' ;
294-
295- try {
296- await execAsync ( 'npm run build' , { cwd : uiDir } ) ;
297- } catch {
298- spinner . fail ( chalk . red ( 'Failed to build React UI, falling back to basic HTML' ) ) ;
306+ if ( ! selectedSource ) {
307+ spinner . text = 'React UI not found, using basic HTML generator...' ;
299308 const { generateHtml } = await import ( '@opensyntaxhq/autodocs-core' ) ;
300309 await generateHtml ( docs , outputDir ) ;
301310 return ;
302311 }
303312
304- spinner . succeed ( chalk . green ( ' React UI built' ) ) ;
313+ spinner . succeed ( chalk . green ( ` React UI ready ( ${ selectedSource . label } )` ) ) ;
305314
306315 // Step 2: Clean and create output directory
307316 spinner . start ( 'Preparing output directory...' ) ;
@@ -310,9 +319,9 @@ export async function buildReactUI(
310319 await fsPromises . mkdir ( outputDir , { recursive : true } ) ;
311320
312321 // Step 3: Copy React UI assets
313- spinner . text = ' Copying UI assets...' ;
322+ spinner . text = ` Copying UI assets ( ${ selectedSource . label } )...` ;
314323
315- await copyDirectory ( uiDistDir , outputDir ) ;
324+ await copyDirectory ( selectedSource . distDir , outputDir ) ;
316325
317326 spinner . succeed ( chalk . green ( 'UI assets copied' ) ) ;
318327
0 commit comments