UNPKG

fhirclient

Version:

JavaScript client for Fast Healthcare Interoperability Resources

1,286 lines (1,094 loc) 46.8 kB
/// <reference lib="dom" /> import Client from "./Client"; import { getPath, byCodes, byCode } from "./lib"; import { IncomingMessage } from "http"; 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"; /** * Some OAuth implementations require the client_id to be sent * when using a refresh token. * Setting `FHIR.oauth2.settings.refreshTokenWithClientId = true` * enables this behavior, sending the "client_id" parameter in * the refresh request body. */ refreshTokenWithClientId?: boolean; // 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; /** * An opaque value used by the client to maintain state between the request and callback. * * If stateKey is not specified, one will be generated automatically. * * The authorization server includes this value when redirecting the user-agent back to the * client. * * It's important to ensure that no sensitive information is included in the state * parameter because it could be saved in the browser's history or server logs. To prevent * CSRF attacks, the state parameter should be generated with a secure random seed. * * From the perspective of developing client applications, the state parameter is useful * for restoring a user's session, which might involve querying a data structure for cached * objects specific to that user. The state parameter could refer to a user session key, * but its purpose may vary depending on the application. */ stateKey?: string; /** * Optional request options (headers, etc) to use when calling fetchWellKnownJson. */ wellKnownRequestOptions?: RequestInit; /** * Optional request options (headers, etc) to use when calling getSecurityExtensionsFromConformanceStatement. */ conformanceRequestOptions?: RequestInit; } interface ReadyOptions { privateKey?: JWK | { key: CryptoKey alg: "RS384" | "ES384" kid: string }; clientPublicKeySetUrl?: string; // for jku code?: string; // Optional authorization code to use vs. from URL in ready() stateKey?: string; // Optional state value to use vs. from URL in ready() // [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 * used in human communication. If hours and minutes are specified, a time * zone SHALL be populated. Seconds must be provided due to schema type * constraints but may be zero-filled and may be ignored. Dates SHALL be * valid dates. The time "24:00" is not allowed. * * Patterns: * - `YYYY-MM-DDTHH:mm:ss.SSSSZ` * - `YYYY-MM-DDTHH:mm:ss.SSSZ` * - `YYYY-MM-DDTHH:mm:ssZ` * - `YYYY-MM-DD` * - `YYYY-MM` * - `YYYY` * * Regex: * -?[0-9]{4}(-(0[1-9]|1[0-2])(-(0[0-9]|[1-2][0-9]|3[0-1])(T([01] * [0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9](\.[0-9]+)?(Z|(\+|-)((0[0-9]|1[0-3]): * [0-5][0-9]|14:00)))?)?)? */ type dateTime = string; /** * Any non-negative integer (e.g. >= 0) * Regex: [0]|([1-9][0-9]*) */ type unsignedInt = number; type valueX = "valueInteger" | "valueUnsignedInt" | "valuePositiveInt" | "valueDecimal"|"valueDateTime"|"valueDate"|"valueTime"|"valueInstant"| "valueString"|"valueUri"|"valueOid"|"valueUuid"|"valueId"| "valueBoolean"|"valueCode"|"valueMarkdown"|"valueBase64Binary"| "valueCoding"|"valueCodeableConcept"|"valueAttachment"| "valueIdentifier"|"valueQuantity"|"valueSampledData"|"valueRange"| "valuePeriod"|"valueRatio"|"valueHumanName"|"valueAddress"| "valueContactPoint"|"valueTiming"|"valueReference"|"valueAnnotation"| "valueSignature"|"valueMeta"; interface Element { id?: id; extension?: Array<Extension<valueX>>; } interface Extension<T = "valueX"> extends Element { /** * identifies the meaning of the extension */ url: uri; [T: string]: any; } interface CapabilityStatement { resourceType: string; fhirVersion: string; rest: Array<{ security?: { cors?: boolean; extension?: Array<{ url: string; extension: Array<Extension<"valueUri">> }> }; resource: Array<{ type: string }> }>; } interface Resource extends Record<string, any> { /** * Logical id of this artifact */ id ?: id; resourceType?: string; /** * Metadata about the resource */ meta ?: Meta; /** * A set of rules under which this content was created */ implicitRules ?: uri; /** * Language of the resource content */ language ?: code; } interface Meta extends Element { /** * When the resource version last changed */ lastUpdated: instant; } interface Observation extends Resource { resourceType: "Observation"; } interface Patient extends Resource { resourceType: "Patient"; } interface Practitioner extends Resource { resourceType: "Practitioner"; } interface RelatedPerson extends Resource { resourceType: "RelatedPerson"; } interface Encounter extends Resource { resourceType: "Encounter"; } interface Period extends Element { /** * Starting time with inclusive boundary */ start ?: dateTime; /** * End time with inclusive boundary, if not ongoing */ end ?: dateTime; } interface BackboneElement extends Element { modifierExtension ?: Extension[]; } interface CodeableConcept extends Element { /** * Code defined by a terminology system */ coding?: Coding[]; /** * Plain text representation of the concept */ text?: string; } interface Coding extends Element { /** * Identity of the terminology system */ system ?: uri; /** * Version of the system - if relevant */ version ?: string; /** * Symbol in syntax defined by the system */ code ?: code; /** * Representation defined by the system */ display ?: string; /** * If this coding was chosen directly by the user */ userSelected ?: boolean; } interface Identifier extends Element { use ?: "usual" | "official" | "temp" | "secondary"; /** * Description of identifier */ type ?: CodeableConcept; /** * The namespace for the identifier value */ system ?: uri; /** * The value that is unique */ value ?: string; /** * Time period when id is/was valid for use */ period ?: Period; /** * Organization that issued id (may be just text) */ assigner ?: Reference; } interface Reference extends Element { /** * Literal reference, Relative, internal or absolute URL */ reference ?: string; /** * Logical reference, when literal reference is not known */ identifier ?: Identifier; /** * Text alternative for the resource */ display ?: string; } interface BundleLink extends BackboneElement { relation: string; url: uri; } interface BundleEntry extends BackboneElement { fullUrl: string; // This is optional on POSTs resource: Resource; } interface Bundle extends Resource { /** * Persistent identifier for the bundle */ identifier ?: Identifier; type: "document" | "message" | "transaction" | "transaction-response" | "batch" | "batch-response" | "history" | "searchset" | "collection"; total ?: unsignedInt; link: BundleLink[]; entry?: BundleEntry[]; } } }