@@ -5,9 +5,12 @@ import {
5
5
isProblemApp ,
6
6
setPlayground ,
7
7
} from '@epic-web/workshop-utils/apps.server'
8
+ import { execa } from 'execa'
8
9
import fsExtra from 'fs-extra'
10
+ import { globby } from 'globby'
9
11
10
12
await warm ( )
13
+ await runAllSeeds ( )
11
14
12
15
const allApps = await getApps ( )
13
16
const problemApps = allApps . filter ( isProblemApp )
@@ -32,3 +35,93 @@ if (!process.env.SKIP_PLAYGROUND) {
32
35
)
33
36
}
34
37
}
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