@@ -23,10 +23,13 @@ const BUILD_TIMEOUT = 5 * 60 * 1000; // 5 minutes
2323// Create concurrency limiter
2424const limit = pLimit ( MAX_CONCURRENT_BUILDS ) ;
2525
26+ // Workspace directories containing examples
27+ const WORKSPACES = [ 'nx' , 'vanilla' , 'turborepo' ] ;
28+
2629// Check if build is needed based on file timestamps
2730function needsBuild ( folderPath : string , skipCache : boolean = false ) : boolean {
2831 if ( skipCache ) return true ;
29-
32+
3033 try {
3134 const packagePath = join ( folderPath , "package.json" ) ;
3235 const distPath = join ( folderPath , "dist" ) ;
@@ -45,79 +48,130 @@ function needsBuild(folderPath: string, skipCache: boolean = false): boolean {
4548
4649interface BuildResult {
4750 example : string ;
51+ workspace : string ;
4852 result : string ;
4953}
5054
55+ interface ExampleInfo {
56+ name : string ;
57+ workspace : string ;
58+ path : string ;
59+ }
60+
61+ // Discover all examples across all workspaces
62+ function discoverExamples ( ) : ExampleInfo [ ] {
63+ const rootPath = join ( __dirname , "../.." ) ;
64+ const allExamples : ExampleInfo [ ] = [ ] ;
65+
66+ for ( const workspace of WORKSPACES ) {
67+ const workspacePath = join ( rootPath , workspace ) ;
68+ const examplesPath = join ( workspacePath , "examples" ) ;
69+
70+ if ( ! existsSync ( examplesPath ) ) {
71+ console . log ( `${ orange ( `Warning: ${ workspace } /examples not found, skipping...` ) } ` ) ;
72+ continue ;
73+ }
74+
75+ const examples = readdirSync ( examplesPath ) ;
76+
77+ for ( const example of examples ) {
78+ const examplePath = join ( examplesPath , example ) ;
79+ const packagePath = join ( examplePath , "package.json" ) ;
80+
81+ // Only include if it has a package.json
82+ if ( existsSync ( packagePath ) ) {
83+ allExamples . push ( {
84+ name : example ,
85+ workspace,
86+ path : examplePath ,
87+ } ) ;
88+ }
89+ }
90+ }
91+
92+ return allExamples ;
93+ }
94+
5195const buildPackages = async ( ) : Promise < void > => {
5296 // Parse command line arguments
5397 const args = process . argv . slice ( 2 ) ;
5498 const skipCache = args . includes ( '--skip-cache' ) ;
5599 const packagesArg = args . find ( arg => arg . startsWith ( '--packages=' ) ) ;
56-
57- let examples : string [ ] ;
100+
101+ let examplesToBuild : ExampleInfo [ ] ;
58102 let buildType : string ;
59-
103+
104+ // Discover all examples
105+ const allExamples = discoverExamples ( ) ;
106+
60107 if ( packagesArg ) {
61108 // Parse comma-separated list of packages
62109 const packagesList = packagesArg . split ( '=' ) [ 1 ] ;
63- examples = packagesList ? packagesList . split ( ',' ) . filter ( Boolean ) : [ ] ;
64- buildType = "specified examples" ;
65-
66- if ( examples . length === 0 ) {
110+ const requestedExamples = packagesList ? packagesList . split ( ',' ) . filter ( Boolean ) : [ ] ;
111+
112+ if ( requestedExamples . length === 0 ) {
67113 console . log ( `\n${ green ( "No examples specified - nothing to build." ) } ` ) ;
68114 return ;
69115 }
70-
116+
117+ // Filter examples by requested names
118+ examplesToBuild = allExamples . filter ( ex => requestedExamples . includes ( ex . name ) ) ;
119+ buildType = "specified examples" ;
120+
71121 console . log ( `\n${ orange ( "-- Building specified examples only " ) } ` ) ;
72- console . log ( `${ blue ( "Examples:" ) } ${ examples . join ( ', ' ) } ` ) ;
122+ console . log ( `${ blue ( "Examples:" ) } ${ examplesToBuild . map ( ex => ` ${ ex . workspace } / ${ ex . name } ` ) . join ( ', ' ) } ` ) ;
73123 } else {
74- const examplesFolder = join ( __dirname , "../../examples" ) ;
75- examples = readdirSync ( examplesFolder ) ;
124+ examplesToBuild = allExamples ;
76125 buildType = "all examples" ;
77126 console . log ( `\n${ orange ( "-- Building all examples " ) } ` ) ;
127+ console . log ( `${ blue ( "Total examples found:" ) } ${ examplesToBuild . length } ` ) ;
128+
129+ // Show breakdown by workspace
130+ const byWorkspace = examplesToBuild . reduce ( ( acc , ex ) => {
131+ acc [ ex . workspace ] = ( acc [ ex . workspace ] || 0 ) + 1 ;
132+ return acc ;
133+ } , { } as Record < string , number > ) ;
134+
135+ Object . entries ( byWorkspace ) . forEach ( ( [ workspace , count ] ) => {
136+ console . log ( ` ${ blue ( workspace ) } : ${ count } examples` ) ;
137+ } ) ;
78138 }
79-
139+
80140 console . log ( `${ blue ( "Max concurrent builds:" ) } ${ MAX_CONCURRENT_BUILDS } ` ) ;
81141 if ( skipCache ) {
82142 console . log ( `${ orange ( "Cache skipped - forcing rebuild of all packages" ) } ` ) ;
83143 }
84144 console . log ( ) ;
85145
86146 const logFolder = join ( __dirname , "../tmp/build" , getDateString ( ) ) ;
87- const examplesFolder = join ( __dirname , "../../examples" ) ;
88147 const success : BuildResult [ ] = [ ] ;
89148 const fails : BuildResult [ ] = [ ] ;
90149 const skipped : BuildResult [ ] = [ ] ;
91150
92151 const startTime = Date . now ( ) ;
93152
94153 await Promise . all (
95- examples . map ( ( example ) =>
154+ examplesToBuild . map ( ( example ) =>
96155 limit ( async ( ) => {
97- const folderPath = join ( examplesFolder , example ) ;
156+ const { name, workspace, path : folderPath } = example ;
157+ const displayName = `${ workspace } /${ name } ` ;
98158 const packagePath = join ( folderPath , "package.json" ) ;
99- const packageExists = existsSync ( packagePath ) ;
100-
101- if ( ! packageExists ) {
102- fails . push ( { example, result : "No package.json found." } ) ;
103- return ;
104- }
105159
106160 const packageJson = JSON . parse ( readFileSync ( packagePath , "utf-8" ) ) as { scripts ?: { build ?: string } } ;
107161 if ( ! packageJson . scripts ?. build ) {
108- fails . push ( { example, result : "No build script." } ) ;
162+ fails . push ( { example : displayName , workspace , result : "No build script." } ) ;
109163 return ;
110164 }
111165
112166 // Check if build is needed (simple caching)
113167 if ( ! needsBuild ( folderPath , skipCache ) ) {
114- console . log ( `[${ blue ( example ) } ] ${ green ( "skipped - up to date" ) } ` ) ;
115- skipped . push ( { example, result : "Build cache hit" } ) ;
168+ console . log ( `[${ blue ( displayName ) } ] ${ green ( "skipped - up to date" ) } ` ) ;
169+ skipped . push ( { example : displayName , workspace , result : "Build cache hit" } ) ;
116170 return ;
117171 }
118172
119- const writeStream = await getLogWriteStream ( example , logFolder ) ;
120- console . log ( `Building [${ blue ( example ) } ] project...` ) ;
173+ const writeStream = await getLogWriteStream ( ` ${ workspace } - ${ name } ` , logFolder ) ;
174+ console . log ( `Building [${ blue ( displayName ) } ] project...` ) ;
121175
122176 const buildStart = Date . now ( ) ;
123177
@@ -135,12 +189,13 @@ const buildPackages = async (): Promise<void> => {
135189
136190 const buildTime = Date . now ( ) - buildStart ;
137191 console . log (
138- `[${ blue ( example ) } ] ${ green (
192+ `[${ blue ( displayName ) } ] ${ green (
139193 "successfully built!"
140194 ) } (${ buildTime } ms)`
141195 ) ;
142196 success . push ( {
143- example,
197+ example : displayName ,
198+ workspace,
144199 result : `Successfully built in ${ buildTime } ms` ,
145200 } ) ;
146201 } catch ( e : any ) {
@@ -150,9 +205,10 @@ const buildPackages = async (): Promise<void> => {
150205 writeStream . write ( `\nError: ${ e . message } \n` ) ;
151206 writeStream . end ( ) ;
152207
153- console . log ( `[${ blue ( example ) } ] ${ red ( "failed to build." ) } ` ) ;
208+ console . log ( `[${ blue ( displayName ) } ] ${ red ( "failed to build." ) } ` ) ;
154209 fails . push ( {
155- example,
210+ example : displayName ,
211+ workspace,
156212 result :
157213 e . code === "ETIMEDOUT"
158214 ? "Build timeout"
0 commit comments