@@ -346,6 +346,120 @@ describe('get', () => {
346346 } )
347347} )
348348
349+ describe ( 'getMetadata' , ( ) => {
350+ describe ( 'With API credentials' , ( ) => {
351+ test ( 'Reads from the blob store and returns the etag and the metadata object' , async ( ) => {
352+ const mockMetadata = {
353+ name : 'Netlify' ,
354+ cool : true ,
355+ functions : [ 'edge' , 'serverless' ] ,
356+ }
357+ const headers = {
358+ etag : '123456789' ,
359+ 'x-amz-meta-user' : `b64;${ base64Encode ( mockMetadata ) } ` ,
360+ }
361+ const mockStore = new MockFetch ( ) . head ( {
362+ headers : { authorization : `Bearer ${ apiToken } ` } ,
363+ response : new Response ( null , { headers } ) ,
364+ url : `https://api.netlify.com/api/v1/sites/${ siteID } /blobs/${ key } ?context=production` ,
365+ } )
366+
367+ globalThis . fetch = mockStore . fetch
368+
369+ const blobs = getStore ( {
370+ name : 'production' ,
371+ token : apiToken ,
372+ siteID,
373+ } )
374+
375+ const entry = await blobs . getMetadata ( key )
376+ expect ( entry ?. etag ) . toBe ( headers . etag )
377+ expect ( entry ?. metadata ) . toEqual ( mockMetadata )
378+
379+ expect ( mockStore . fulfilled ) . toBeTruthy ( )
380+ } )
381+
382+ test ( 'Returns `null` when the API returns a 404' , async ( ) => {
383+ const mockStore = new MockFetch ( ) . head ( {
384+ headers : { authorization : `Bearer ${ apiToken } ` } ,
385+ response : new Response ( null , { status : 404 } ) ,
386+ url : `https://api.netlify.com/api/v1/sites/${ siteID } /blobs/${ key } ?context=production` ,
387+ } )
388+
389+ globalThis . fetch = mockStore . fetch
390+
391+ const blobs = getStore ( {
392+ name : 'production' ,
393+ token : apiToken ,
394+ siteID,
395+ } )
396+
397+ expect ( await blobs . getMetadata ( key ) ) . toBeNull ( )
398+ expect ( mockStore . fulfilled ) . toBeTruthy ( )
399+ } )
400+
401+ test ( 'Throws when the metadata object cannot be parsed' , async ( ) => {
402+ const headers = {
403+ etag : '123456789' ,
404+ 'x-amz-meta-user' : `b64;${ base64Encode ( `{"name": "Netlify", "cool` ) } ` ,
405+ }
406+ const mockStore = new MockFetch ( ) . head ( {
407+ headers : { authorization : `Bearer ${ apiToken } ` } ,
408+ response : new Response ( null , { headers } ) ,
409+ url : `https://api.netlify.com/api/v1/sites/${ siteID } /blobs/${ key } ?context=production` ,
410+ } )
411+
412+ globalThis . fetch = mockStore . fetch
413+
414+ const blobs = getStore ( {
415+ name : 'production' ,
416+ token : apiToken ,
417+ siteID,
418+ } )
419+
420+ await expect ( async ( ) => await blobs . getMetadata ( key ) ) . rejects . toThrowError (
421+ 'An internal error occurred while trying to retrieve the metadata for an entry. Please try updating to the latest version of the Netlify Blobs client.' ,
422+ )
423+
424+ expect ( mockStore . fulfilled ) . toBeTruthy ( )
425+ } )
426+ } )
427+
428+ describe ( 'With edge credentials' , ( ) => {
429+ test ( 'Reads from the blob store and returns the etag and the metadata object' , async ( ) => {
430+ const mockMetadata = {
431+ name : 'Netlify' ,
432+ cool : true ,
433+ functions : [ 'edge' , 'serverless' ] ,
434+ }
435+ const headers = {
436+ etag : '123456789' ,
437+ 'x-amz-meta-user' : `b64;${ base64Encode ( mockMetadata ) } ` ,
438+ }
439+ const mockStore = new MockFetch ( ) . head ( {
440+ headers : { authorization : `Bearer ${ edgeToken } ` } ,
441+ response : new Response ( null , { headers } ) ,
442+ url : `${ edgeURL } /${ siteID } /production/${ key } ` ,
443+ } )
444+
445+ globalThis . fetch = mockStore . fetch
446+
447+ const blobs = getStore ( {
448+ edgeURL,
449+ name : 'production' ,
450+ token : edgeToken ,
451+ siteID,
452+ } )
453+
454+ const entry = await blobs . getMetadata ( key )
455+ expect ( entry ?. etag ) . toBe ( headers . etag )
456+ expect ( entry ?. metadata ) . toEqual ( mockMetadata )
457+
458+ expect ( mockStore . fulfilled ) . toBeTruthy ( )
459+ } )
460+ } )
461+ } )
462+
349463describe ( 'getWithMetadata' , ( ) => {
350464 describe ( 'With API credentials' , ( ) => {
351465 test ( 'Reads from the blob store and returns the etag and the metadata object' , async ( ) => {
@@ -387,14 +501,14 @@ describe('getWithMetadata', () => {
387501 } )
388502
389503 const entry1 = await blobs . getWithMetadata ( key )
390- expect ( entry1 . data ) . toBe ( value )
391- expect ( entry1 . etag ) . toBe ( responseHeaders . etag )
392- expect ( entry1 . metadata ) . toEqual ( mockMetadata )
504+ expect ( entry1 ? .data ) . toBe ( value )
505+ expect ( entry1 ? .etag ) . toBe ( responseHeaders . etag )
506+ expect ( entry1 ? .metadata ) . toEqual ( mockMetadata )
393507
394508 const entry2 = await blobs . getWithMetadata ( key , { type : 'stream' } )
395- expect ( await streamToString ( entry2 . data as unknown as NodeJS . ReadableStream ) ) . toBe ( value )
396- expect ( entry2 . etag ) . toBe ( responseHeaders . etag )
397- expect ( entry2 . metadata ) . toEqual ( mockMetadata )
509+ expect ( await streamToString ( entry2 ? .data as unknown as NodeJS . ReadableStream ) ) . toBe ( value )
510+ expect ( entry2 ? .etag ) . toBe ( responseHeaders . etag )
511+ expect ( entry2 ? .metadata ) . toEqual ( mockMetadata )
398512
399513 expect ( mockStore . fulfilled ) . toBeTruthy ( )
400514 } )
@@ -495,16 +609,16 @@ describe('getWithMetadata', () => {
495609 } )
496610
497611 const staleEntry = await blobs . getWithMetadata ( key , { etag : etags [ 0 ] } )
498- expect ( staleEntry . data ) . toBe ( value )
499- expect ( staleEntry . etag ) . toBe ( etags [ 0 ] )
500- expect ( staleEntry . fresh ) . toBe ( false )
501- expect ( staleEntry . metadata ) . toEqual ( mockMetadata )
612+ expect ( staleEntry ? .data ) . toBe ( value )
613+ expect ( staleEntry ? .etag ) . toBe ( etags [ 0 ] )
614+ expect ( staleEntry ? .fresh ) . toBe ( false )
615+ expect ( staleEntry ? .metadata ) . toEqual ( mockMetadata )
502616
503617 const freshEntry = await blobs . getWithMetadata ( key , { etag : etags [ 1 ] , type : 'text' } )
504- expect ( freshEntry . data ) . toBe ( null )
505- expect ( freshEntry . etag ) . toBe ( etags [ 0 ] )
506- expect ( freshEntry . fresh ) . toBe ( true )
507- expect ( freshEntry . metadata ) . toEqual ( mockMetadata )
618+ expect ( freshEntry ? .data ) . toBe ( null )
619+ expect ( freshEntry ? .etag ) . toBe ( etags [ 0 ] )
620+ expect ( freshEntry ? .fresh ) . toBe ( true )
621+ expect ( freshEntry ? .metadata ) . toEqual ( mockMetadata )
508622
509623 expect ( mockStore . fulfilled ) . toBeTruthy ( )
510624 } )
@@ -543,14 +657,14 @@ describe('getWithMetadata', () => {
543657 } )
544658
545659 const entry1 = await blobs . getWithMetadata ( key )
546- expect ( entry1 . data ) . toBe ( value )
547- expect ( entry1 . etag ) . toBe ( responseHeaders . etag )
548- expect ( entry1 . metadata ) . toEqual ( mockMetadata )
660+ expect ( entry1 ? .data ) . toBe ( value )
661+ expect ( entry1 ? .etag ) . toBe ( responseHeaders . etag )
662+ expect ( entry1 ? .metadata ) . toEqual ( mockMetadata )
549663
550664 const entry2 = await blobs . getWithMetadata ( key , { type : 'stream' } )
551- expect ( await streamToString ( entry2 . data as unknown as NodeJS . ReadableStream ) ) . toBe ( value )
552- expect ( entry2 . etag ) . toBe ( responseHeaders . etag )
553- expect ( entry2 . metadata ) . toEqual ( mockMetadata )
665+ expect ( await streamToString ( entry2 ? .data as unknown as NodeJS . ReadableStream ) ) . toBe ( value )
666+ expect ( entry2 ? .etag ) . toBe ( responseHeaders . etag )
667+ expect ( entry2 ? .metadata ) . toEqual ( mockMetadata )
554668
555669 expect ( mockStore . fulfilled ) . toBeTruthy ( )
556670 } )
0 commit comments