@@ -71,76 +71,81 @@ export async function handleBuildSettingsV2(payload: BuildRequestV2) {
7171 throw new ValidationError ( 'Request body is required' ) ;
7272 }
7373
74- console . log ( '[COMAPEO-API] Received request for /v2 build.' ) ;
74+ try {
75+ console . log ( '[COMAPEO-API] Received request for /v2 build.' ) ;
7576
76- const result = await buildComapeoCatV2 ( payload ) ;
77- const tmpDir = path . dirname ( result . outputPath ) ;
77+ const result = await buildComapeoCatV2 ( payload ) ;
78+ const tmpDir = path . dirname ( result . outputPath ) ;
7879
79- if ( result . warnings . length > 0 ) {
80- for ( const warning of result . warnings ) {
81- console . warn ( `[COMAPEO-API][WARN] ${ warning } ` ) ;
80+ if ( result . warnings . length > 0 ) {
81+ for ( const warning of result . warnings ) {
82+ console . warn ( `[COMAPEO-API][WARN] ${ warning } ` ) ;
83+ }
8284 }
83- }
8485
85- console . log ( `[COMAPEO-API] Generated .comapeocat file: ${ result . outputPath } . Starting validation.` ) ;
86-
87- try {
88- const reader = new Reader ( result . outputPath ) ;
89- const validationResult = await validateComapeocatWithTimeout ( reader , result . outputPath ) ;
90- if ( Array . isArray ( validationResult ) && validationResult . length > 0 ) {
91- // Validation failed
92- const errors = validationResult . map ( e => `${ e . message } at ${ e . filePath || 'unknown file' } ` ) . join ( '\n' ) ;
93- console . error ( `[COMAPEO-API] .comapeocat validation failed for ${ result . outputPath } :\n${ errors } ` ) ;
94- // Clean up temp directory before throwing error
86+ console . log ( `[COMAPEO-API] Generated .comapeocat file: ${ result . outputPath } . Starting validation.` ) ;
87+
88+ try {
89+ const reader = new Reader ( result . outputPath ) ;
90+ const validationResult = await validateComapeocatWithTimeout ( reader , result . outputPath ) ;
91+ if ( Array . isArray ( validationResult ) && validationResult . length > 0 ) {
92+ // Validation failed
93+ const errors = validationResult . map ( e => `${ e . message } at ${ e . filePath || 'unknown file' } ` ) . join ( '\n' ) ;
94+ console . error ( `[COMAPEO-API] .comapeocat validation failed for ${ result . outputPath } :\n${ errors } ` ) ;
95+ // Clean up temp directory before throwing error
96+ await fs . rm ( tmpDir , { recursive : true , force : true } ) . catch ( console . error ) ;
97+ throw new ValidationError ( `Generated .comapeocat file is invalid:\n${ errors } ` ) ;
98+ }
99+ console . log ( `[COMAPEO-API] .comapeocat validation successful for ${ result . outputPath } .` ) ;
100+ } catch ( validationError : any ) { // Explicitly type validationError as 'any' for broader compatibility
101+ // Handle errors during validation itself (e.g., file not found, reader issues)
102+ console . error ( `[COMAPEO-API] Error during .comapeocat validation for ${ result . outputPath } :` , validationError ) ;
103+ // Clean up temp directory before re-throwing error
95104 await fs . rm ( tmpDir , { recursive : true , force : true } ) . catch ( console . error ) ;
96- throw new ValidationError ( `Generated .comapeocat file is invalid:\n ${ errors } `) ;
105+ throw new ProcessingError ( `Failed to validate generated .comapeocat file: ${ validationError . message } `) ;
97106 }
98- console . log ( `[COMAPEO-API] .comapeocat validation successful for ${ result . outputPath } .` ) ;
99- } catch ( validationError : any ) { // Explicitly type validationError as 'any' for broader compatibility
100- // Handle errors during validation itself (e.g., file not found, reader issues)
101- console . error ( `[COMAPEO-API] Error during .comapeocat validation for ${ result . outputPath } :` , validationError ) ;
102- // Clean up temp directory before re-throwing error
103- await fs . rm ( tmpDir , { recursive : true , force : true } ) . catch ( console . error ) ;
104- throw new ProcessingError ( `Failed to validate generated .comapeocat file: ${ validationError . message } ` ) ;
105- }
106107
107- // Create a streaming response that cleans up after the file is sent
108- const bunFile = Bun . file ( result . outputPath ) ;
109- const originalStream = bunFile . stream ( ) ;
108+ // Create a streaming response that cleans up after the file is sent
109+ const bunFile = Bun . file ( result . outputPath ) ;
110+ const originalStream = bunFile . stream ( ) ;
110111
111- console . log ( `[COMAPEO-API] Sending .comapeocat file: ${ result . fileName } ` ) ;
112+ console . log ( `[COMAPEO-API] Sending .comapeocat file: ${ result . fileName } ` ) ;
112113
113- // Wrap the stream to ensure cleanup happens after streaming completes
114- const reader = originalStream . getReader ( ) ;
115- const cleanupStream = new ReadableStream ( {
116- async pull ( controller ) {
117- const { done, value } = await reader . read ( ) ;
118- if ( done ) {
119- controller . close ( ) ;
120- // Clean up temp directory after streaming is complete
114+ // Wrap the stream to ensure cleanup happens after streaming completes
115+ const reader = originalStream . getReader ( ) ;
116+ const cleanupStream = new ReadableStream ( {
117+ async pull ( controller ) {
118+ const { done, value } = await reader . read ( ) ;
119+ if ( done ) {
120+ controller . close ( ) ;
121+ // Clean up temp directory after streaming is complete
122+ fs . rm ( tmpDir , { recursive : true , force : true } ) . catch ( console . error ) ;
123+ } else {
124+ controller . enqueue ( value ) ;
125+ }
126+ } ,
127+ cancel ( ) {
128+ // Clean up if the stream is cancelled/aborted
121129 fs . rm ( tmpDir , { recursive : true , force : true } ) . catch ( console . error ) ;
122- } else {
123- controller . enqueue ( value ) ;
124130 }
125- } ,
126- cancel ( ) {
127- // Clean up if the stream is cancelled/aborted
128- fs . rm ( tmpDir , { recursive : true , force : true } ) . catch ( console . error ) ;
129- }
130- } ) ;
131+ } ) ;
131132
132- const headers : Record < string , string > = {
133- 'Content-Type' : 'application/octet-stream' ,
134- 'Content-Disposition' : `attachment; filename="${ path . basename ( result . outputPath ) } "` ,
135- 'Content-Length' : bunFile . size . toString ( ) ,
136- } ;
133+ const headers : Record < string , string > = {
134+ 'Content-Type' : 'application/octet-stream' ,
135+ 'Content-Disposition' : `attachment; filename="${ path . basename ( result . outputPath ) } "` ,
136+ 'Content-Length' : bunFile . size . toString ( ) ,
137+ } ;
137138
138- const warningsHeader = formatWarningsHeader ( result . warnings ) ;
139- if ( warningsHeader ) {
140- headers [ 'X-Comapeo-Warnings' ] = warningsHeader ;
141- }
139+ const warningsHeader = formatWarningsHeader ( result . warnings ) ;
140+ if ( warningsHeader ) {
141+ headers [ 'X-Comapeo-Warnings' ] = warningsHeader ;
142+ }
142143
143- return new Response ( cleanupStream , { headers } ) ;
144+ return new Response ( cleanupStream , { headers } ) ;
145+ } catch ( error ) {
146+ logV2PayloadForFailure ( payload , error ) ;
147+ throw error ;
148+ }
144149}
145150
146151async function validateComapeocatWithTimeout ( reader : Reader , outputPath : string ) {
@@ -177,3 +182,12 @@ function formatWarningsHeader(warnings: string[]) {
177182 // Limit header size to a reasonable length to avoid header bloat
178183 return joined . length > 1024 ? `${ joined . slice ( 0 , 1021 ) } ...` : joined ;
179184}
185+
186+ function logV2PayloadForFailure ( payload : BuildRequestV2 , error : unknown ) {
187+ try {
188+ const serializedPayload = JSON . stringify ( payload , null , 2 ) ;
189+ console . error ( '[COMAPEO-API][ERROR] /v2 build failed. Payload dump follows:' , serializedPayload , error ) ;
190+ } catch ( serializationError ) {
191+ console . error ( '[COMAPEO-API][ERROR] /v2 build failed and payload serialization threw an error:' , serializationError , error ) ;
192+ }
193+ }
0 commit comments