forked from jmandel/fhir-js-client
/
types.d.ts
1246 lines (1059 loc) · 43.8 KB
/
types.d.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/// <reference lib="dom" />
import Client from "./Client";
import { getPath, byCodes, byCode } from "./lib";
import { IncomingMessage } from "http";
// tslint:disable-next-line: no-namespace
declare namespace fhirclient {
interface RequestWithSession extends IncomingMessage {
session: fhirclient.JsonObject;
}
interface SMART {
options: BrowserFHIRSettings;
/**
* This should be called on your `redirect_uri`. Returns a Promise that
* will eventually be resolved with a Client instance that you can use
* to query the fhir server.
*/
ready(options?: fhirclient.ReadyOptions): Promise<Client>;
/**
* Starts the [SMART Launch Sequence](http://hl7.org/fhir/smart-app-launch/#smart-launch-sequence).
*
* > **IMPORTANT:** `authorize()` will end up redirecting you to the
* authorization server. This means that you should **not** add
* anything to the returned promise chain. Any code written directly
* after the `authorize()` call might not be executed due to that
* redirect!
*
* The options that you would typically pass for an EHR launch are just
* `clientId` and `scope`. For standalone launch you should also provide
* the `iss` option.
* @param options
*/
authorize(options: AuthorizeParams): Promise<string|void>;
/**
* This function can be used when you want to handle everything in one
* page (no launch endpoint needed).
*
* 1. It will only work if your `launch_uri` is the same as your `redirect_uri`.
* While this should be valid, we can't promise that every EHR will allow you
* to register client with such settings.
* 2. Internally, init() will be called twice. First it will redirect to the EHR,
* then the EHR will redirect back to the page where `init()` will be called
* again to complete the authorization. This is generally fine, because the
* returned promise will only be resolved once, after the second execution,
* but please also consider the following:
* - You should wrap all your app's code in a function that is only executed
* after init() resolves!
* - Since the page will be loaded twice, you must be careful if your code has
* global side effects that can persist between page reloads (for example
* writing to localStorage).
* @param options
*/
init(options: AuthorizeParams): Promise<never|Client>;
/**
* Creates and returns a Client instance that can be used to query the
* FHIR server.
*/
client(state: string | fhirclient.ClientState): Client;
[key: string]: any
}
interface BrowserFHIRSettings extends Record<string, any> {
/**
* Replaces the browser's current URL using
* `window.history.replaceState` API.
*
* ONLY RELEVANT IN BROWSERS!
*/
replaceBrowserHistory?: boolean;
/**
* When set to true, this variable will fully utilize HTML5
* sessionStorage API. This variable can be overridden to false by
* setting `FHIR.oauth2.settings.fullSessionStorageSupport = false`.
* When set to false, the sessionStorage will be keyed by a state
* variable. This is to allow the embedded IE browser instances
* instantiated on a single thread to continue to function without
* having sessionStorage data shared across the embedded IE instances.
*/
fullSessionStorageSupport?: boolean;
/**
* Do we want to send cookies while making a request to the token
* endpoint in order to obtain new access token using existing
* refresh token. In rare cases the auth server might require the
* client to send cookies along with those requests. In this case
* developers will have to change this before initializing the app
* like so:
* `FHIR.oauth2.settings.refreshTokenWithCredentials = "include";`
* or
* `FHIR.oauth2.settings.refreshTokenWithCredentials = "same-origin";`
* Can be one of:
* "include" - always send cookies
* "same-origin" - only send cookies if we are on the same domain (default)
* "omit" - do not send cookies
*/
refreshTokenWithCredentials?: "omit" | "include" | "same-origin";
// storage?: Storage | ((options?: JsonObject) => Storage);
}
interface CodeValue {
code: string;
value: number;
}
interface ObservationMap {
[code: string]: FHIR.Observation[];
}
interface Adapter {
/**
* Environment-specific options
*/
options: BrowserFHIRSettings;
/**
* Given the current environment, this method returns the current url
* as URL instance
*/
getUrl(): URL;
/**
* Given the current environment, this method must redirect to the given
* path
* @param path The relative path to redirect to
*/
redirect(to: string): void | Promise<any>;
/**
* This must return a Storage object
* @returns {fhirclient.Storage}
*/
getStorage(): Storage;
/**
* Given a relative path, compute and return the full url, assuming that
* it is relative to the current location
* @param {String} path The path to convert to absolute
*/
relative(path: string): string;
/**
* Base64 to ASCII string
*/
btoa(str: string): string;
/**
* ASCII string to Base64
*/
atob(str: string): string;
/**
* ASCII string or Uint8Array to Base64URL
*/
base64urlencode: (input: string | Uint8Array) => string
/**
* Base64Url to ASCII string
*/
base64urldecode: (input: string) => string
/**
* Returns a reference to the AbortController class
*/
getAbortController(): typeof AbortController;
/**
* Creates and returns adapter-aware SMART api. Not that while the shape of
* the returned object is well known, the arguments to this function are not.
* Those who override this method are free to require any environment-specific
* arguments. For example in node we will need a request, a response and
* optionally a storage or storage factory function.
*/
getSmartApi(): SMART;
security: {
randomBytes: (count: number) => Uint8Array
digestSha256: (payload: string) => Promise<Uint8Array>
generatePKCEChallenge: (entropy?: number) => Promise<{ codeChallenge: string; codeVerifier: string }>
importJWK: (jwk: JWK) => Promise<CryptoKey>
signCompactJws: (alg: "ES384" | "RS384", privateKey: CryptoKey, header: any, payload: any) => Promise<string>
}
}
/**
* Simple key/value storage interface
*/
interface Storage {
/**
* Sets the `value` on `key` and returns a promise that will be resolved
* with the value that was set.
*/
set: (key: string, value: any) => Promise<any>;
/**
* Gets the value at `key`. Returns a promise that will be resolved
* with that value (or undefined for missing keys).
*/
get: (key: string) => Promise<any>;
/**
* Deletes the value at `key`. Returns a promise that will be resolved
* with true if the key was deleted or with false if it was not (eg. if
* did not exist).
*/
unset: (key: string) => Promise<boolean>;
}
// =========================================================================
type WindowTargetVariable = "_self"|"_top"|"_parent"|"_blank"|"popup"|string|number|Window;
function WindowTargetFunction(): WindowTargetVariable;
function WindowTargetFunction(): Promise<WindowTargetVariable>;
type WindowTarget = WindowTargetVariable | typeof WindowTargetFunction;
type PkceMode = 'ifSupported' | 'required' | 'disabled' | 'unsafeV1';
type storageFactory = (options?: Record<string, any>) => Storage;
interface IncludeResponseHint {
includeResponse?: boolean
[k: string]: any
}
/**
* A function or method that makes requests to the backend server. If the
* `includeResponse` option is `true` resolves with `CombinedFetchResult`
* where the `response` property is the `Response` object and the `body`
* property is the result of type `R` (if any). Otherwise resolves with the
* result as `R`.
* @param R The expected return type
* @param O May contain the `includeResponse` flag to signal that we also
* want to receive the raw response object. Any other option will be passed
* to the underlying `fetch` call.
*/
type RequestFunction<R = any> = <O extends IncludeResponseHint = {}>(requestOptions?: O) =>
Promise<O["includeResponse"] extends true ? CombinedFetchResult<R> : R>;
/**
* Options passed to the lib.request function
*/
interface FetchOptions extends RequestInit {
/**
* If `true` the request function will be instructed to resolve with a
* [[CombinedFetchResult]] object that contains the `Response` object
* abd the parsed body (if any)
*/
includeResponse?: boolean;
}
/**
* If an `includeResponse` is set to true when calling the lib.request
* function the returned object will include the Response object and the
* parsed body if available
*/
interface CombinedFetchResult<T = fhirclient.JsonObject | string> {
body?: T
response: Response
}
/**
* The return type of the lib.request function
*/
type FetchResult = Response | fhirclient.JsonObject | string | CombinedFetchResult
interface ES384JWK extends JsonWebKey {
alg: "ES384"
kty: "EC"
crv: "P-384"
kid: string
key_ops?: KeyUsage[]
[propName: string]: unknown
}
interface RS384JWK extends JsonWebKey {
alg: "RS384"
kty: "RSA"
kid: string
key_ops?: KeyUsage[]
[propName: string]: unknown
}
type JWK = ES384JWK | RS384JWK;
/**
* Options that must contain an `url` property (String|URL).
* A `includeResponse` boolean option might also be passed. Any other
* properties will be passed to the underlying `fetch()` call.
*/
interface RequestOptions extends RequestInit {
/**
* The URL to request
*/
url: string | URL;
/**
* If set to true the request function will resolve with an object
* like `{ body: any, response: Response }` so that users have
* access to the response object and it's properties like headers
* status etc.
*/
includeResponse?: boolean;
}
/**
* The three security endpoints that SMART servers might declare in the
* conformance statement
*/
interface OAuthSecurityExtensions {
/**
* You could register new SMART client at this endpoint (if the server
* supports dynamic client registration)
*/
registrationUri: string;
/**
* You must call this endpoint to ask for authorization code
*/
authorizeUri: string;
/**
* You must call this endpoint to exchange your authorization code
* for an access token.
*/
tokenUri: string;
/**
* Supported PKCE Code challenge methods
*/
codeChallengeMethods: string[];
}
/**
* Describes the state that should be passed to the Client constructor.
* Everything except `serverUrl` is optional
*/
interface ClientState {
/**
* The base URL of the Fhir server. The library should have detected it
* at authorization time from request query params of from config options.
*/
serverUrl: string;
/**
* The client_id that you should have obtained while registering your
* app with the auth server or EHR (as set in the configuration options)
*/
clientId?: string;
/**
* The URI to redirect to after successful authorization, as set in the
* configuration options.
*/
redirectUri?: string;
/**
* The access scopes that you requested in your options (or an empty string).
* @see http://docs.smarthealthit.org/authorization/scopes-and-launch-context/
*/
scope?: string;
/**
* Your client public JWKS url if you have one
* (for asymmetric confidential clients that have registered a JWKS URL)
*/
clientPublicKeySetUrl?: AuthorizeParams['clientPublicKeySetUrl'];
/**
* Your client private JWK if you have one (for asymmetric confidential clients)
*/
clientPrivateJwk?: JWK;
/**
* Your client secret if you have one (for symmetric confidential clients)
*/
clientSecret?: string;
/**
* The (encrypted) access token, in case you have completed the auth flow
* already.
*/
// access_token?: string;
/**
* The response object received from the token endpoint while trying to
* exchange the auth code for an access token (if you have reached that point).
*/
tokenResponse?: TokenResponse;
/**
* The username for basic auth. If present, `password` must also be provided.
*/
username?: string;
/**
* The password for basic auth. If present, `username` must also be provided.
*/
password?: string;
/**
* You could register new SMART client at this endpoint (if the server
* supports dynamic client registration)
*/
registrationUri?: string;
/**
* You must call this endpoint to ask for authorization code
*/
authorizeUri?: string;
/**
* You must call this endpoint to exchange your authorization code
* for an access token.
*/
tokenUri?: string;
/**
* The key under which this state is persisted in the storage
*/
key?: string;
/**
* If `true`, the app requested to be initialized in the specified [[AuthorizeParams.target]].
* Otherwise, the app requested to be initialized in the window in which
* [[authorize]] was called.
*/
completeInTarget?: boolean;
/**
* An Unix timestamp (JSON numeric value representing the number of
* seconds since 1970). This updated every time an access token is
* received from the server.
*/
expiresAt?: number;
/**
* PKCE code challenge base value.
*/
codeChallenge?: string;
/**
* PKCE code verification, formatted with base64url-encode (RFC 4648 § 5)
* without padding, which is NOT the same as regular base64 encoding.
*/
codeVerifier?: string;
}
/**
* Authorization parameters that can be passed to `authorize` or `init`
*/
interface AuthorizeParams {
/**
* This is the URL of the service you are connecting to.
* For [EHR Launch](http://hl7.org/fhir/smart-app-launch/#ehr-launch-sequence)
* you **MUST NOT** provide this option. It will be passed by the EHR as
* url parameter instead. Using `iss` as an option will "lock" your app to
* that service provider. In other words, passing an `iss` option is how
* you can do [Standalone Launch](http://hl7.org/fhir/smart-app-launch/#standalone-launch-sequence).
*/
iss?: string;
/**
* Can be used to verify that the app is being launched against certain
* servers. This is especially useful when working with multiple EHR
* configurations. Can be a string (in which case it will be expected to
* match the provided ISS exactly), a regular expression to test against
* the current ISS, or a function that will be called with the current
* ISS and should return true or false to signify if that ISS is acceptable.
*/
issMatch?: string | RegExp | ((iss: string) => boolean);
/**
* Do not pass use this option, unless you want to test it. It should come
* as url parameter from the SMART authorization server as part of the EHR
* launch sequence
*/
launch?: string;
/**
* The base URL of the FHIR server to use. This is just like the `iss`
* option, except that it is designed to bypass the authentication. If
* `fhirServiceUrl` is passed, the `authorize` function will NOT actually
* attempt to authorize. It will skip that and redirect you to your
* `redirect_uri`.
*/
fhirServiceUrl?: string;
/**
* Defaults to the current directory (it's index file)
* @alias redirect_uri
*/
redirectUri?: string;
/**
* Same as redirectUri
* @alias redirectUri
* @deprecated
*/
redirect_uri?: string;
/**
*
*/
noRedirect?: boolean;
/**
* The client_id that you have obtained while registering your app in the
* EHR. This is not required if you only intend to communicate with open
* FHIR servers. Note: For backwards compatibility reasons we also accept
* `client_id` instead of `clientId`!
* @alias client_id
*/
clientId?: string;
/**
* The client_id that you have obtained while registering your app in the
* EHR. This is not required if you only intend to communicate with open
* FHIR servers. Note: For backwards compatibility reasons we accept
* `client_id` as an alias of `clientId`!
* @alias clientId
* @deprecated
*/
client_id?: string;
/**
* One or more space-separated scopes that you would like to request from
* the EHR. [Learn more](http://hl7.org/fhir/smart-app-launch/scopes-and-launch-context/index.html)
*/
scope?: string;
/**
* The ID of the selected patient. If you are launching against an open FHIR
* server, there is no way to obtain the launch context that would include
* the selected patient ID. This way you can "inject" that ID and make the
* client behave as if that is the currently active patient.
*/
patientId?: string;
/**
* The ID of the selected encounter. If you are launching against an open
* FHIR server, there is no way to obtain the launch context that would
* (in some EHRs) include the selected encounter ID. This way you can
* "inject" that ID and make the client behave as if this is the currently
* active encounter.
*/
encounterId?: string;
/**
* If you have registered a confidential client, you should pass your
* `clientSecret` here. **Note: ONLY use this on the server**, as the
* browsers are considered incapable of keeping a secret.
*/
clientSecret?: string;
/**
* If you have registered a confidential client and you host your public
* key online, you can pass your JWKS URL here **Note: ONLY use this on the server**, as the
* browsers are considered incapable of keeping a secret.
*/
clientPublicKeySetUrl?: string;
/**
* If you have registered a confidential client, you should pass your
* `clientPrivateJwk` here. **Note: ONLY use this on the server**, as
* the browsers are considered incapable of keeping a secret.
*/
clientPrivateJwk?: JWK;
/**
* Useful for testing. This object can contain any properties that are
* typically contained in an [access token response](http://hl7.org/fhir/smart-app-launch/#step-3-app-exchanges-authorization-code-for-access-token).
* These properties will be stored into the client state, as if it has been
* authorized.
*/
fakeTokenResponse?: object;
/**
* Where to start the auth flow. This option is only applicable in
* browsers and is ignored on the server. Can be one of:
* - `_self` Authorize in the same window (**default**)
* - `_top` Authorize in the topmost window
* - `_parent` Authorize in the parent window
* - `_blank` Authorize in new tab or window
* - `"popup"` Open a popup, authorize in it and close it when done
* - `String` Frame name (string index in window.frames)
* - `Number` Numeric index in `window.frames`
* - `Object` Window reference (must have the same `origin`)
* - `Function` A function that returns one of the above values or a
* promise that will resolve to such value.
*/
target?: WindowTarget;
/**
* The width of the authorization popup window. Only used in browsers
* and if the [[AuthorizeParams.target]] option is set to "popup".
*/
width?: number;
/**
* The height of the authorization popup window. Only used in browsers
* and if the [[AuthorizeParams.target]] option is set to "popup".
*/
height?: number;
/**
* If `true`, the app will be initialized in the specified [[AuthorizeParams.target]].
* Otherwise, the app will be initialized in the window in which
* [[authorize]] was called.
*/
completeInTarget?: boolean;
/**
* Client expectations for PKCE (Proof Key for Code Exchange). Can be
* one of:
* - `ifSupported` Use if a matching code challenge method is available (**default**)
* - `required` Do not attempt authorization to servers without support
* - `disabled` Do not use PKCE
* - `unsafeV1` Use against Smart v1 servers. Smart v1 does not define
* conformance, so validate your server supports PKCE before using
* this setting
*/
pkceMode?: PkceMode;
}
interface ReadyOptions {
privateKey?: JWK | {
key: CryptoKey
alg: "RS384" | "ES384"
kid: string
};
clientPublicKeySetUrl?: string; // for jku
// [key: string]: any; // Other options TBD
}
/**
* Additional options that can be passed to `client.request` to control its
* behavior
*/
interface FhirOptions {
/**
* When you request a Bundle, the result will typically come back in pages
* and you will only get the first page. You can use `pageLimit` greater
* than `1` to request multiple pages. For example `pageLimit: 3` will fetch
* the first 3 pages as array. To fetch all the available pages you can set
* this to `0`.
* - Defaults to `1`.
* - Ignored if the response is not a `Bundle`.
*/
pageLimit?: number;
/**
* When you fetch multiple pages the resulting array may be very large,
* requiring a lot of time and memory. It is often better if you specify a
* page callback instead. The `onPage` callback will be called once for each
* page with the page Bundle as it's argument. If you use `resolveReferences`
* and `graph: false`, the references will be passed to `onPage` as second
* argument.
* - If `onPage` returns a promise it will be awaited for, meaning that no
* more pages will be fetched until the `onPage` promise is resolved.
* - If `onPage` returns a rejected promise or throws an error, the client
* will not continue fetching more pages.
* - If you use `onPage` callback, the promise returned by `request()` will
* be resolved with `null`. This is to avoid building that huge array in
* memory. By using the `onPage` option you are stating that you will
* handle the result one page at a time, instead of expecting to receive
* the big combined result.
* @param data Depending in the other options can be `Bundle`, `Bundle[]`,
* `Resource[]`
* @param references Map of resolved references. Only available if the `graph`
* option is set to `false`
*/
onPage?: (data: JsonObject | JsonObject[], references?: JsonObject) => any;
/**
* When fetching a `Bundle`, you are typically only interested in the
* included resources which are located at `{response}.entry[N].resource`.
* If this option is set to `true`, the returned result will be an array of
* resources instead of the whole bundle. This is especially useful when
* multiple pages are fetched, because an array of page bundles is not that
* useful and will often have to be converted to array of resources that is
* easier to iterate.
* - This option is ignored if the response is not a bundle.
* - If you use `onPage` callback with `flat: true`, it will receive that
* array of resources instead of the page bundle.
* - Resources from multiple pages are flattened into single array (unless
* you use `onPage`, which will be called with one array for each page).
* - Defaults to `false`.
* - Finally, `Bundle.entry` is optional in FHIR and that leads to bugs in
* apps that assume that it is always present. With `flat: true`, you will
* always get an array, even if it is empty, and even if no `entry` is
* found in the response bundle.
*/
flat?: boolean;
/**
* Only applicable if you use `resolveReferences`. If `false`, the resolved
* references will not be "mounted" in the result tree, but will be returned
* as separate map object instead. **Defaults to `true`**.
*/
graph?: boolean;
/**
* One or more references to resolve. Single item can be specified as a
* string or as an array of one string. Multiple items must be specified as
* array.
* - Each item is a dot-separated path to the desired reference within the
* result object, excluding the "reference" property. For example
* `context.serviceProvider` will look for `{Response}.context.serviceProvider.reference`.
* - If the target is an array of references (E.g.
* [Patient.generalPractitioner](http://hl7.org/fhir/R4/patient-definitions.html#Patient.generalPractitioner)), you can request one or more of them by index (E.g. `generalPractitioner.0`).
* If the index is not specified, all the references in the array will be
* resolved.
* - The order in which the reference paths are specified does not matter.
* For example, if you use `["subject", "encounter.serviceProvider", "encounter"]`,
* the library should figure out that `encounter.serviceProvider` must be
* fetched after `encounter`. In fact, in this case it will first fetch
* subject and encounter in parallel, and then proceed to encounter.serviceProvider.
* - This option does not work with contained references (they are "already
* resolved" anyway).
*/
resolveReferences?: string|string[];
/**
* If the client is authorized, it will possess an access token and pass it
* with the requests it makes. When that token expires, you should get back
* a `401 Unauthorized` response. When that happens, if the client also has
* a refresh token and if `useRefreshToken` is `true` (default), the client
* will attempt to automatically re-authorize itself and then it will re-run
* the failed request and eventually resolve it's promise with the final
* result. This means that your requests should never fail with `401`,
* unless the refresh token is also expired. If you don't want this, you can
* set `useRefreshToken` to `false`. There is a `refresh` method on the
* client that can be called manually to renew the access token.
* - **Defaults to `true`**.
*/
useRefreshToken?: boolean;
}
/**
* The response object received from the token endpoint while trying to
* exchange the auth code for an access token. This object has a well-known
* base structure but the auth servers are free to augment it with
* additional properties.
* @see http://docs.smarthealthit.org/authorization/
*/
interface TokenResponse {
/**
* If present, this tells the app that it is being rendered within an
* EHR frame and the UI outside that frame already displays the selected
* patient's name, age, gender etc. The app can decide to hide those
* details to prevent the UI from duplicated information.
*/
need_patient_banner?: boolean;
/**
* This could be a public location of some style settings that the EHR
* would like to suggest. The app might look it up and optionally decide
* to apply some or all of it.
* @see https://launch.smarthealthit.org/smart-style.json
*/
smart_style_url?: string;
/**
* If you have requested that require it (like `launch` or `launch/patient`)
* the selected patient ID will be available here.
*/
patient?: string;
/**
* If you have requested that require it (like `launch` or `launch/encounter`)
* the selected encounter ID will be available here.
* **NOTE:** This is not widely supported as of 2018.
*/
encounter?: string;
/**
* If you have requested `openid` and `profile` scopes the profile of
* the active user will be available as `client_id`.
* **NOTE:** Regardless of it's name, this property does not store an ID
* but a token that also suggests the user type like `Patient/123`,
* `Practitioner/xyz` etc.
*/
client_id?: string;
/**
* Fixed value: bearer
*/
token_type?: "bearer" | "Bearer";
/**
* Scope of access authorized. Note that this can be different from the
* scopes requested by the app.
*/
scope?: string;
/**
* Lifetime in seconds of the access token, after which the token SHALL NOT
* be accepted by the resource server
*/
expires_in ?: number;
/**
* The access token issued by the authorization server
*/
access_token?: string;
/**
* Authenticated patient identity and profile, if requested
*/
id_token ?: string;
/**
* Token that can be used to obtain a new access token, using the same or a
* subset of the original authorization grants
*/
refresh_token ?: string;
/**
* Other properties might be passed by the server
*/
[key: string]: any;
}
interface IDToken {
profile: string;
aud: string;
sub: string;
iss: string;
iat: number;
exp: number;
[key: string]: any;
}
// JSON objects
interface JsonObject { [key: string]: JsonValue; }
type JsonPrimitive = string | number | boolean | null
type JsonValue = JsonPrimitive|JsonArray|JsonObject
type JsonArray = JsonValue[]
// JSON Patch - https://datatracker.ietf.org/doc/html/rfc6902
interface JsonPatchAdd { op: "add" ; path: string; value: JsonValue; }
interface JsonPatchReplace { op: "replace"; path: string; value: JsonValue; }
interface JsonPatchTest { op: "test" ; path: string; value: JsonValue; }
interface JsonPatchMove { op: "move" ; path: string; from: string; }
interface JsonPatchCopy { op: "copy" ; path: string; from: string; }
interface JsonPatchRemove { op: "remove" ; path: string; }
type JsonPatchOperation = JsonPatchAdd|JsonPatchRemove|JsonPatchReplace|JsonPatchMove|JsonPatchCopy|JsonPatchTest;
type JsonPatch = JsonPatchOperation[]
// Capabilities ------------------------------------------------------------
type codeChallengeMethod = "S256";
type SMARTAuthenticationMethod = "client_secret_post" | "client_secret_basic" | "private_key_jwt";
type launchMode = "launch-ehr" | "launch-standalone";
type clientType = "client-public" | "client-confidential-symmetric";
type singleSignOn = "sso-openid-connect";
type launchContext = "context-banner" | "context-style";
type launchContextEHR = "context-ehr-patient" | "context-ehr-encounter";
type launchContextStandalone = "context-standalone-patient" | "context-standalone-encounter";
type permissions = "permission-offline" | "permission-patient" | "permission-user";
interface WellKnownSmartConfiguration {
/**
* URL to the OAuth2 authorization endpoint.
*/
authorization_endpoint: string;
/**
* URL to the OAuth2 token endpoint.
*/
token_endpoint: string;
/**
* If available, URL to the OAuth2 dynamic registration endpoint for the
* FHIR server.
*/
registration_endpoint?: string;
/**
* RECOMMENDED! URL where an end-user can view which applications currently
* have access to data and can make adjustments to these access rights.
*/
management_endpoint?: string;
/**
* RECOMMENDED! URL to a server’s introspection endpoint that can be used
* to validate a token.
*/
introspection_endpoint?: string;
/**
* RECOMMENDED! URL to a server’s revoke endpoint that can be used to
* revoke a token.
*/
revocation_endpoint?: string;
/**
* RECOMMENDED! PKCE challenge methods the server supports.
*/
code_challenge_methods_supported?: codeChallengeMethod[];
/**
* Array of client authentication methods supported by the token endpoint.
* The options are “client_secret_post” and “client_secret_basic”.
*/
token_endpoint_auth_methods?: SMARTAuthenticationMethod[];
/**
* Array of scopes a client may request.
*/
scopes_supported?: string[];
/**
* Array of OAuth2 response_type values that are supported
*/
response_types_supported?: string[];
/**
* Array of strings representing SMART capabilities (e.g., single-sign-on
* or launch-standalone) that the server supports.
*/
capabilities: Array<
SMARTAuthenticationMethod |
launchMode |
clientType |
singleSignOn |
launchContext |
launchContextEHR |
launchContextStandalone |
permissions
>;
}
namespace FHIR {
/**
* Any combination of upper or lower case ASCII letters ('A'..'Z', and
* 'a'..'z', numerals ('0'..'9'), '-' and '.', with a length limit of 64
* characters. (This might be an integer, an un-prefixed OID, UUID or any
* other identifier pattern that meets these constraints.)
* Regex: `[A-Za-z0-9\-\.]{1,64}`
*/
type id = string;
/**
* A Uniform Resource Identifier Reference (RFC 3986 ). Note: URIs are case
* sensitive. For UUID (urn:uuid:53fefa32-fcbb-4ff8-8a92-55ee120877b7) use
* all lowercase. URIs can be absolute or relative, and may have an optional
* fragment identifier.
*/
type uri = string;
/**
* Indicates that the value is taken from a set of controlled strings
* defined elsewhere. Technically, a code is restricted to a string which
* has at least one character and no leading or trailing whitespace, and
* where there is no whitespace other than single spaces in the contents
* Regex: [^\s]+([\s]?[^\s]+)*
*/
type code = string;
/**
* An instant in time - known at least to the second and always includes a
* time zone. Note: This is intended for precisely observed times (typically
* system logs etc.), and not human-reported times - for them, use date and
* dateTime. instant is a more constrained dateTime.
*
* Patterns:
* - `YYYY-MM-DDTHH:mm:ss.SSSSZ`
* - `YYYY-MM-DDTHH:mm:ss.SSSZ`
* - `YYYY-MM-DDTHH:mm:ssZ`
*/
type instant = string; // "2018-04-30T13:31:44.140-04:00"
/**
* A date, date-time or partial date (e.g. just year or year + month) as