1+ import { ZSTDDecoder } from 'zstddec' ;
2+
13import { CustomError } from './classes/customClasses' ;
24import { createMetadataJsonUrl } from './classes/utils' ;
5+ import { medatata } from './constants' ;
36import { createMetadataFileName , getDirectoryHandle , readFile , writeFile } from './fileAccessSystemUtils' ;
4- import type { JsonMetadata , MetadataUrlCreationParams } from './types' ;
7+ import type { InstanceMetadata , JsonMetadata , MetadataUrlCreationParams } from './types' ;
58
69class MetadataManager {
710 private metadataPromises : Record < string , Promise < JsonMetadata > > = { } ;
11+ private decoder ?: ZSTDDecoder ;
12+ private decoderInitPromise : Promise < boolean > ;
13+
14+ constructor ( ) {
15+ this . decoder = null ;
16+ const decoder = new ZSTDDecoder ( ) ;
817
9- constructor ( ) { }
18+ this . decoderInitPromise = decoder
19+ . init ( )
20+ . then ( ( ) => {
21+ this . decoder = decoder ;
22+ return true ;
23+ } )
24+ . catch ( ( error ) => {
25+ console . error ( 'Failed to initialize ZSTD WASM module:' , error ) ;
26+ return false ;
27+ } ) ;
28+ }
1029
11- public addDeidMetadata ( jsonMetadata : JsonMetadata , url : string ) : void {
30+ public async addDeidMetadata ( jsonMetadata : JsonMetadata , url : string ) : Promise < void > {
1231 const { cod } = jsonMetadata ;
1332 const [ studyUID , _ , seriesUID ] = url . match ( / s t u d i e s \/ ( .* ?) \/ m e t a d a t a / ) ?. [ 1 ] . split ( '/' ) || [ ] ;
1433
@@ -19,9 +38,22 @@ class MetadataManager {
1938
2039 for ( const sopUID in cod . instances ) {
2140 const instance = cod . instances [ sopUID ] ;
22- instance . metadata . DeidStudyInstanceUID = { Value : [ studyUID ] } ;
23- instance . metadata . DeidSeriesInstanceUID = { Value : [ seriesUID ] } ;
24- instance . metadata . DeidSopInstanceUID = { Value : [ sopUID ] } ;
41+
42+ // For V2, convert the metadata to InstanceMetadata format.
43+ if ( instance . version === medatata . METADATA_VERSION . V2 && typeof instance . metadata === 'string' ) {
44+ const parsedMetadata = await this . decodeDecompressAndParse ( instance . metadata ) ;
45+
46+ if ( ! parsedMetadata ) {
47+ throw new Error ( 'Failed to decode, decompress, or parse JSON' ) ;
48+ }
49+
50+ instance . metadata = parsedMetadata ;
51+ }
52+
53+ const instanceMetadata = instance . metadata as InstanceMetadata ;
54+ instanceMetadata . DeidStudyInstanceUID = { Value : [ studyUID ] } ;
55+ instanceMetadata . DeidSeriesInstanceUID = { Value : [ seriesUID ] } ;
56+ instanceMetadata . DeidSopInstanceUID = { Value : [ sopUID ] } ;
2557 }
2658 }
2759
@@ -56,9 +88,10 @@ class MetadataManager {
5688 }
5789 return response . json ( ) ;
5890 } )
59- . then ( ( data ) => {
60- this . addDeidMetadata ( data , url ) ;
61- return writeFile ( directoryHandle , fileName , data , true ) . then ( ( ) => data ) ;
91+ . then ( async ( data ) => {
92+ await this . addDeidMetadata ( data , url ) ;
93+ await writeFile ( directoryHandle , fileName , data , true ) ;
94+ return data ;
6295 } ) ;
6396
6497 return await this . metadataPromises [ url ] ;
@@ -67,6 +100,26 @@ class MetadataManager {
67100 throw error ;
68101 }
69102 }
103+
104+ private async decodeDecompressAndParse ( base64String : string ) : Promise < InstanceMetadata > {
105+ if ( ! base64String ) {
106+ return null ;
107+ }
108+
109+ try {
110+ if ( ! ( await this . decoderInitPromise ) ) {
111+ throw new Error ( 'WASM Decoder is not initialized. Cannot decompress data.' ) ;
112+ }
113+
114+ const compressedBytes = Uint8Array . from ( atob ( base64String ) , ( c ) => c . charCodeAt ( 0 ) ) ;
115+ const decompressedBytes = this . decoder . decode ( compressedBytes ) ;
116+ const jsonString = new TextDecoder ( ) . decode ( decompressedBytes ) ;
117+ return JSON . parse ( jsonString ) ;
118+ } catch ( error ) {
119+ console . error ( 'Failed to decode, decompress, or parse JSON:' , error ) ;
120+ return null ;
121+ }
122+ }
70123}
71124
72125export default MetadataManager ;
0 commit comments