11import Adapter from '../interfaces/Adapter'
2- import { Bookmark , Folder , ItemLocation } from '../Tree'
2+ import { Bookmark , Folder , ItemLocation , TItem , TItemLocation } from '../Tree'
33import PQueue from 'p-queue'
44import { ICapabilities , IHashSettings , IResource } from '../interfaces/Resource'
55import Logger from '../Logger'
@@ -118,12 +118,7 @@ export default class KarakeepAdapter implements Adapter, IResource<typeof ItemLo
118118 }
119119 }
120120
121- async createBookmark ( bookmark : {
122- id : string | number
123- url : string
124- title : string
125- parentId : string | number
126- } ) : Promise < string | number > {
121+ async createBookmark ( bookmark : Bookmark < TItemLocation > ) : Promise < string | number > {
127122 Logger . log ( '(karakeep)CREATE' , { bookmark } )
128123 const response = await this . sendRequest (
129124 'POST' ,
@@ -133,7 +128,9 @@ export default class KarakeepAdapter implements Adapter, IResource<typeof ItemLo
133128 type : 'link' ,
134129 url : bookmark . url ,
135130 title : bookmark . title ,
136- }
131+ } ,
132+ false ,
133+ bookmark
137134 )
138135 if ( response . alreadyExists ) {
139136 await this . sendRequest (
@@ -142,25 +139,23 @@ export default class KarakeepAdapter implements Adapter, IResource<typeof ItemLo
142139 'application/json' ,
143140 {
144141 title : bookmark . title ,
145- }
142+ } ,
143+ false ,
144+ bookmark
146145 )
147146 }
148147 await this . sendRequest (
149148 'PUT' ,
150149 `/api/v1/lists/${ bookmark . parentId } /bookmarks/${ response . id } ` ,
151150 'application/json' ,
152151 undefined ,
153- /* returnRawResponse */ true
152+ true ,
153+ bookmark
154154 )
155155 return `${ response . id } ;${ bookmark . parentId } `
156156 }
157157
158- async updateBookmark ( bookmark : {
159- id : string | number
160- url : string
161- title : string
162- parentId : string | number
163- } ) : Promise < void > {
158+ async updateBookmark ( bookmark : Bookmark < TItemLocation > ) : Promise < void > {
164159 Logger . log ( '(karakeep)UPDATE' , { bookmark } )
165160 const [ id , oldParentId ] = this . parseBookmarkId ( bookmark . id )
166161 await this . sendRequest (
@@ -170,7 +165,9 @@ export default class KarakeepAdapter implements Adapter, IResource<typeof ItemLo
170165 {
171166 url : bookmark . url ,
172167 title : bookmark . title ,
173- }
168+ } ,
169+ false ,
170+ bookmark
174171 )
175172
176173 if ( oldParentId !== bookmark . parentId ) {
@@ -180,55 +177,61 @@ export default class KarakeepAdapter implements Adapter, IResource<typeof ItemLo
180177 `/api/v1/lists/${ oldParentId } /bookmarks/${ id } ` ,
181178 'application/json' ,
182179 undefined ,
183- /* returnRawResponse */ true
180+ true ,
181+ bookmark
184182 ) ,
185183 this . sendRequest (
186184 'PUT' ,
187185 `/api/v1/lists/${ bookmark . parentId } /bookmarks/${ id } ` ,
188186 'application/json' ,
189187 undefined ,
190- /* returnRawResponse */ true
188+ true ,
189+ bookmark
191190 ) ,
192191 ] )
193192 }
194193 bookmark . id = `${ id } ;${ bookmark . parentId } `
195194 }
196195
197- async removeBookmark ( bookmark : {
198- id : string | number
199- parentId : string | number
200- } ) : Promise < void > {
196+ async removeBookmark ( bookmark : Bookmark < TItemLocation > ) : Promise < void > {
201197 Logger . log ( '(karakeep)DELETE' , { bookmark } )
202198
203199 const [ id , parentId ] = this . parseBookmarkId ( bookmark . id )
204200
205- // Remove the bookmark from the list
206- await this . sendRequest (
207- 'DELETE' ,
208- `/api/v1/lists/${ parentId } /bookmarks/${ id } ` ,
209- 'application/json' ,
210- undefined ,
211- /* returnRawResponse */ true
212- )
213-
214- // If the bookmark is not in any list, delete it from the server
215- const bookmarkLists = await this . getListsOfBookmark ( id )
216- if ( bookmarkLists . size === 0 ) {
201+ try {
202+ // Remove the bookmark from the list
217203 await this . sendRequest (
218204 'DELETE' ,
219- `/api/v1/bookmarks/${ id } ` ,
205+ `/api/v1/lists/ ${ parentId } / bookmarks/${ id } ` ,
220206 'application/json' ,
221207 undefined ,
222- /* returnRawResponse */ true
208+ true ,
209+ bookmark
223210 )
211+
212+ // If the bookmark is not in any list, delete it from the server
213+ const bookmarkLists = await this . getListsOfBookmark ( id )
214+ if ( bookmarkLists . size === 0 ) {
215+ await this . sendRequest (
216+ 'DELETE' ,
217+ `/api/v1/bookmarks/${ id } ` ,
218+ 'application/json' ,
219+ undefined ,
220+ true ,
221+ bookmark
222+ )
223+ }
224+ } catch ( e ) {
225+ if ( e instanceof HttpError ) {
226+ if ( e . status === 404 ) {
227+ return
228+ }
229+ }
230+ throw e
224231 }
225232 }
226233
227- async createFolder ( folder : {
228- id : string | number
229- title ?: string
230- parentId : string | number
231- } ) : Promise < string | number > {
234+ async createFolder ( folder : Folder < TItemLocation > ) : Promise < string | number > {
232235 Logger . log ( '(karakeep)CREATEFOLDER' , { folder } )
233236 const response = await this . sendRequest (
234237 'POST' ,
@@ -239,16 +242,14 @@ export default class KarakeepAdapter implements Adapter, IResource<typeof ItemLo
239242 icon : '📔' ,
240243 type : 'manual' ,
241244 parentId : folder . parentId ,
242- }
245+ } ,
246+ false ,
247+ folder
243248 )
244249 return response . id
245250 }
246251
247- async updateFolder ( folder : {
248- id : string | number
249- title ?: string
250- parentId : string | number
251- } ) : Promise < void > {
252+ async updateFolder ( folder : Folder < TItemLocation > ) : Promise < void > {
252253 Logger . log ( '(karakeep)UPDATEFOLDER' , { folder } )
253254 await this . sendRequest (
254255 'PATCH' ,
@@ -257,14 +258,16 @@ export default class KarakeepAdapter implements Adapter, IResource<typeof ItemLo
257258 {
258259 name : folder . title ,
259260 parentId : folder . parentId ,
260- }
261+ } ,
262+ false ,
263+ folder
261264 )
262265 }
263266
264267 /**
265268 * Removes the list from karakeep, but also all its content recursively
266269 */
267- async removeFolder ( folder : { id : string | number } ) : Promise < void > {
270+ async removeFolder ( folder : Folder < TItemLocation > ) : Promise < void > {
268271 Logger . log ( '(karakeep)DELETEFOLDER' , { folder } )
269272
270273 const deleteListContent = async ( ) => {
@@ -276,17 +279,27 @@ export default class KarakeepAdapter implements Adapter, IResource<typeof ItemLo
276279 'GET' ,
277280 `/api/v1/lists/${ folder . id } /bookmarks?includeContent=false&${
278281 nextCursor ? 'cursor=' + nextCursor : ''
279- } `
282+ } `,
283+ undefined ,
284+ undefined ,
285+ false ,
286+ folder
280287 )
281288 nextCursor = response . nextCursor
282289 bookmarkIds . push ( ...response . bookmarks . map ( ( b ) => b . id ) )
283290 } while ( nextCursor !== null )
284291 await Promise . all (
285292 bookmarkIds . map ( ( id ) =>
286- this . removeBookmark ( {
287- id : `${ id } ;${ folder . id } ` ,
288- parentId : folder . id ,
289- } )
293+ // create a dummy bookmark
294+ this . removeBookmark (
295+ new Bookmark ( {
296+ id : `${ id } ;${ folder . id } ` ,
297+ parentId : folder . id ,
298+ url : 'about:blank' ,
299+ title : '' ,
300+ location : ItemLocation . SERVER ,
301+ } )
302+ )
290303 )
291304 )
292305 }
@@ -300,23 +313,37 @@ export default class KarakeepAdapter implements Adapter, IResource<typeof ItemLo
300313
301314 await Promise . all (
302315 childrenListIds . map ( ( listId ) =>
303- this . removeFolder ( {
316+ // create dummy folder
317+ this . removeFolder ( new Folder ( {
304318 id : listId ,
305- } )
319+ parentId : folder . id ,
320+ title : '' ,
321+ location : ItemLocation . SERVER ,
322+ } ) )
306323 )
307324 )
308325 }
309326
310327 await Promise . all ( [ deleteListContent ( ) , deleteListFolders ( ) ] )
311328
312329 // Delete the list itself "after" deleting all its content in case any failure occurs in the previous steps
313- await this . sendRequest (
314- 'DELETE' ,
315- `/api/v1/lists/${ folder . id } ` ,
316- 'application/json' ,
317- undefined ,
318- /* returnRawResponse */ true
319- )
330+ try {
331+ await this . sendRequest (
332+ 'DELETE' ,
333+ `/api/v1/lists/${ folder . id } ` ,
334+ 'application/json' ,
335+ undefined ,
336+ true ,
337+ folder
338+ )
339+ } catch ( e ) {
340+ if ( e instanceof HttpError ) {
341+ if ( e . status === 404 ) {
342+ return
343+ }
344+ }
345+ throw e
346+ }
320347 }
321348
322349 async getBookmarksTree (
@@ -428,7 +455,8 @@ export default class KarakeepAdapter implements Adapter, IResource<typeof ItemLo
428455 relUrl : string ,
429456 type : string = null ,
430457 body : any = null ,
431- returnRawResponse = false
458+ returnRawResponse = false ,
459+ item : TItem < TItemLocation > = null
432460 ) : Promise < any > {
433461 const url = this . server . url + relUrl
434462 let res
@@ -447,7 +475,7 @@ export default class KarakeepAdapter implements Adapter, IResource<typeof ItemLo
447475 Logger . log ( `QUEUING ${ verb } ${ url } ` )
448476
449477 if ( ! IS_BROWSER ) {
450- return this . sendRequestNative ( verb , url , type , body , returnRawResponse )
478+ return this . sendRequestNative ( verb , url , type , body , returnRawResponse , item )
451479 }
452480
453481 try {
@@ -487,16 +515,21 @@ export default class KarakeepAdapter implements Adapter, IResource<typeof ItemLo
487515 throw new RedirectError ( )
488516 }
489517
490- if ( returnRawResponse ) {
491- return res
492- }
493-
494518 if ( res . status === 403 ) {
495519 throw new AuthenticationError ( )
496520 }
497521 if ( res . status === 503 || res . status >= 400 ) {
498- throw new HttpError ( res . status , verb )
522+ Logger . log (
523+ `${ verb } ${ url } : Server responded with ${ res . status } : ` +
524+ ( await res . text ( ) ) . substring ( 0 , 250 )
525+ )
526+ throw new HttpError ( res . status , verb , item )
527+ }
528+
529+ if ( returnRawResponse ) {
530+ return res
499531 }
532+
500533 let json
501534 try {
502535 json = await res . json ( )
@@ -512,7 +545,8 @@ export default class KarakeepAdapter implements Adapter, IResource<typeof ItemLo
512545 url : string ,
513546 type : string ,
514547 body : any ,
515- returnRawResponse : boolean
548+ returnRawResponse : boolean ,
549+ item : TItem < TItemLocation > = null
516550 ) {
517551 let res
518552 let timedOut = false
@@ -561,7 +595,18 @@ export default class KarakeepAdapter implements Adapter, IResource<typeof ItemLo
561595 throw new AuthenticationError ( )
562596 }
563597 if ( res . status === 503 || res . status >= 400 ) {
564- throw new HttpError ( res . status , verb )
598+ let responseData : string
599+ try {
600+ responseData =
601+ typeof res . data === 'string' ? res . data : JSON . stringify ( res . data )
602+ } catch ( e ) {
603+ responseData = String ( res . data )
604+ }
605+ Logger . log (
606+ `${ verb } ${ url } : Server responded with ${ res . status } : ` +
607+ responseData . substring ( 0 , 250 )
608+ )
609+ throw new HttpError ( res . status , verb , item )
565610 }
566611 const json = res . data
567612
0 commit comments