@@ -498,6 +498,51 @@ export function validateOwdModule(packageDir, options = {}) {
498498 'theme src/module.ts should call registerThemeTailwindPath from @owdproject/kit-primevue/kit/registerTailwindPath' ,
499499 )
500500 }
501+
502+ // Check required theme components
503+ const componentsDir = join ( dir , 'src' , 'runtime' , 'components' )
504+ if ( ! existsSync ( componentsDir ) ) {
505+ issue (
506+ 'error' ,
507+ 'missing-components-dir' ,
508+ 'theme src/runtime/components/ directory is required' ,
509+ )
510+ } else {
511+ const foundComponents = new Set ( )
512+ const scanComponents = ( current ) => {
513+ for ( const entry of readdirSync ( current ) ) {
514+ const full = join ( current , entry )
515+ let stat
516+ try {
517+ stat = statSync ( full )
518+ } catch {
519+ continue
520+ }
521+ if ( stat . isDirectory ( ) ) {
522+ scanComponents ( full )
523+ } else if ( / \. ( v u e | t s | j s ) $ / i. test ( entry ) ) {
524+ const name = entry . replace ( / \. ( v u e | t s | j s ) $ / i, '' )
525+ foundComponents . add ( name )
526+ }
527+ }
528+ }
529+ scanComponents ( componentsDir )
530+
531+ const requiredComponents = [
532+ 'DesktopWindow' ,
533+ 'DesktopWindowNav' ,
534+ 'DesktopWindowIframe' ,
535+ ]
536+ for ( const req of requiredComponents ) {
537+ if ( ! foundComponents . has ( req ) ) {
538+ issue (
539+ 'error' ,
540+ `missing-theme-component-${ req . toLowerCase ( ) } ` ,
541+ `theme must implement the "${ req } " component under src/runtime/components/` ,
542+ )
543+ }
544+ }
545+ }
501546 } else if ( kind === 'app' && ! hasKitTailwind ) {
502547 issue (
503548 'warning' ,
0 commit comments