@@ -5,9 +5,12 @@ import {
55 isProblemApp ,
66 setPlayground ,
77} from '@epic-web/workshop-utils/apps.server'
8+ import { execa } from 'execa'
89import fsExtra from 'fs-extra'
10+ import { globby } from 'globby'
911
1012await warm ( )
13+ await runAllSeeds ( )
1114
1215const allApps = await getApps ( )
1316const problemApps = allApps . filter ( isProblemApp )
@@ -32,3 +35,93 @@ if (!process.env.SKIP_PLAYGROUND) {
3235 )
3336 }
3437}
38+
39+ async function runAllSeeds ( ) {
40+ try {
41+ // Find all seed.ts files in exercises directories
42+ const seedFiles = await globby ( 'exercises/**/src/db/seed.ts' )
43+
44+ console . log (
45+ `🌱 Found ${ seedFiles . length } seed files to run to get the databases ready.` ,
46+ )
47+ for ( const file of seedFiles . toSorted ( ) ) {
48+ // Get the exercise directory (3 levels up from src/db/seed.ts)
49+ const exerciseDir = path . dirname ( path . dirname ( path . dirname ( file ) ) )
50+
51+ // Create the relative path to the seed file from the exercise directory
52+ const seedFilePath = path . relative ( exerciseDir , file )
53+
54+ const label = file . split ( path . sep ) . slice ( 1 , 3 ) . join ( path . sep )
55+ try {
56+ await execWithBufferedOutput ( 'npx' , [ 'tsx' , seedFilePath ] , {
57+ cwd : exerciseDir ,
58+ } )
59+ console . log ( ` ✓ Seeded ${ label } ` )
60+ } catch ( error ) {
61+ console . error ( `❌ Seeding failed for ${ label } :` , error . message )
62+ throw error
63+ }
64+ }
65+
66+ console . log ( '✅ All seeds completed.' )
67+ } catch ( error ) {
68+ console . error ( '❌ Seeding process failed:' , error . message )
69+ throw error
70+ }
71+ }
72+
73+ /**
74+ * Execute a command with buffered output that only displays if there's an error
75+ */
76+ async function execWithBufferedOutput ( command , args , options = { } ) {
77+ return new Promise ( ( resolve , reject ) => {
78+ const outputBuffer = [ ]
79+
80+ function addToBuffer ( channel , data ) {
81+ outputBuffer . push ( { channel, data } )
82+ }
83+
84+ function printBufferedOutput ( ) {
85+ // Print all buffered output in sequence
86+ for ( const { channel, data } of outputBuffer ) {
87+ const str = data . toString ( )
88+ if ( channel === 'stdout' ) {
89+ process . stdout . write ( str )
90+ } else if ( channel === 'stderr' ) {
91+ process . stderr . write ( str )
92+ }
93+ }
94+ }
95+
96+ const childProcess = execa ( command , args , options )
97+
98+ function bufferStdout ( data ) {
99+ addToBuffer ( 'stdout' , data )
100+ }
101+
102+ function bufferStderr ( data ) {
103+ addToBuffer ( 'stderr' , data )
104+ }
105+
106+ childProcess . stdout . on ( 'data' , bufferStdout )
107+ childProcess . stderr . on ( 'data' , bufferStderr )
108+
109+ childProcess . on ( 'error' , ( err ) => {
110+ printBufferedOutput ( )
111+ reject ( err )
112+ } )
113+
114+ childProcess . on ( 'exit' , ( code ) => {
115+ if ( code !== 0 ) {
116+ printBufferedOutput ( )
117+ reject (
118+ new Error (
119+ `Command "${ command } ${ args . join ( ' ' ) } " exited with code ${ code } ` ,
120+ ) ,
121+ )
122+ } else {
123+ resolve ( )
124+ }
125+ } )
126+ } )
127+ }
0 commit comments