1212 * or submit itself to any jurisdiction.
1313 */
1414
15- import { FailedDependencyError , LogManager } from '@aliceo2/web-ui' ;
15+ import { FailedDependencyError , LogManager , NotFoundError } from '@aliceo2/web-ui' ;
1616import { httpHeadJson , httpGetJson } from '../../utils/httpRequests.js' ;
1717import {
1818 CCDB_MONITOR , CCDB_VERSION_KEY , CCDB_RESPONSE_BODY_KEYS , CCDB_FILTER_FIELDS , CCDB_RESPONSE_HEADER_KEYS ,
@@ -176,7 +176,8 @@ export class CcdbService {
176176 * ```
177177 * @param {CcdbObjectIdentification } partialIdentification - fields such as path, validFrom, etc.
178178 * @returns {Promise.<CcdbObjectIdentification> } - returns object full identification
179- * @throws {Error }
179+ * @throws {Error } throws if the object cannot be fetched
180+ * @throws {NotFoundError } throws if the object cannot be found
180181 */
181182 async getObjectIdentification ( partialIdentification ) {
182183 const headers = {
@@ -185,18 +186,28 @@ export class CcdbService {
185186 } ;
186187 const url = `/latest${ this . _buildCcdbUrlPath ( partialIdentification ) } ` ;
187188
188- const result = await httpGetJson ( this . _hostname , this . _port , url , { headers } ) ;
189- if ( result ?. objects ?. length > 0 ) {
190- const [ qcObject ] = result . objects ;
191- return {
192- [ CCDB_RESPONSE_BODY_KEYS . PATH ] : qcObject [ CCDB_RESPONSE_BODY_KEYS . PATH ] ,
193- [ CCDB_RESPONSE_BODY_KEYS . VALID_FROM ] : qcObject [ CCDB_RESPONSE_BODY_KEYS . VALID_FROM ] ,
194- [ CCDB_RESPONSE_BODY_KEYS . VALID_UNTIL ] : qcObject [ CCDB_RESPONSE_BODY_KEYS . VALID_UNTIL ] ,
195- [ CCDB_RESPONSE_BODY_KEYS . ID ] : qcObject [ CCDB_RESPONSE_BODY_KEYS . ID ] ,
196- } ;
197- } else {
198- throw new Error ( `Object: ${ url } could not be found` ) ;
189+ let result = null ;
190+ try {
191+ result = await httpGetJson ( this . _hostname , this . _port , url , { headers } ) ;
192+ } catch {
193+ throw new Error ( `Failed to fetch object at url '${ url } ' and path '${ partialIdentification . path } '.` ) ;
199194 }
195+
196+ if ( ! result ?. objects ?. length ) {
197+ const errorMessage = this . _buildFilterErrorMessage (
198+ `Object at url '${ url } ' and path '${ partialIdentification . path } ' could not be found.` ,
199+ partialIdentification . filters ,
200+ ) ;
201+ throw new NotFoundError ( errorMessage ) ;
202+ }
203+
204+ const [ qcObject ] = result . objects ;
205+ return {
206+ [ CCDB_RESPONSE_BODY_KEYS . PATH ] : qcObject [ CCDB_RESPONSE_BODY_KEYS . PATH ] ,
207+ [ CCDB_RESPONSE_BODY_KEYS . VALID_FROM ] : qcObject [ CCDB_RESPONSE_BODY_KEYS . VALID_FROM ] ,
208+ [ CCDB_RESPONSE_BODY_KEYS . VALID_UNTIL ] : qcObject [ CCDB_RESPONSE_BODY_KEYS . VALID_UNTIL ] ,
209+ [ CCDB_RESPONSE_BODY_KEYS . ID ] : qcObject [ CCDB_RESPONSE_BODY_KEYS . ID ] ,
210+ } ;
200211 }
201212
202213 /**
@@ -215,7 +226,7 @@ export class CcdbService {
215226 * @throws {Error }
216227 */
217228 async getObjectDetails ( identification ) {
218- const { path = '' , validFrom = undefined } = identification ?? { } ;
229+ const { path = '' , filters , validFrom = undefined } = identification ?? { } ;
219230 if ( ! path || ! validFrom ) {
220231 throw new Error ( 'Missing mandatory parameters: path & validFrom' ) ;
221232 }
@@ -226,15 +237,23 @@ export class CcdbService {
226237 . split ( ', ' )
227238 . filter ( ( location ) => ! location . startsWith ( 'alien' ) && ! location . startsWith ( 'file' ) ) ;
228239 if ( ! location ) {
229- throw new Error ( `No location provided by CCDB for object with path: ${ path } ` ) ;
240+ const errorMessage = this . _buildFilterErrorMessage (
241+ `No location provided by CCDB for object with path: ${ path } ` ,
242+ filters ,
243+ ) ;
244+ throw new Error ( errorMessage ) ;
230245 }
231246 return {
232247 ...headers ,
233248 location,
234249 path,
235250 } ;
236251 } else {
237- throw new Error ( `Unable to retrieve object: ${ path } due to status: ${ status } ` ) ;
252+ const errorMessage = this . _buildFilterErrorMessage (
253+ `Unable to retrieve object: ${ path } due to status: ${ status } ` ,
254+ filters ,
255+ ) ;
256+ throw new Error ( errorMessage ) ;
238257 }
239258 }
240259
@@ -243,7 +262,8 @@ export class CcdbService {
243262 * The minimum required parameter to provide is the `path`
244263 * @param {CcdbObjectIdentification } identification - attributes by which the object should be queried
245264 * @returns {Promise.<JSON> } - object details for a given timestamp
246- * @throws {Error }
265+ * @throws {Error } Thrown when an error occurs whilst fetching the object
266+ * @throws {NotFoundError } Thrown when the object cannot be found
247267 */
248268 async getObjectLatestVersionInfo ( identification ) {
249269 const { path } = identification ?? { } ;
@@ -257,7 +277,7 @@ export class CcdbService {
257277 const url = `/latest${ this . _buildCcdbUrlPath ( identification ) } ` ;
258278 const { objects } = await httpGetJson ( this . _hostname , this . _port , url , { headers : timestampHeaders } ) ;
259279 if ( objects ?. length <= 0 ) {
260- throw new Error ( `No object found for: ${ path } ` ) ;
280+ throw new NotFoundError ( `No object found for: ${ path } ` ) ;
261281 }
262282 return objects [ 0 ] ;
263283 } catch {
@@ -342,4 +362,32 @@ export class CcdbService {
342362 }
343363 return url ;
344364 }
365+
366+ /**
367+ * Builds a detailed error message for CCDB objects that may have been filtered out.
368+ * This method appends a filter-specific hint to a base error message when
369+ * the `filters` object contains one or more keys. It ensures proper punctuation
370+ * and provides a clear explanation for why the object might not have been found.
371+ * @param {string } baseMessage - The initial error message describing the failure.
372+ * @param {object } [filters] - Optional object representing filters applied when searching for the object.
373+ * @returns {string } - The final, human-readable error message including filter hints if applicable.
374+ */
375+ _buildFilterErrorMessage ( baseMessage , filters ) {
376+ // Only append filter-specific hint if filters object exists and has keys
377+ if ( filters && Object . keys ( filters ) . length > 0 ) {
378+ // Ensure the base message ends with proper punctuation.
379+ // If it does NOT end with any Unicode punctuation, append a period.
380+ if ( ! / \p{ P} $ / u. test ( baseMessage ) ) {
381+ baseMessage += '.' ;
382+ }
383+ if ( ! baseMessage . endsWith ( ' ' ) ) {
384+ baseMessage += ' ' ;
385+ }
386+
387+ // Append a clear, descriptive filter hint.
388+ baseMessage += 'It was likely excluded by the applied filters.' ;
389+ }
390+
391+ return baseMessage ;
392+ }
345393}
0 commit comments