1+ #!/usr/bin/env -S pnpm exec tsx
2+
3+ /**
4+ * Validation Runner - Runs all validation scripts
5+ * Orchestrates multiple validation checks across the codebase
6+ */
7+
8+ import { spawn } from 'child_process' ;
9+ import path from 'path' ;
10+
11+ interface ValidationResult {
12+ name : string ;
13+ script : string ;
14+ passed : boolean ;
15+ output : string ;
16+ error ?: string ;
17+ }
18+
19+ const VALIDATION_SCRIPTS = [
20+ {
21+ name : 'Import Patterns' ,
22+ script : 'validate-imports.ts' ,
23+ description : 'Validates ESM import patterns and cross-package imports' ,
24+ } ,
25+ {
26+ name : 'File Naming Conventions' ,
27+ script : 'validate-file-naming.ts' ,
28+ description : 'Validates kebab-case naming conventions in web directory' ,
29+ } ,
30+ {
31+ name : 'API Standardization' ,
32+ script : 'validate-api-standardization-ast.ts' ,
33+ description : 'Validates API response format standardization' ,
34+ } ,
35+ {
36+ name : 'Response Envelopes' ,
37+ script : 'validate-response-envelopes-ast.ts' ,
38+ description : 'Validates response envelope patterns' ,
39+ } ,
40+ {
41+ name : 'Architecture Patterns' ,
42+ script : 'validate-architecture-patterns-ast.ts' ,
43+ description : 'Validates architectural consistency patterns' ,
44+ } ,
45+ ] ;
46+
47+ /**
48+ * Run a single validation script
49+ */
50+ async function runValidation ( scriptPath : string ) : Promise < { passed : boolean ; output : string ; error ?: string } > {
51+ return new Promise ( ( resolve ) => {
52+ const child = spawn ( 'pnpm' , [ 'exec' , 'tsx' , scriptPath ] , {
53+ stdio : 'pipe' ,
54+ cwd : process . cwd ( ) ,
55+ } ) ;
56+
57+ let output = '' ;
58+ let error = '' ;
59+
60+ child . stdout ?. on ( 'data' , ( data ) => {
61+ output += data . toString ( ) ;
62+ } ) ;
63+
64+ child . stderr ?. on ( 'data' , ( data ) => {
65+ error += data . toString ( ) ;
66+ } ) ;
67+
68+ child . on ( 'close' , ( code ) => {
69+ resolve ( {
70+ passed : code === 0 ,
71+ output : output . trim ( ) ,
72+ error : error . trim ( ) || undefined ,
73+ } ) ;
74+ } ) ;
75+
76+ child . on ( 'error' , ( err ) => {
77+ resolve ( {
78+ passed : false ,
79+ output : '' ,
80+ error : err . message ,
81+ } ) ;
82+ } ) ;
83+ } ) ;
84+ }
85+
86+ /**
87+ * Main validation runner
88+ */
89+ async function runAllValidations ( ) : Promise < void > {
90+ const args = process . argv . slice ( 2 ) ;
91+ const showList = args . includes ( '--list' ) ;
92+ const quickMode = args . includes ( '--quick' ) ;
93+
94+ if ( showList ) {
95+ console . log ( '📋 Available validation scripts:\n' ) ;
96+ VALIDATION_SCRIPTS . forEach ( ( script , index ) => {
97+ console . log ( `${ index + 1 } . ${ script . name } ` ) ;
98+ console . log ( ` ${ script . description } ` ) ;
99+ console . log ( ` Script: ${ script . script } \n` ) ;
100+ } ) ;
101+ return ;
102+ }
103+
104+ console . log ( '🔍 Running all validation scripts...\n' ) ;
105+
106+ const results : ValidationResult [ ] = [ ] ;
107+ const scriptsToRun = quickMode
108+ ? VALIDATION_SCRIPTS . filter ( s => [ 'validate-imports.ts' , 'validate-file-naming.ts' ] . includes ( s . script ) )
109+ : VALIDATION_SCRIPTS ;
110+
111+ // Run validations sequentially to avoid overwhelming output
112+ for ( const script of scriptsToRun ) {
113+ const scriptPath = path . join ( 'scripts/validation' , script . script ) ;
114+ console . log ( `🔍 Running: ${ script . name } ...` ) ;
115+
116+ const result = await runValidation ( scriptPath ) ;
117+ results . push ( {
118+ name : script . name ,
119+ script : script . script ,
120+ ...result ,
121+ } ) ;
122+
123+ if ( result . passed ) {
124+ console . log ( `✅ ${ script . name } - PASSED` ) ;
125+ } else {
126+ console . log ( `❌ ${ script . name } - FAILED` ) ;
127+ if ( ! quickMode ) {
128+ console . log ( result . output ) ;
129+ if ( result . error ) {
130+ console . log ( `Error: ${ result . error } ` ) ;
131+ }
132+ }
133+ }
134+ console . log ( '' ) ;
135+ }
136+
137+ // Summary
138+ const passed = results . filter ( r => r . passed ) . length ;
139+ const total = results . length ;
140+ const failed = results . filter ( r => ! r . passed ) ;
141+
142+ console . log ( '📊 Validation Summary:' ) ;
143+ console . log ( ` Passed: ${ passed } /${ total } ` ) ;
144+
145+ if ( failed . length > 0 ) {
146+ console . log ( ` Failed: ${ failed . length } ` ) ;
147+ console . log ( '\n❌ Failed validations:' ) ;
148+ failed . forEach ( result => {
149+ console . log ( ` - ${ result . name } ` ) ;
150+ } ) ;
151+
152+ if ( quickMode && failed . length > 0 ) {
153+ console . log ( '\n💡 Run without --quick flag to see detailed error messages' ) ;
154+ }
155+ }
156+
157+ if ( passed === total ) {
158+ console . log ( '\n✅ All validations passed!' ) ;
159+ process . exit ( 0 ) ;
160+ } else {
161+ console . log ( '\n❌ Some validations failed. Please review and fix the issues above.' ) ;
162+ process . exit ( 1 ) ;
163+ }
164+ }
165+
166+ // Run validation if called directly
167+ if ( import . meta. url === `file://${ process . argv [ 1 ] } ` ) {
168+ runAllValidations ( ) . catch ( ( error ) => {
169+ console . error ( '💥 Validation runner failed:' , error ) ;
170+ process . exit ( 1 ) ;
171+ } ) ;
172+ }
173+
174+ export { runAllValidations } ;
0 commit comments