@@ -53,6 +53,41 @@ export class AssetManagementAdapter implements IAssetManagementAdapter {
5353 return '?' + parts . join ( '&' ) ;
5454 }
5555
56+ /**
57+ * Format response body or payload for error logging. Safely stringifies and truncates.
58+ */
59+ private formatResponseBodyForError ( data : unknown , maxLen : number = 500 ) : string {
60+ if ( data === null || data === undefined ) return '' ;
61+ try {
62+ const str = typeof data === 'string' ? data : JSON . stringify ( data ) ;
63+ return str . length > maxLen ? str . substring ( 0 , maxLen ) + '...' : str ;
64+ } catch {
65+ return '' ;
66+ }
67+ }
68+
69+ /**
70+ * Normalize AM API failures into a consistent error message with optional cause and body snippet.
71+ */
72+ private normalizeAmGetFailure ( details : {
73+ path : string ;
74+ fullPath : string ;
75+ status ?: number ;
76+ cause ?: unknown ;
77+ bodySnippet ?: string ;
78+ } ) : Error {
79+ const { path, status, cause, bodySnippet } = details ;
80+ let message = `AM API GET failed: path ${ path } ` ;
81+ if ( status ) message += ` (status ${ status } )` ;
82+ if ( cause && cause instanceof Error ) {
83+ message += ` - ${ cause . message } ` ;
84+ } else if ( cause ) {
85+ message += ` - ${ String ( cause ) } ` ;
86+ }
87+ if ( bodySnippet ) message += `\nResponse: ${ bodySnippet } ` ;
88+ return new Error ( message ) ;
89+ }
90+
5691 /**
5792 * GET a space-level endpoint (e.g. /api/spaces/{uid}). Builds path + query string and performs the request.
5893 */
@@ -73,11 +108,29 @@ export class AssetManagementAdapter implements IAssetManagementAdapter {
73108 const queryString = this . buildQueryString ( safeParams ) ;
74109 const fullPath = path + queryString ;
75110 log . debug ( `GET ${ fullPath } ` , this . config . context ) ;
76- const response = await this . apiClient . get < T > ( fullPath ) ;
77- if ( response . status < 200 || response . status >= 300 ) {
78- throw new Error ( `Asset Management API error: status ${ response . status } , path ${ path } ` ) ;
111+
112+ try {
113+ const response = await this . apiClient . get < T > ( fullPath ) ;
114+ if ( response . status < 200 || response . status >= 300 ) {
115+ const bodySnippet = this . formatResponseBodyForError ( response . data ) ;
116+ throw this . normalizeAmGetFailure ( {
117+ path,
118+ fullPath,
119+ status : response . status ,
120+ bodySnippet : bodySnippet || undefined ,
121+ } ) ;
122+ }
123+ return response . data as T ;
124+ } catch ( error ) {
125+ if ( error instanceof Error && error . message . includes ( 'AM API GET failed' ) ) {
126+ throw error ;
127+ }
128+ throw this . normalizeAmGetFailure ( {
129+ path,
130+ fullPath,
131+ cause : error ,
132+ } ) ;
79133 }
80- return response . data as T ;
81134 }
82135
83136 async init ( ) : Promise < void > {
@@ -196,32 +249,60 @@ export class AssetManagementAdapter implements IAssetManagementAdapter {
196249 const baseUrl = this . config . baseURL ?. replace ( / \/ $ / , '' ) ?? '' ;
197250 const headers = await this . getPostHeaders ( { 'Content-Type' : 'application/json' , ...extraHeaders } ) ;
198251 log . debug ( `POST ${ path } ` , this . config . context ) ;
199- const response = await fetch ( `${ baseUrl } ${ path } ` , {
200- method : 'POST' ,
201- headers,
202- body : JSON . stringify ( body ) ,
203- } ) ;
204- if ( ! response . ok ) {
205- const text = await response . text ( ) . catch ( ( ) => '' ) ;
206- throw new Error ( `AM API POST error: status ${ response . status } , path ${ path } , body: ${ text } ` ) ;
252+
253+ try {
254+ const response = await fetch ( `${ baseUrl } ${ path } ` , {
255+ method : 'POST' ,
256+ headers,
257+ body : JSON . stringify ( body ) ,
258+ } ) ;
259+ if ( ! response . ok ) {
260+ const text = await response . text ( ) . catch ( ( ) => '' ) ;
261+ const bodySnippet = this . formatResponseBodyForError ( text ) ;
262+ throw new Error (
263+ `AM API POST failed: status ${ response . status } path ${ path } ${
264+ bodySnippet ? `\nResponse: ${ bodySnippet } ` : ''
265+ } `,
266+ ) ;
267+ }
268+ return response . json ( ) as Promise < T > ;
269+ } catch ( error ) {
270+ if ( error instanceof Error && error . message . includes ( 'AM API POST failed' ) ) {
271+ throw error ;
272+ }
273+ throw new Error ( `AM API POST failed: path ${ path } - ${ error instanceof Error ? error . message : String ( error ) } ` ) ;
207274 }
208- return response . json ( ) as Promise < T > ;
209275 }
210276
211277 private async postMultipart < T > ( path : string , form : FormData , extraHeaders : Record < string , string > = { } ) : Promise < T > {
212278 const baseUrl = this . config . baseURL ?. replace ( / \/ $ / , '' ) ?? '' ;
213279 const headers = await this . getPostHeaders ( extraHeaders ) ;
214280 log . debug ( `POST (multipart) ${ path } ` , this . config . context ) ;
215- const response = await fetch ( `${ baseUrl } ${ path } ` , {
216- method : 'POST' ,
217- headers,
218- body : form ,
219- } ) ;
220- if ( ! response . ok ) {
221- const text = await response . text ( ) . catch ( ( ) => '' ) ;
222- throw new Error ( `AM API multipart POST error: status ${ response . status } , path ${ path } , body: ${ text } ` ) ;
281+
282+ try {
283+ const response = await fetch ( `${ baseUrl } ${ path } ` , {
284+ method : 'POST' ,
285+ headers,
286+ body : form ,
287+ } ) ;
288+ if ( ! response . ok ) {
289+ const text = await response . text ( ) . catch ( ( ) => '' ) ;
290+ const bodySnippet = this . formatResponseBodyForError ( text ) ;
291+ throw new Error (
292+ `AM API multipart POST failed: status ${ response . status } path ${ path } ${
293+ bodySnippet ? `\nResponse: ${ bodySnippet } ` : ''
294+ } `,
295+ ) ;
296+ }
297+ return response . json ( ) as Promise < T > ;
298+ } catch ( error ) {
299+ if ( error instanceof Error && error . message . includes ( 'AM API multipart POST failed' ) ) {
300+ throw error ;
301+ }
302+ throw new Error (
303+ `AM API multipart POST failed: path ${ path } - ${ error instanceof Error ? error . message : String ( error ) } ` ,
304+ ) ;
223305 }
224- return response . json ( ) as Promise < T > ;
225306 }
226307
227308 // ---------------------------------------------------------------------------
0 commit comments