@@ -142,26 +142,31 @@ export class TDKImpl implements tdk.TDK, AsyncDisposable {
142142 const coll = db . getCollection ( normalizeCollectionID ( update . collection ) ) ;
143143 const doc = await coll . getDocument ( update . documentID ) ;
144144 if ( ! doc ) throw new HTTPError ( 404 , `No document "${ update . documentID } "` ) ;
145+
146+ const updatePath = ( pathStr : string , value : cbl . CBLValue | undefined ) : void => {
147+ if ( ! KeyPathCache . path ( pathStr ) . write ( doc , value ) )
148+ throw new HTTPError ( 400 , `Invalid path ${ pathStr } in doc ${ update . documentID } ` ) ;
149+ } ;
150+
145151 switch ( update . type ) {
146152 case 'UPDATE' : {
147153 if ( update . updatedProperties ) {
148154 for ( const props of update . updatedProperties ) {
149- for ( const pathStr of Object . getOwnPropertyNames ( props ) ) {
150- if ( ! KeyPathCache . path ( pathStr ) . write ( doc , props [ pathStr ] ) )
151- throw new HTTPError ( 400 , `Invalid path ${ pathStr } in doc ${ update . documentID } ` ) ;
152- }
155+ for ( const pathStr of Object . getOwnPropertyNames ( props ) )
156+ updatePath ( pathStr , props [ pathStr ] ) ;
153157 }
154158 }
155159 if ( update . removedProperties ) {
156160 for ( const props of update . removedProperties ) {
157- for ( const pathStr of props ) {
158- if ( ! KeyPathCache . path ( pathStr ) . write ( doc , undefined ) )
159- throw new HTTPError ( 400 , `Invalid path ${ pathStr } in doc ${ update . documentID } ` ) ;
160- }
161+ for ( const pathStr of props )
162+ updatePath ( pathStr , undefined ) ;
161163 }
162164 }
163165 if ( update . updatedBlobs ) {
164- throw new HTTPError ( 501 , "updatedBlobs is not implemented yet" ) ; //TODO
166+ for ( const pathStr of Object . getOwnPropertyNames ( update . updatedBlobs ) ) {
167+ const blob = await this . #downloadBlob( update . updatedBlobs [ pathStr ] ) ;
168+ updatePath ( pathStr , blob ) ;
169+ }
165170 }
166171 break ;
167172 }
@@ -190,12 +195,19 @@ export class TDKImpl implements tdk.TDK, AsyncDisposable {
190195 throw new HTTPError ( 501 , "Unimplemented replication feature(s)" ) ;
191196 const collCfg : cbl . ReplicatorCollectionConfig = { } ;
192197 if ( rq . config . replicatorType !== 'pull' ) {
198+ if ( colls . pushFilter ) throw new HTTPError ( 501 , "Push filter is not supported" ) ;
193199 collCfg . push = {
194200 continuous : rq . config . continuous ,
195201 //filter: colls.pushFilter //TODO
196202 } ;
197203 }
198204 if ( rq . config . replicatorType !== 'push' ) {
205+ if ( colls . pullFilter )
206+ throw new HTTPError ( 501 , "Pull filter is not supported" ) ;
207+ if ( colls . documentIDs )
208+ throw new HTTPError ( 501 , "List of docIDs is not supported" ) ;
209+ if ( colls . conflictResolver )
210+ throw new HTTPError ( 501 , "Conflict resolver is not supported" ) ;
199211 collCfg . pull = {
200212 continuous : rq . config . continuous ,
201213 channels : colls . channels ,
@@ -401,7 +413,7 @@ export class TDKImpl implements tdk.TDK, AsyncDisposable {
401413 obj = obj as cbl . CBLDictionary ;
402414 if ( obj [ "@type" ] === "blob" && typeof obj . digest === "string" ) {
403415 ++ totalBlobs ;
404- return await this . #downloadBlob ( obj as unknown as cbl . Bloblike , datasetURL ) ;
416+ return await this . #downloadDataSetBlob ( obj as unknown as cbl . Bloblike , datasetURL ) ;
405417 }
406418 for ( const key of Object . getOwnPropertyNames ( obj ) ) {
407419 const blob = await _installBlobs ( obj [ key ] ) ; // recurse
@@ -416,16 +428,31 @@ export class TDKImpl implements tdk.TDK, AsyncDisposable {
416428 }
417429
418430
419- async #downloadBlob ( blobMeta : cbl . Bloblike , datasetURL : string ) : Promise < cbl . NewBlob > {
431+ async #downloadDataSetBlob ( blobMeta : cbl . Bloblike , datasetURL : string ) : Promise < cbl . NewBlob > {
420432 check ( blobMeta . digest . startsWith ( "sha1-" ) , "Unexpected prefix in blob digest" ) ;
421433 const digest = blobMeta . digest . substring ( 5 ) . replaceAll ( '/' , '_' ) ;
422434 const blobURL = `${ datasetURL } Attachments/${ digest } .blob` ;
423435 this . #logger. info ` - downloading blob ${ blobMeta . digest } ` ;
436+ const contents = await this . #downloadBlobContents( blobURL ) ;
437+ return new cbl . NewBlob ( contents , blobMeta . content_type ) ;
438+ }
439+
440+
441+ async #downloadBlob( blobURL : string ) : Promise < cbl . NewBlob > {
442+ if ( blobURL . endsWith ( ".zip" ) )
443+ throw new HTTPError ( 501 , "Unzipping blobs is not supported" ) ;
444+ const contents = await this . #downloadBlobContents( blobURL ) ;
445+ const type = blobURL . endsWith ( ".jpg" ) ? "image/jpeg" : "application/octet-stream" ;
446+ return new cbl . NewBlob ( contents , type ) ;
447+ }
448+
449+
450+ async #downloadBlobContents( blobURL : string ) : Promise < Uint8Array > {
424451 const response = await fetch ( blobURL ) ;
425452 if ( response . status !== 200 )
426453 throw new HTTPError ( 502 , `Unable to load blob from <${ blobURL } >: ${ response . status } ${ response . statusText } ` ) ;
427454 const data = await response . arrayBuffer ( ) ;
428- return new cbl . NewBlob ( new Uint8Array ( data ) , blobMeta . content_type ) ;
455+ return new Uint8Array ( data ) ;
429456 }
430457
431458
0 commit comments