@@ -5,6 +5,7 @@ const databaseTiny = new dbDriver("tiny")
55export default class Line {
66
77 #tinyAction = 'create'
8+ #hydrated = false
89 #setRerumId( ) {
910 if ( ! this . id . startsWith ( process . env . RERUMIDPREFIX ) ) {
1011 this . id = `${ process . env . RERUMIDPREFIX } ${ this . id . split ( "/" ) . pop ( ) } `
@@ -51,36 +52,48 @@ export default class Line {
5152 throw new Error ( `Failed to save Line to RERUM: ${ err . message } ` )
5253 } )
5354 this . #tinyAction = 'update'
55+ this . #hydrated = true
5456 return this
5557 }
56- // ...else Update the existing page in RERUM
57- const existingLine = await fetch ( this . id ) . then ( res => res . json ( ) )
58- . catch ( err => {
59- if ( err . status === 404 ) {
60- // If the line doesn't exist, we can create it
61- return null
58+ // ...else Update the existing line in RERUM
59+ const existingLine = await fetch ( this . id ) . then ( async ( resp ) => {
60+ if ( resp . ok ) return resp . json ( )
61+ if ( resp . status === 404 ) return null
62+ let rerumErrorMessage
63+ try {
64+ rerumErrorMessage = `${ resp . status ?? 500 } : ${ this . id } - ${ await resp . text ( ) } `
65+ } catch ( e ) {
66+ rerumErrorMessage = `500: ${ this . id } - A RERUM error occurred`
6267 }
63- throw new Error ( `Failed to fetch existing Line from RERUM: ${ err . message } ` )
68+ const err = new Error ( rerumErrorMessage )
69+ err . status = 502
70+ throw err
6471 } )
65-
66- if ( ! existingLine ) {
72+ . catch ( err => {
73+ if ( err . status === 502 ) throw err
74+ const genericRerumNetworkError = new Error ( `500: ${ this . id } - A RERUM error occurred` )
75+ genericRerumNetworkError . status = 502
76+ throw genericRerumNetworkError
77+ } )
78+ if ( ! ( existingLine ?. id || existingLine ?. [ "@id" ] ) ) {
6779 // This id doesn't exist in RERUM, so we need to create it
6880 this . #tinyAction = 'create'
6981 }
70-
7182 // Skip RERUM update if no content changes detected
7283 // Uses hasAnnotationChanges from shared.js instead of a private Class method for testability.
7384 if ( existingLine && ! hasAnnotationChanges ( existingLine , lineAsAnnotation ) ) {
85+ this . #hydrated = true
7486 return this // Return without versioning
7587 }
76-
88+ const action = this . #tinyAction === 'create' ? 'save' : this . #tinyAction
7789 const updatedLine = existingLine ? { ...existingLine , ...lineAsAnnotation } : lineAsAnnotation
78- const newURI = await databaseTiny [ this . #tinyAction ] ( updatedLine ) . then ( res => res . id )
90+ const newURI = await databaseTiny [ action ] ( updatedLine ) . then ( res => res . id )
7991 . catch ( err => {
8092 throw new Error ( `Failed to update Line in RERUM: ${ err . message } ` )
8193 } )
8294 this . id = newURI
8395 this . #tinyAction = 'update'
96+ this . #hydrated = true
8497 return this
8598 }
8699
@@ -98,36 +111,41 @@ export default class Line {
98111 * Only RERUM URIs are supported.
99112 */
100113 async #loadAnnotationDataFromRerum( ) {
101- const rerumURI = this . id
102- if ( rerumURI . startsWith ?. ( process . env . RERUMIDPREFIX ) ) {
103- const rawLineData = await fetch ( rerumURI ) . then ( async ( resp ) => {
114+ if ( this . id . startsWith ?. ( process . env . RERUMIDPREFIX ) ) {
115+ const rawLineData = await fetch ( this . id ) . then ( async ( resp ) => {
104116 if ( resp . ok ) return resp . json ( )
105117 // The response from RERUM indicates a failure, likely with a specific code and textual body
106- let rerumErrorMessage = ` ${ resp . status ?? 500 } : ${ rerumURI } - `
118+ let rerumErrorMessage
107119 try {
108- rerumErrorMessage += await resp . text ( )
120+ rerumErrorMessage = `${ resp . status ?? 500 } : ${ this . id } - ${ await resp . text ( ) } `
121+ } catch ( e ) {
122+ rerumErrorMessage = `500: ${ this . id } - A RERUM error occurred`
109123 }
110- catch ( err ) {
111- rerumErrorMessage = undefined
112- }
113- const err = new Error ( rerumErrorMessage ?? `${ resp . status ?? 500 } : A RERUM error occurred for ${ rerumURI } ` )
124+ const err = new Error ( rerumErrorMessage )
114125 err . status = 502
115126 throw err
116127 } )
128+ . catch ( err => {
129+ if ( err . status === 502 ) throw err
130+ const genericRerumNetworkError = new Error ( `500: ${ this . id } - A RERUM error occurred` )
131+ genericRerumNetworkError . status = 502
132+ throw genericRerumNetworkError
133+ } )
117134 if ( ! ( rawLineData . id || rawLineData [ "@id" ] ) ) {
118135 // A 200 with garbled data, call it a fail
119- const err = new Error ( `A RERUM error occurred for ${ rerumURI } ` )
120- err . status = 502
121- throw err
136+ const genericRerumNetworkError = new Error ( `500: ${ this . id } - A RERUM error occurred` )
137+ genericRerumNetworkError . status = 502
138+ throw genericRerumNetworkError
122139 }
123140 // We don't have Class getters and setters for these properties...
124141 if ( 'body' in rawLineData ) this . body = rawLineData . body
125- if ( rawLineData . target ) this . target = rawLineData . target
142+ if ( ' target' in rawLineData ) this . target = rawLineData . target
126143 if ( rawLineData . creator ) this . creator = rawLineData . creator
127144 if ( rawLineData . motivation ) this . motivation = rawLineData . motivation
128145 if ( rawLineData . label ) this . label = rawLineData . label
129146 if ( rawLineData . type ) this . type = rawLineData . type
130147 this . #tinyAction = 'update'
148+ this . #hydrated = true
131149 }
132150 return this
133151 }
@@ -237,19 +255,27 @@ export default class Line {
237255 }
238256
239257 async asJSON ( isLD ) {
240- if ( this . body === undefined ) await this . #loadAnnotationDataFromRerum( )
241- return isLD ? {
242- '@context' : 'http://iiif.io/api/presentation/3/context.json' ,
243- id : this . id ,
244- type : 'Annotation' ,
245- motivation : this . motivation ?? 'transcribing' ,
246- target : this . target ,
247- body : this . body ,
248- } : {
249- id : this . id ,
250- body : this . body ?? '' ,
251- target : this . target ?? '' ,
258+ if ( ! this . #hydrated) await this . #loadAnnotationDataFromRerum( )
259+ let result
260+ if ( isLD ) {
261+ result = {
262+ '@context' : 'http://iiif.io/api/presentation/3/context.json' ,
263+ id : this . id ,
264+ type : 'Annotation' ,
265+ motivation : this . motivation ?? 'transcribing' ,
266+ target : this . target ,
267+ body : this . body ,
268+ }
269+ if ( this . creator ) result . creator = this . creator
270+ }
271+ else {
272+ result = {
273+ id : this . id ,
274+ body : this . body ?? '' ,
275+ target : this . target ?? '' ,
276+ }
252277 }
278+ return result
253279 }
254280
255281 asHTML ( ) {
@@ -262,7 +288,7 @@ export default class Line {
262288 * @returns {string } The text content of the Line, or empty string if no textual body exists.
263289 */
264290 async asTextBlob ( ) {
265- if ( this . body === undefined ) await this . #loadAnnotationDataFromRerum( )
291+ if ( ! this . #hydrated ) await this . #loadAnnotationDataFromRerum( )
266292 return extractTextFromAnnotationBody ( this . body )
267293 }
268294
0 commit comments