11import { promises as fs , existsSync } from 'fs' ;
22import path from 'path' ;
33import { fileURLToPath } from 'url' ;
4+ import { randomUUID } from 'crypto' ;
45import chalk from 'chalk' ;
56import { ProjectConfig , SkuilderConfig } from '../types.js' ;
7+ import { CourseConfig } from '@vue-skuilder/common' ;
68
79const __filename = fileURLToPath ( import . meta. url ) ;
810const __dirname = path . dirname ( __filename ) ;
@@ -182,7 +184,8 @@ export default defineConfig({
182184 */
183185export async function generateSkuilderConfig (
184186 configPath : string ,
185- config : ProjectConfig
187+ config : ProjectConfig ,
188+ outputPath ?: string
186189) : Promise < void > {
187190 const skuilderConfig : SkuilderConfig = {
188191 title : config . title ,
@@ -194,13 +197,14 @@ export async function generateSkuilderConfig(
194197 skuilderConfig . course = config . course ;
195198 }
196199
197- // For static data layer with imported courses, use the first course as primary
198- if (
199- config . dataLayerType === 'static' &&
200- config . importCourseIds &&
201- config . importCourseIds . length > 0
202- ) {
203- skuilderConfig . course = config . importCourseIds [ 0 ] ;
200+ // For static data layer, use imported course ID or generate new one
201+ if ( config . dataLayerType === 'static' ) {
202+ if ( config . importCourseIds && config . importCourseIds . length > 0 ) {
203+ skuilderConfig . course = config . importCourseIds [ 0 ] ;
204+ } else {
205+ // Generate UUID for new static courses without imports
206+ skuilderConfig . course = randomUUID ( ) ;
207+ }
204208 }
205209
206210 if ( config . couchdbUrl ) {
@@ -212,6 +216,11 @@ export async function generateSkuilderConfig(
212216 }
213217
214218 await fs . writeFile ( configPath , JSON . stringify ( skuilderConfig , null , 2 ) ) ;
219+
220+ // For static data layer without imports, create empty course structure
221+ if ( config . dataLayerType === 'static' && ( ! config . importCourseIds || config . importCourseIds . length === 0 ) && outputPath ) {
222+ await createEmptyCourseStructure ( outputPath , skuilderConfig . course ! , config . title ) ;
223+ }
215224}
216225
217226/**
@@ -250,6 +259,72 @@ export async function transformTsConfig(tsconfigPath: string): Promise<void> {
250259 await fs . writeFile ( tsconfigPath , JSON . stringify ( tsconfig , null , 2 ) ) ;
251260}
252261
262+ /**
263+ * Create empty course structure for new static courses
264+ */
265+ async function createEmptyCourseStructure (
266+ projectPath : string ,
267+ courseId : string ,
268+ title : string
269+ ) : Promise < void > {
270+ const staticCoursesPath = path . join ( projectPath , 'public' , 'static-courses' ) ;
271+ const coursePath = path . join ( staticCoursesPath , courseId ) ;
272+
273+ // Create directory structure
274+ await fs . mkdir ( coursePath , { recursive : true } ) ;
275+ await fs . mkdir ( path . join ( coursePath , 'chunks' ) , { recursive : true } ) ;
276+ await fs . mkdir ( path . join ( coursePath , 'indices' ) , { recursive : true } ) ;
277+
278+ // Create minimal CourseConfig
279+ const courseConfig : CourseConfig = {
280+ courseID : courseId ,
281+ name : title ,
282+ description : '' ,
283+ public : false ,
284+ deleted : false ,
285+ creator : 'system' ,
286+ admins : [ ] ,
287+ moderators : [ ] ,
288+ dataShapes : [ ] ,
289+ questionTypes : [ ]
290+ } ;
291+
292+ // Create manifest.json with proper structure
293+ const manifest = {
294+ version : '1.0.0' ,
295+ courseId,
296+ courseName : title ,
297+ courseConfig,
298+ lastUpdated : new Date ( ) . toISOString ( ) ,
299+ documentCount : 0 ,
300+ chunks : [ ] ,
301+ indices : [ ] ,
302+ designDocs : [ ]
303+ } ;
304+
305+ await fs . writeFile (
306+ path . join ( coursePath , 'manifest.json' ) ,
307+ JSON . stringify ( manifest , null , 2 )
308+ ) ;
309+
310+ // Create empty tags index
311+ await fs . writeFile (
312+ path . join ( coursePath , 'indices' , 'tags.json' ) ,
313+ JSON . stringify ( { tags : [ ] } , null , 2 )
314+ ) ;
315+
316+ // Create CourseConfig chunk
317+ await fs . writeFile (
318+ path . join ( coursePath , 'chunks' , 'CourseConfig.json' ) ,
319+ JSON . stringify ( [ {
320+ _id : 'CourseConfig' ,
321+ ...courseConfig
322+ } ] , null , 2 )
323+ ) ;
324+
325+ console . log ( chalk . green ( `✅ Created empty course structure for ${ courseId } ` ) ) ;
326+ }
327+
253328/**
254329 * Generate .gitignore file for the project
255330 */
@@ -540,7 +615,7 @@ export async function processTemplate(
540615
541616 console . log ( chalk . blue ( '🔧 Generating configuration...' ) ) ;
542617 const configPath = path . join ( projectPath , 'skuilder.config.json' ) ;
543- await generateSkuilderConfig ( configPath , config ) ;
618+ await generateSkuilderConfig ( configPath , config , projectPath ) ;
544619
545620 console . log ( chalk . blue ( '📝 Creating README...' ) ) ;
546621 const readmePath = path . join ( projectPath , 'README.md' ) ;
0 commit comments