UNPKG

@i4mi/fhir_r4

Version:

FHIR resource definitions + API methods + utils

245 lines (244 loc) 8.16 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ApiMethods = exports.HttpMethod = void 0; exports.apiCall = apiCall; var HttpMethod; (function (HttpMethod) { HttpMethod["POST"] = "POST"; HttpMethod["PUT"] = "PUT"; HttpMethod["GET"] = "GET"; HttpMethod["DELETE"] = "DELETE"; })(HttpMethod || (exports.HttpMethod = HttpMethod = {})); ; class ApiMethods { constructor(config) { this._content_type = "application/fhir+json;fhirVersion=4.0"; this._config = config ? config : { base_url: "" }; } /** * change the content type to your type * the content type is used as "Content-Type" header in CREATE and UPDATE * the content type is used as "Accept" header in SEARCH and READ * @param ct content type if not "application/fhir+json;fhirVersion=4.0" */ differentiateContentType(ct) { this._content_type = ct; } /** * create a new record * @param resource the resource to create * @param config Optional - the configurations for the request */ create(resource, config) { let args = this.init(HttpMethod.POST, config); if (resource.resourceType !== 'Bundle') { args.url += ('/' + resource.resourceType); } if (!args.headers) { args.headers = { "Prefer": "return=representation", "Content-Type": this._content_type }; } else { if (!args.headers.Prefer) args.headers.Prefer = "return=representation"; if (!args.headers["Content-Type"]) args.headers["Content-Type"] = this._content_type; } args.payload = resource; return apiCall(args); } /** * update a record * @param resource resource to update * @param config Optional - the configurations for the request */ update(resource, config) { let args = this.init(HttpMethod.PUT, config); args.url += ('/' + resource.resourceType + '/' + resource.id); if (!args.headers) { args.headers = { "Prefer": "return=representation", "Content-Type": this._content_type }; } else { if (!args.headers.Prefer) args.headers.Prefer = "return=representation"; if (!args.headers["Content-Type"]) args.headers["Content-Type"] = this._content_type; } args.payload = resource; return apiCall(args); } /** * get a resource * @param resourceType the resource type * @param id the id of the resource * @param vid optional: the version of this resource * @param config optional: the configurations for the request */ read(resourceType, id, vid, config) { let args = this.init(HttpMethod.GET, config); args.url += ('/' + resourceType + '/' + id + (vid ? "/_history/" + vid : "")); if (!args.headers) { args.headers = { "Accept": this._content_type }; } else { if (!args.headers["Accept"]) args.headers["Accept"] = this._content_type; } return apiCall(args); } /** * search resources * @param params the search parameters * @param resourceType the resource type * @param config optional: the configurations for the request */ search(params, resourceType, config) { let args = this.init(HttpMethod.GET, config); //https://www.hl7.org/fhir/http.html#vsearch if (resourceType) { args.url += ('/' + resourceType); } if (!args.headers) { args.headers = { "Accept": this._content_type }; } else { if (!args.headers["Accept"]) args.headers["Accept"] = this._content_type; } if (params) { args.url += "?"; if (typeof params === "string") { args.url += params; } else { let first_time_in_loop_params = true; Object.keys(params).forEach((key) => { if (first_time_in_loop_params) first_time_in_loop_params = false; else args.url += "&"; args.url += (key + "=" + encodeURI(params[key])); }); } } return apiCall(args); } // TODO: delete() { throw "NOT IMPLEMENTED"; } // TODO: implement history()? // help functions /** * this function initialize the CRUD functions * @param method the http method * @param config optional: the configurations for the request */ init(method, config) { // if the configurations are null then use the default configurations defined in the constructor if (!config) { config = this._config; } let args = { method: method, url: config.base_url }; // Add token if given if (config.authorization_type && config.access_token) { if (args.headers) { args.headers.Authorization = config.authorization_type + ' ' + config.access_token; } else { args.headers = { Authorization: config.authorization_type + ' ' + config.access_token }; } } // Add default values for Headers return args; } } exports.ApiMethods = ApiMethods; function apiCall(args) { let url = args.url; let method = args.method; let payload = args.payload; let headers = args.headers; let jsonBody = args.jsonBody || false; let jsonEncoded = args.jsonEncoded; // flag indicating json-encoding const DEFAULT_TIMEOUT = 20000; return new Promise((resolve, reject) => { let xhr = new XMLHttpRequest(); xhr.open(method, url, true); xhr.timeout = DEFAULT_TIMEOUT; if (headers) { Object.keys(headers).forEach((key) => { xhr.setRequestHeader(key, headers[key]); }); } xhr.onload = function () { let status = xhr.status; if (status >= 200 && status < 300) { // successful response let body; if (jsonBody) { body = JSON.parse(xhr.responseText); } else { body = xhr.responseText; } resolve({ message: 'Request successful', body: body, status: status }); } else { // loaded but non-successful response reject({ message: xhr.statusText, body: xhr.responseText, status: status }); } }; xhr.ontimeout = function () { reject({ message: 'Request timed out. No answer from server received', body: '', status: -1 }); }; xhr.onerror = function () { reject({ message: 'Error. transaction failed', body: '', status: 0 }); }; // NOTE: Note that the payload should probably be stringified // before being passed into this function in order to allow // non-json encodings of the payload (such as url-encoded or plain text). // Supplement wya3: Check for JSON encoding. Additionally check if undefined in // order to ensure backward compatibility. if (payload !== undefined) { if (jsonEncoded || jsonEncoded == undefined) { xhr.send(JSON.stringify(payload)); } else { xhr.send(payload); } } else { xhr.send(); } }); } ;