1
1
import { decodeJwt } from 'jose'
2
2
import { logger } from '@navikt/next-logger'
3
+ import { ZodIssue } from 'zod'
3
4
4
5
import { getSession } from '@fhir/auth/session'
5
- import { FhirDocumentReference , FhirDocumentReferenceResponseSchema } from '@fhir/fhir-data/schema/documentReference'
6
+ import { FhirDocumentReference , FhirDocumentReferenceBaseSchema } from '@fhir/fhir-data/schema/documentReference'
6
7
7
8
import { FhirPractitionerSchema } from '../fhir-data/schema/practitioner'
8
9
import { getHpr } from '../fhir-data/schema/mappers/practitioner'
9
10
import { getName } from '../fhir-data/schema/mappers/patient'
10
- import { BehandlerInfo , DocumentReferenceResponse } from '../../data-fetcher/data-service'
11
+ import { BehandlerInfo , WriteToEhrResult } from '../../data-fetcher/data-service'
11
12
12
13
/**
13
14
* These FHIR resources are only available in the server runtime. They are not proxied through the backend.
14
15
* They will use the session store and fetch resources directly from the FHIR server.
15
16
*/
16
17
export const serverFhirResources = {
17
- createDocumentReference : async ( pdf : string , title : string ) : Promise < DocumentReferenceResponse > => {
18
+ createDocumentReference : async (
19
+ pdf : string ,
20
+ title : string ,
21
+ sykmeldingId : string ,
22
+ ) : Promise <
23
+ | WriteToEhrResult
24
+ | { errorType : 'INVALID_FHIR_RESPONSE' ; zodErrors : ZodIssue [ ] }
25
+ | { errorType : 'INVALID_PRACTITIONER_ID' ; zodErrors : ZodIssue [ ] }
26
+ | { errorType : 'INACTIVE_USER_SESSION' ; zodErrors : ZodIssue [ ] }
27
+ > => {
18
28
const currentSession = await getSession ( )
19
29
if ( currentSession == null ) {
20
- throw new Error ( 'Active session is required' )
30
+ return { errorType : 'INACTIVE_USER_SESSION' , zodErrors : [ ] }
21
31
}
22
32
23
33
const decodedIdToken = decodeJwt ( currentSession . idToken )
@@ -31,14 +41,21 @@ export const serverFhirResources = {
31
41
const encounterId = currentSession . encounter
32
42
33
43
if ( typeof practitionerId !== 'string' ) {
34
- throw new Error ( 'practitionerId is not string' )
44
+ return { errorType : 'INVALID_PRACTITIONER_ID' , zodErrors : [ ] }
35
45
}
36
- const documentReference = prepareDocRefWithB64Data ( practitionerId , patientId , encounterId , pdf , title )
46
+ const documentReferencePayload = prepareDocRefWithB64Data ( {
47
+ title,
48
+ pdf,
49
+ sykmeldingId,
50
+ encounterId,
51
+ patientId,
52
+ practitionerId,
53
+ } )
37
54
38
55
const resourcePath = `${ currentSession . issuer } /DocumentReference/`
39
56
const documentReferenceResponse = await fetch ( resourcePath , {
40
57
method : 'POST' ,
41
- body : JSON . stringify ( documentReference ) ,
58
+ body : JSON . stringify ( documentReferencePayload ) ,
42
59
headers : {
43
60
Authorization : `Bearer ${ currentSession . accessToken } ` ,
44
61
ContentType : 'application/fhir+json' ,
@@ -55,24 +72,30 @@ export const serverFhirResources = {
55
72
logger . error ( `Request to create DocumentReference failed with json: ${ JSON . stringify ( json ) } ` )
56
73
}
57
74
58
- throw new Error ( 'Unable to create DocumentReference' )
75
+ return { errorType : 'INVALID_FHIR_RESPONSE' , zodErrors : [ ] }
59
76
}
60
77
61
78
const docRefResult = await documentReferenceResponse . json ( )
62
- const parsedDocRefResult = FhirDocumentReferenceResponseSchema . safeParse ( docRefResult )
79
+ const parsedDocRefResult = FhirDocumentReferenceBaseSchema . safeParse ( docRefResult )
63
80
if ( ! parsedDocRefResult . success ) {
64
- throw new Error ( 'DocumentReference was not a valid FhirDocumentReference' , {
65
- cause : parsedDocRefResult . error ,
66
- } )
81
+ return { errorType : 'INVALID_FHIR_RESPONSE' , zodErrors : [ ] }
67
82
}
68
83
69
- return parsedDocRefResult . data
84
+ return { outcome : 'NEWLY_CREATED' , documentReference : parsedDocRefResult . data }
70
85
} ,
71
86
72
- getDocumentReference : async ( sykmeldingId : string ) : Promise < DocumentReferenceResponse > => {
87
+ getDocumentReference : async (
88
+ sykmeldingId : string ,
89
+ ) : Promise <
90
+ | WriteToEhrResult
91
+ | { errorType : 'DOCUMENT_NOT_FOUND' }
92
+ | { errorType : 'INVALID_FHIR_RESPONSE' ; zodErrors : ZodIssue [ ] }
93
+ | { errorType : 'INACTIVE_USER_SESSION' ; zodErrors : ZodIssue [ ] }
94
+ | { errorType : 'FAILED_TO_GET_DOCUMENT_REFERENCE' ; zodErrors : ZodIssue [ ] }
95
+ > => {
73
96
const currentSession = await getSession ( )
74
97
if ( currentSession == null ) {
75
- throw new Error ( 'Active session is required' )
98
+ return { errorType : 'INACTIVE_USER_SESSION' , zodErrors : [ ] }
76
99
}
77
100
const resourcePath = `${ currentSession . issuer } /DocumentReference/${ sykmeldingId } `
78
101
logger . info ( `Resource path: ${ resourcePath } ` )
@@ -84,6 +107,11 @@ export const serverFhirResources = {
84
107
} ,
85
108
} )
86
109
110
+ if ( documentReferenceResponse . status === 404 ) {
111
+ logger . info ( `DocumentReference/${ sykmeldingId } was not found on FHIR server` )
112
+ return { errorType : 'DOCUMENT_NOT_FOUND' }
113
+ }
114
+
87
115
if ( ! documentReferenceResponse . ok ) {
88
116
logger . error ( 'Request to get DocumentReference failed' , documentReferenceResponse )
89
117
if ( documentReferenceResponse . headers . get ( 'Content-Type' ) ?. includes ( 'text/plain' ) ) {
@@ -93,19 +121,20 @@ export const serverFhirResources = {
93
121
const json = await documentReferenceResponse . json ( )
94
122
logger . error ( `Request to get DocumentReference failed with json: ${ JSON . stringify ( json ) } ` )
95
123
}
96
-
97
- throw new Error ( 'Unable to get DocumentReference' )
124
+ return { errorType : 'FAILED_TO_GET_DOCUMENT_REFERENCE' , zodErrors : [ ] }
98
125
}
99
126
100
- const safeParsedDocumentReferenceResponse = FhirDocumentReferenceResponseSchema . safeParse (
127
+ const safeParsedDocumentReferenceResponse = FhirDocumentReferenceBaseSchema . safeParse (
101
128
await documentReferenceResponse . json ( ) ,
102
129
)
103
130
if ( ! safeParsedDocumentReferenceResponse . success ) {
104
- throw new Error ( 'DocumentReference was not a valid FhirDocumentReference' , {
105
- cause : safeParsedDocumentReferenceResponse . error ,
106
- } )
131
+ return {
132
+ errorType : 'INVALID_FHIR_RESPONSE' ,
133
+ zodErrors : safeParsedDocumentReferenceResponse . error . errors ,
134
+ }
107
135
}
108
- return safeParsedDocumentReferenceResponse . data
136
+
137
+ return { outcome : 'ALREADY_EXISTS' , documentReference : safeParsedDocumentReferenceResponse . data }
109
138
} ,
110
139
111
140
getBehandlerInfo : async ( ) : Promise < BehandlerInfo > => {
@@ -165,15 +194,26 @@ export const serverFhirResources = {
165
194
} ,
166
195
}
167
196
168
- function prepareDocRefWithB64Data (
169
- patientId : string ,
170
- practitionerId : string ,
171
- encounterId : string ,
172
- pdf : string ,
173
- title : string ,
174
- ) : FhirDocumentReference {
197
+ type PrepareDocRefOpts = {
198
+ patientId : string
199
+ practitionerId : string
200
+ encounterId : string
201
+ pdf : string
202
+ title : string
203
+ sykmeldingId : string
204
+ }
205
+
206
+ function prepareDocRefWithB64Data ( {
207
+ patientId,
208
+ practitionerId,
209
+ encounterId,
210
+ pdf,
211
+ title,
212
+ sykmeldingId,
213
+ } : PrepareDocRefOpts ) : Omit < FhirDocumentReference , 'meta' > {
175
214
return {
176
215
resourceType : 'DocumentReference' ,
216
+ id : sykmeldingId ,
177
217
status : 'current' ,
178
218
type : {
179
219
coding : [
0 commit comments