emr-api-client
Version:
Api client for accessing openmrs service
1 lines • 57.6 kB
Source Map (JSON)
{"version":3,"sources":["../src/types.ts","../package.json","../src/api_core.ts","../src/global_property.ts","../src/demographic_exchange.ts","../src/user.ts","../src/user_property.ts","../src/obs.ts","../src/location.ts","../src/patient.ts","../src/person.ts","../src/lab.ts","../src/drug.ts","../src/encounter.ts"],"sourcesContent":["export enum ClientError {\n INVALID_API_VERSION = 'Invalid API version',\n NOT_FOUND = 'Request not found',\n ENTITY_ERROR = 'Entity error',\n BAD_REQUEST = 'Bad request',\n REQUEST_FAILED = 'Request Failed',\n NO_CONNECTION = 'No connection',\n SERVER_ERROR = 'Server Error',\n INTERNAL_ERROR = 'Internal error',\n GENERAL_ERROR = 'General Error',\n GENERAL_REQUEST_ERROR = 'General request error',\n AUTHENTICATION_ERROR = 'Authentication Error',\n GATE_WAY_ERROR = 'Gate way error',\n RECORD_CONFLICT = 'Record conflict'\n}\n\nexport type IdentificationTypeName = 'OpenMRS Identification Number' |\n 'Old Identification Number' |\n 'National id' |\n 'ARV Number' |\n 'z_deprecated Pre ART Number (Old format)' |\n 'VHW ID' |\n 'District TB Number' |\n 'Dummy ID' |\n 'z_deprecated EID Number' |\n 'Unknown ID' |\n 'MDR-TB Program Identifier' |\n 'KS Number' |\n 'z_deprecated PART Number' |\n 'Diabetes Number' |\n 'LAB IDENTIFIER' |\n 'DS Number' |\n 'Filing number' |\n 'Archived filing number' |\n 'HCC Number' |\n 'Radiology Study Number' |\n 'IVR Access Code' |\n 'Pre-ART Number' |\n 'Serial Number' |\n 'HTC Identifier' |\n 'ANC Connect ID' |\n 'FUCHIA ID' |\n 'DDE person document ID' |\n 'Malawi National ID' |\n 'District IPT Number' |\n 'Legacy ARV Number'\n\nexport type UserRoleName = 'Anonymous' |\n 'Provider' |\n 'System Developer' |\n 'Accompagnateur' |\n 'Accompagnateur Leader' |\n 'Adults' |\n 'Clinician' |\n 'Counselor' |\n 'Data Assistant' |\n 'Data Element Contributor' |\n 'Data Manager' |\n 'Doctor' |\n 'General Registration Clerk' |\n 'HMIS lab order' |\n 'HSA' |\n 'Informatics Manager' |\n 'Lab' |\n 'Medical Assistant' |\n 'Nurse' |\n 'Paediatrics' |\n 'Pharmacist' |\n 'Program Manager' |\n 'Registration Clerk' |\n 'Social Worker' |\n 'SPINE clinician' |\n 'Superuser' |\n '\"Superuser,Superuser,\"' |\n 'Supervisor' |\n 'Therapeutic Feeding Clerk' |\n 'Vitals Clerk' |\n 'Authenticated'\n\nexport interface UpdatedUserI {\n given_name?: string;\n family_name?: string;\n password?: string;\n roles?: UserRoleName[];\n programs?: number[];\n must_append_roles?: boolean;\n}\n\nexport interface NewUserI {\n given_name: string;\n family_name: string;\n roles: UserRoleName[];\n username: string;\n password: string;\n programs?: number[];\n}\n\nexport interface RequestDataI {\n url: string;\n config: Record<string, any>\n}\n\nexport interface UserI {\n deactivated_on: string | null;\n user_id: number;\n creator: number;\n person_id: number;\n changed_by: number;\n date_changed: string;\n system_id: string;\n username: string;\n date_created: string;\n retired: number;\n retired_by: number | null;\n date_retired: string | null;\n retire_reason: string;\n uuid: string;\n roles: RoleI[];\n programs: any[]; // You might want to define a type for programs if needed\n person: PersonI;\n}\n \nexport interface RoleI {\n role: string;\n description: string;\n uuid: string;\n}\n\ninterface PersonAddressI {\n person_address_id: number;\n person_id: number;\n preferred: number;\n address1: null | string;\n address2: string;\n city_village: string;\n state_province: string;\n postal_code: null | string;\n country: null | string;\n latitude: null | string;\n longitude: null | string;\n creator: number;\n date_created: string;\n voided: number;\n voided_by: null | number;\n date_voided: null | string;\n void_reason: null | string;\n county_district: string;\n neighborhood_cell: string;\n region: null | string;\n subregion: null | string;\n township_division: string;\n uuid: string;\n}\n\nexport interface PersonI {\n person_id: number;\n gender: string;\n birthdate: string | null;\n birthdate_estimated: number;\n dead: number;\n death_date: string | null;\n cause_of_death: string | null;\n creator: number;\n date_created: string;\n changed_by: number;\n date_changed: string;\n voided: number;\n voided_by: number | null;\n date_voided: string | null;\n void_reason: string | null;\n uuid: string;\n names: PersonNameI[];\n person_attributes: PersonAttributeI[];\n addresses: PersonAddressI[];\n}\n\nexport interface PersonNameI {\n person_name_id: number;\n preferred: number;\n person_id: number;\n prefix: string | null;\n given_name: string;\n middle_name: string;\n family_name_prefix: string | null;\n family_name: string;\n family_name2: string | null;\n family_name_suffix: string | null;\n degree: string | null;\n creator: number;\n date_created: string;\n voided: number;\n voided_by: number | null;\n date_voided: string | null;\n void_reason: string | null;\n changed_by: number | null;\n date_changed: string | null;\n uuid: string;\n}\n\nexport interface RequestBodyI {\n method: 'GET' | 'POST' | 'PUT' | 'DELETE',\n body?: string\n}\n\nexport interface AuthorizationDataI {\n token: string;\n expiry_time: string;\n user: UserI;\n}\n\nexport interface DDESearchDemographicsI {\n given_name: string;\n family_name: string;\n gender: string;\n}\n\nexport interface DDESearchByDemographicsResponse {\n locals: PatientI[];\n remotes: PatientI[];\n}\n\nexport interface DDEclientMergeDataI {\n patient_id: number;\n doc_id: string;\n}\n\n/**\n * Data that is saved in session storage for persitence\n */ \nexport interface ApiDataI {\n host: string;\n token: string;\n tokenExpiryDate: string;\n userID: string;\n personID: string;\n username: string;\n userRoles: string;\n}\n\n/**\n * When making API calls, this object will be returns\n */\nexport interface JsonRequestResponse<T = any> {\n /**\n * For successful API connections, ok will be true\n */\n ok: boolean;\n /**s\n * Retrieve client error type. Useful for handling specific errors\n */\n clientErrorType?: ClientError;\n /**\n * Generated error message\n */\n errorMessage?: string;\n /**\n * Response as returned by fetch request\n */\n httpStatusResponse?: number;\n /**\n * Any data returned by the API\n */\n data?: T;\n}\n\nexport interface ObsValueI {\n concept_id: number;\n value_text?: string;\n value_coded?: number;\n value_datetime?: string;\n value_modifier?: string | null;\n value_boolean?: string;\n value_numeric?: number;\n obs_group_id?: number;\n obs_datetime?: string;\n}\n\nexport interface NewObsI {\n encounter_id: number;\n observations: Array<ObsValueI>;\n}\n\nexport interface NewPatientI {\n given_name?: string;\n family_name?: string;\n gender?: string;\n birth_date?: string;\n home_district?: number;\n birthdate_estimated?: boolean;\n home_traditional_authority?: number;\n home_village?: number;\n current_district?: number;\n current_village?: number;\n current_traditional_authority?: number;\n cell_phone_number?: string;\n landmark?: string;\n}\n\nexport interface NewPersonAttributeI {\n person_id: number;\n person_attribute_type_id: number;\n value: number | string;\n}\n\nexport interface PersonAttributeTypeI {\n person_attribute_type_id: number;\n name: string;\n description: string;\n format: string;\n foreign_key: null;\n searchable:number;\n creator: number;\n date_created: Date;\n changed_by: number;\n date_changed: Date;\n retired: number;\n retired_by: null;\n date_retired: null;\n retire_reason: null;\n edit_privilege:null;\n uuid: string;\n sort_weight: number;\n}\n\nexport interface PersonAttributeI {\n person_attribute_id?: number;\n person_id: number;\n value: string;\n person_attribute_type_id: number;\n creator?: number;\n date_created?: Date;\n changed_by?: null;\n date_changed?: null;\n voided?: number;\n voided_by?: null;\n date_voided?: null;\n void_reason?: null;\n uuid?: string;\n type?: PersonAttributeTypeI;\n}\n\nexport interface NewPersonI {\n given_name: string;\n family_name: string;\n middle_name?: string;\n gender: string;\n birthdate: string;\n birthdate_estimated: boolean;\n home_district: string;\n home_traditional_authority: string;\n home_village: string;\n current_district: string;\n current_traditional_authority: string;\n current_village: string;\n landmark: string;\n cell_phone_number: string;\n occupation: string;\n}\n\nexport interface ModifyPersonI {\n program_id?: number;\n given_name?: string;\n family_name?: string;\n gender?: string;\n birthdate?: string;\n birthdate_estimated?: boolean;\n home_district?: string;\n home_traditional_authority?: string;\n home_village?: string;\n current_district?: string;\n current_traditional_authority?: string;\n current_village?: string;\n landmark?: string;\n cell_phone_number?: string;\n occupation?: string;\n}\n\nexport interface NewStateI {\n state: number;\n date: string;\n}\n\nexport interface NewTestsI {\n concept_id: number\n}\n\nexport interface NewOrderI {\n accession_number : string;\n encounter_id: number;\n tests: NewTestsI[];\n reason_for_test_id: string;\n target_lab: string;\n date: string;\n requesting_clinician: string;\n specimen?: {\n concept_id: number\n }\n}\n\nexport interface NewLabOrderI {\n encounter_id: number;\n order: NewOrderI[];\n}\n\nexport interface DrugI{\n drug_inventory_id: number;\n dose: number;\n drug?: any;\n dosage_struct?: any;\n order?: any;\n equivalent_daily_dose: number;\n frequency: string;\n start_date: string;\n auto_expire_date: string;\n instructions: string;\n units: string;\n quantity?: number;\n}\n\nexport interface PatientI {\n patient_id: number;\n tribe: string|null;\n creator: string;\n date_created: string;\n changed_by: number;\n date_changed: string;\n voided: number;\n voided_by: string|null;\n date_voided: string|null;\n void_reason: string|null;\n merge_history: any[];\n tpt_status: {\n tpt: string|null;\n completed: boolean;\n tb_treatment: boolean;\n tpt_init_date: string|null;\n tpt_complete_date: string|null;\n tpt_end_date: string|null\n };\n art_start_date: string;\n person: PersonI;\n patient_identifiers: PatientIdentifierI[];\n}\n\nexport interface PatientIdentifierI {\n patient_identifier_id: number;\n patient_id: number;\n identifier: string;\n identifier_type: number;\n preferred: number;\n location_id: number;\n creator: number;\n date_created: string;\n voided: number;\n voided_by: number|null;\n date_voided: string|null;\n void_reason: string|null;\n uuid: string;\n}\n\nexport interface DemographicSearchParamsI {\n given_name?: string;\n family_name?: string;\n gender?: string;\n middle_name?: string; \n birthdate?: string;\n}\n\nexport interface RelationshipTypeI {\n relationship_type_id: number;\n a_is_to_b: string;\n b_is_to_a: string;\n preferred: number;\n weight: number;\n description: string;\n creator: number;\n date_created: string;\n uuid: string;\n retired: boolean;\n retired_by: null | number;\n date_retired: null | string;\n retire_reason: null | string;\n}\n\nexport interface RelationI {\n relationship_id: number;\n person_a: number;\n relationship: number;\n person_b: number;\n creator: number;\n date_created: string;\n voided: number;\n voided_by: null | number;\n date_voided: null | string;\n void_reason: null | string;\n uuid: string;\n type: RelationshipTypeI;\n relation: PersonI;\n}\n\nexport interface RegionI {\n region_id: number;\n name: string;\n creator: number;\n date_created: string;\n retired: boolean;\n retired_by: null | number;\n date_retired: null | string;\n retire_reason: null | string;\n}\n\nexport interface DistrictI {\n district_id: number;\n name: string;\n region_id: number;\n creator: number;\n date_created: string;\n retired: boolean;\n retired_by: null | number;\n date_retired: null | string;\n retire_reason: null | string;\n}\n\nexport interface TAI {\n traditional_authority_id: number;\n name: string;\n district_id: number;\n creator: number;\n date_created: string;\n retired: boolean;\n retired_by: null | number;\n date_retired: null | string;\n retire_reason: null | string;\n}\n\nexport interface VillageI {\n village_id: number;\n name: string;\n traditional_authority_id: number;\n creator: number;\n date_created: string;\n retired: boolean;\n retired_by: null | number;\n date_retired: null | string;\n retire_reason: null | string;\n}\n\nexport interface LocationI {\n location_id: number;\n name: string;\n description: string;\n address1: string;\n address2: string;\n city_village: string;\n state_province: string;\n postal_code: string;\n country: string;\n latitude: string;\n longitude: string;\n creator: number;\n date_created: string;\n county_district: null | string;\n neighborhood_cell: null | string;\n region: null | string;\n subregion: null | string;\n township_division: null | string;\n retired: boolean;\n retired_by: null | number;\n date_retired: null | string;\n retire_reason: null | string;\n location_type_id: null | number;\n parent_location: null | number;\n uuid: string;\n district: string;\n}\n\nexport interface NewDrugOrderI {\n encounter_id: number;\n drug_orders: DrugI[];\n}\n\nexport interface LoginAuthenticationResponse {\n authorization : AuthorizationDataI;\n}\n\nexport interface UserActivationI {\n message: string[];\n user: UserI\n}\n\nexport interface UserPropertyI {\n user_id: number;\n property: string;\n property_value: string;\n}\n\nexport interface NewGlobalPropertyI {\n property: string;\n property_value: string;\n description: null | string;\n uuid: string;\n}\n\nexport interface ObsFiltersI {\n person_id?: number;\n concept_id?: number;\n encounter_id?: number;\n order_id?: number;\n value_coded?: number;\n value_datetime?: string;\n value_numeric?: number;\n accession_number?: number; \n value_text?: string;\n program_id?: number;\n date?: string;\n start_date?: string;\n end_date?: string;\n\n}\n\nexport interface ConceptNameI {\n concept_id: number;\n name: string;\n locale: string;\n creator: number;\n date_created: string;\n concept_name_id: number;\n voided: number;\n voided_by: any;\n date_voided: any;\n void_reason: any;\n uuid: string;\n concept_name_type: string;\n locale_preferred: number;\n }\n \nexport interface ConceptI {\n concept_id: number;\n retired: number;\n short_name: any;\n description: any;\n form_text: any;\n datatype_id: number;\n class_id: number;\n is_set: number;\n creator: number;\n date_created: string;\n default_charge: any;\n version: string;\n changed_by: any;\n date_changed: any;\n retired_by: any;\n date_retired: any;\n retire_reason: any;\n uuid: string;\n concept_names: ConceptNameI[];\n}\n \nexport interface ObservationI {\n obs_id: number;\n person_id: number;\n concept_id: number;\n encounter_id: number;\n order_id: any;\n obs_datetime: string;\n location_id: any;\n obs_group_id: any;\n accession_number: any;\n value_group_id: any;\n value_boolean: any;\n value_coded: any;\n value_coded_name_id: any;\n value_drug: any;\n value_datetime: any;\n value_numeric: number;\n value_modifier: any;\n value_text: any;\n date_started: any;\n date_stopped: any;\n comments: any;\n creator: number;\n date_created: string;\n voided: number;\n voided_by: any;\n date_voided: any;\n void_reason: any;\n value_complex: any;\n uuid: string;\n concept: ConceptI;\n children: ObservationI[];\n}\n\nexport interface EncounterFiltersI {\n program_id?: number;\n patient_id?: number;\n location_id?: number;\n encounter_type_id?: number;\n date?: string;\n page?: number;\n page_size?: number;\n}\n\nexport interface EncounterTypeI {\n encounter_type_id: number;\n name: string;\n description: string;\n creator: number;\n date_created: string;\n retired: number;\n retired_by: null | any;\n date_retired: null | any;\n retire_reason: null | any;\n uuid: string;\n}\n\nexport interface ProgramI {\n program_id: number;\n concept_id: number;\n creator: number;\n date_created: string;\n changed_by: number;\n date_changed: string;\n retired: number;\n name: string;\n description: string;\n uuid: string;\n}\n\nexport interface NewEncounterI {\n encounter_type_id: number; \n patient_id: number; \n program_id: number;\n provider_id?: number;\n encounter_datetime?: string;\n}\n\nexport interface EncounterI {\n encounter_id: number;\n encounter_type: number;\n patient_id: number;\n provider_id: number;\n location_id: number;\n form_id: null | any;\n encounter_datetime: string;\n creator: number;\n date_created: string;\n voided: number;\n voided_by: null | any;\n date_voided: null | any;\n void_reason: null | any;\n uuid: string;\n changed_by: number;\n date_changed: string;\n program_id: number;\n type: EncounterTypeI;\n patient: {\n patient_id: number;\n tribe: null | any;\n creator: number;\n date_created: string;\n changed_by: null | any;\n date_changed: null | any;\n voided: number;\n voided_by: null | any;\n date_voided: null | any;\n void_reason: null | any;\n };\n location: LocationI;\n provider: PersonI;\n program: ProgramI;\n observations: ObservationI[];\n}\n\nexport interface EncounterCountParamsI {\n encounter_types: number[];\n program_id?: number;\n date?: string;\n}\n\nexport interface UpdateEncounterI {\n type_id?: number;\n patient_id?: number;\n provider_id?: number;\n encounter_datetime?: string;\n}\n\nexport interface UserFiltersI {\n page_size?: number;\n page?: number;\n role?: UserRoleName;\n}\n\nexport interface ConceptFiltersI {\n name?: string;\n set?: string;\n page_size?: number;\n page?: number;\n}","{\n \"name\": \"emr-api-client\",\n \"version\": \"1.1.1\",\n \"apiConfig\": {\n \"host\": \"http://127.0.0.1:9000\"\n },\n \"description\": \"Api client for accessing openmrs service\",\n \"main\": \"./dist/index.js\",\n \"module\": \"./dist/index.mjs\",\n \"types\": \"./dist/index.d.ts\",\n \"files\": [\n \"dist\"\n ],\n \"scripts\": {\n \"build\": \"tsup\",\n \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\",\n \"prepublishOnly\": \"npm run build\"\n },\n \"author\": \"Andrew Mfune\",\n \"license\": \"ISC\",\n \"devDependencies\": {\n \"ts-node\": \"^10.9.1\",\n \"tsup\": \"^7.2.0\",\n \"typescript\": \"^5.2.2\"\n },\n \"keywords\": [\n \"BHT-EMR-API Client\",\n \"BHT-EMR-API\",\n \"H.I.S\",\n \"EMR\",\n \"EMR Client\",\n \"POC\",\n \"POC Client\",\n \"Emastercard\"\n ]\n}\n","import {\n RoleI,\n ApiDataI,\n RequestBodyI,\n RequestDataI,\n ClientError,\n JsonRequestResponse,\n UserRoleName,\n LoginAuthenticationResponse,\n AuthorizationDataI,\n} from \"./types\"\nimport packageJs from \"../package.json\"\n\nexport default new class {\n readonly AUTH = '_auth_'\n readonly HOST = '_host_'\n readonly KEEP_USER_LOGGED_IN_FLAG = '_keep_user_logged_in_'\n userRoles: RoleI[] = []\n host = ''\n token = ''\n username = ''\n userID = -1\n personID = -1\n tokenExpiryDate = ''\n sessionAvailable = false\n canPersistLogin: boolean = false\n interceptRequest: (req: RequestDataI) => RequestDataI\n interceptResponse: (req: RequestDataI, res: JsonRequestResponse) => JsonRequestResponse\n constructor() {\n this.loadState()\n this.interceptRequest = (req: RequestDataI) => req\n this.interceptResponse = (_, res: JsonRequestResponse) => res\n }\n /**\n * This will return the current logged in user's name\n * @returns \n */\n getUsername() { return this.username }\n\n /**\n * Get the logged in user's person id\n * @returns \n */\n getProviderID() { return this.personID }\n\n /**\n * Returns userID of currently logged in user\n * @returns \n */\n getUserID() { return this.userID }\n \n /**\n * Returns URL of API host\n * @returns \n */\n getHost() { return this.host }\n\n /**\n * Configure API host URL i.e. http://localhost:3000 or https://emr.malawi.com \n * @param host \n */\n setHost(host: string) {\n this.host = host\n localStorage.setItem(this.HOST, this.host)\n }\n\n /**\n * Generic function for running API endpoints.\n * @param relativeUrl \n * @param data \n * @param baseUrl \n * @returns \n */\n async restRequest<T = any>(relativeUrl: string, data: RequestBodyI, baseUrl='api/v1'): Promise<JsonRequestResponse<T>> {\n let requestData: RequestDataI = {\n url: `${this.host}/${baseUrl}/${relativeUrl}`,\n config: {\n ...data,\n mode: 'cors',\n headers: {\n 'Authorization': this.token,\n 'Content-Type': 'application/json'\n }\n }\n }\n const res: JsonRequestResponse = { ok: false }\n // Run callback before making API request to allow for modifications to the original request object\n requestData = this.interceptRequest(requestData)\n try {\n const req = await fetch(requestData.url, requestData.config)\n const statusResponse = req.status\n res.httpStatusResponse = statusResponse;\n if(statusResponse === 204) {\n return this.interceptResponse(requestData, res);\n }\n\n res.data = await req.json()\n if ([200, 201, 202].includes(statusResponse)) {\n res.ok = true;\n return this.interceptResponse(requestData, res)\n }\n switch(statusResponse) {\n case 400:\n res.clientErrorType = ClientError.BAD_REQUEST\n break;\n case 401:\n res.clientErrorType = ClientError.AUTHENTICATION_ERROR\n break;\n case 404:\n res.clientErrorType = ClientError.NOT_FOUND\n break;\n case 409: \n res.clientErrorType = ClientError.RECORD_CONFLICT\n break;\n case 422:\n res.clientErrorType = ClientError.ENTITY_ERROR\n break;\n case 500:\n res.clientErrorType = ClientError.SERVER_ERROR\n break;\n case 502:\n res.clientErrorType = ClientError.GATE_WAY_ERROR\n break; \n default:\n res.clientErrorType = ClientError.GENERAL_REQUEST_ERROR\n break;\n }\n res.errorMessage = Array.isArray(res.data?.errors) \n ? res.data?.errors.join(',') \n : res.clientErrorType || `Error code ${res.httpStatusResponse}`\n } catch(e) {\n if (/NetworkError|Failed to fetch/i.test(`${e}`)) {\n res.clientErrorType = ClientError.NO_CONNECTION\n res.errorMessage = \"Unable to connect to server/network\"\n } else {\n res.clientErrorType = ClientError.INTERNAL_ERROR\n res.errorMessage = `${e}`\n }\n }\n return this.interceptResponse(requestData, res)\n }\n\n /**\n * Authentication methord that creates a temporary session on the client side after a successful login\n * @param username\n * @param password\n * @returns\n */\n async login(username: string, password: string, canPersistLogin=this.canPersistLogin) {\n this.sessionAvailable = false\n const res = await this.postJson<LoginAuthenticationResponse>('auth/login', { username, password })\n if (res.ok) {\n this.canPersistLogin = canPersistLogin\n this.username = username\n this.startSession(res.data!.authorization)\n return res\n }\n this.clearState()\n return res\n }\n\n\n /**\n * Starts a new session by saving authentication data and updating the session state.\n * @param data - The authorization data containing token, expiry time, user details, and roles.\n */\n startSession(data: AuthorizationDataI) {\n this.tokenExpiryDate = data.expiry_time\n this.personID = data.user.person_id\n this.userID = data.user.user_id\n this.userRoles = data.user.roles\n this.token = data.token\n this.sessionAvailable = true\n this.saveState()\n }\n\n /**\n * Verifies a password reset token by making a POST request to the API.\n * If the token is valid, starts a new session with the returned authorization data.\n * @param token - The reset token to verify.\n * @returns A boolean indicating whether the token verification was successful.\n */\n async verifyResetToken(token: string) {\n const res = await this.postJson<LoginAuthenticationResponse>(`auth/reset_password?code=${token}`, {})\n if (res.ok && res.data) {\n this.startSession(res.data.authorization);\n return true;\n }\n this.clearState()\n return false;\n }\n\n /**\n * Clears login session information on the client side\n */\n logout() {\n this.token = ''\n this.userID = -1\n this.personID = -1\n this.username = ''\n this.userRoles = []\n this.tokenExpiryDate = ''\n this.sessionAvailable = false\n this.clearState()\n }\n\n /**Simple check to verify login session */\n isLoggedIn() { return this.sessionAvailable }\n\n /**\n * Validates provided roles against roles assigned to the current login user\n * @param roles\n * @returns\n */\n userHasRoles(roles: UserRoleName[]) {\n const sanitize = (txt: string) => txt.toLowerCase().trim()\n const sanitizedRoles = roles.map(r => sanitize(r))\n return this.userRoles.some((role) => sanitizedRoles.includes(sanitize(role.role)))\n }\n\n /**\n * Perfoms GET http requests with optional parameters\n * @param url \n * @param params \n * @returns \n */\n getJson<T>(url: string, params: Record<string, any>={}) {\n const urlParams = Object.keys(params).map(k => `${k}=${params[k]}`).join('&')\n const fullUrl = urlParams.length ? `${url}?${urlParams}` : url\n return this.restRequest<T>(fullUrl, { method: \"GET\" })\n }\n\n /**\n * Perfoms POST http requests with provided data\n * @param url \n * @param data \n * @returns \n */\n postJson<T>(url: string, data: any) {\n return this.restRequest<T>(url, {\n method: \"POST\",\n body: JSON.stringify(data)\n })\n }\n\n /**\n * Perfoms PUT http requests with provided data\n * @param url \n * @param data \n * @returns \n */\n putJson<T>(url: string, data: any) {\n return this.restRequest<T>(url, { \n method: \"PUT\",\n body: JSON.stringify(data)\n })\n }\n\n /**\n * Perfoms DELETE http requests with provided data\n * @param url \n * @param data \n * @returns \n */\n void<T>(url: string, params={}) {\n return this.restRequest<T>(url, { \n method: \"DELETE\", \n body: JSON.stringify(params) \n })\n }\n\n /**\n * Method for validating expiration status of a token\n * @returns \n */\n tokenHasExpired() {\n return this.tokenExpiryDate ? new Date() > new Date(this.tokenExpiryDate) : true \n }\n\n /**\n * Perfoms a healthcheck operation to verify if the API is up\n * @returns \n */\n async apiOk() {\n const req = await this.getJson<Record<'status', 'up' | 'down'>>('_health')\n return req.ok && `${req?.data?.status}`.toLowerCase() === 'up'\n }\n\n /**\n * Gets current date from the API\n * @returns \n */\n async getDate() {\n const req = await this.getJson('current_time')\n if (req.ok) return req.data\n }\n\n /**\n * Gets current API version\n * @returns \n */\n async getVersion() {\n const req = await this.getJson<Record<string, string>>('version')\n if (req.ok && req.data) return req?.data['System version']\n }\n\n /**\n * Caches authentication data\n */\n saveState() {\n const data = JSON.stringify({\n token: this.token,\n userID: this.userID,\n personID: this.personID,\n username: this.username,\n userRoles: this.userRoles,\n tokenExpiryDate: this.tokenExpiryDate\n })\n this.canPersistLogin\n ? localStorage.setItem(this.AUTH, data)\n : sessionStorage.setItem(this.AUTH, data)\n localStorage.setItem(this.KEEP_USER_LOGGED_IN_FLAG, `${this.canPersistLogin}`)\n }\n\n /**\n * Reads saved authentication state\n */\n loadState() {\n this.canPersistLogin = JSON.parse(localStorage.getItem(this.KEEP_USER_LOGGED_IN_FLAG)||`${this.canPersistLogin}`)\n const strData = this.canPersistLogin\n ? localStorage.getItem(this.AUTH)\n : sessionStorage.getItem(this.AUTH)\n const state: ApiDataI = JSON.parse(strData||'{}')\n this.host = localStorage.getItem(this.HOST)|| packageJs?.apiConfig?.host\n this.token = state?.token\n this.username = state?.username\n this.personID = parseInt(`${state?.personID}`)\n this.userID = parseInt(`${state?.userID}`)\n this.tokenExpiryDate = state?.tokenExpiryDate\n this.userRoles = state?.userRoles || [] as any\n this.sessionAvailable = Object.keys(state).length > 0 && !this.tokenHasExpired()\n }\n\n clearState() {\n localStorage.removeItem(this.AUTH)\n sessionStorage.removeItem(this.AUTH)\n }\n}\n","import ApiCore from \"./api_core\";\nimport { NewGlobalPropertyI } from \"./types\";\n\nexport default new class {\n get(property: string) {\n return ApiCore.getJson<Record<string, string>>('global_properties', { property })\n }\n\n set(property: string, propertyValue: string) {\n return ApiCore.postJson<NewGlobalPropertyI>('global_properties', {\n property, property_value: propertyValue\n })\n }\n\n async isProp(property: string) {\n try {\n const [prop, val] = property.split('=')\n const curVal = await this.get(prop)\n\n if (curVal?.data) return val === curVal.data[prop]\n } catch (e) {\n console.error(e)\n }\n return false\n }\n}","import ApiCore from \"./api_core\"\nimport { DDESearchByDemographicsResponse, DDESearchDemographicsI, DDEclientMergeDataI, PatientI } from \"./types\"\nimport GlobalProperty from \"./global_property\"\n\nexport default class {\n programID: number\n readonly NATIONAL_ID_TYPE = 3\n\n constructor(programID: number) {\n this.programID = programID\n }\n\n async isDDeEnabled() {\n return GlobalProperty.isProp('dde_enabled=true')\n }\n\n async enableDDe() {\n return GlobalProperty.set('dde_enabled', `true`)\n }\n\n async disableDDe() {\n return GlobalProperty.set('dde_enabled', `false`)\n }\n\n findByNpid(npid: string) {\n return ApiCore.getJson('dde/patients/find_by_npid', {\n npid: npid, program_id: this.programID \n })\n }\n\n findByDemographics(demographics: DDESearchDemographicsI) {\n return ApiCore.getJson<DDESearchByDemographicsResponse>(`dde/patients/find_by_name_and_gender`, {\n program_id: this.programID, ...demographics\n })\n }\n\n findVoidedNpid(npid: string) {\n return ApiCore.getJson(`search/patients/by_identifier`, {\n voided: true,\n identifier: npid,\n type_id: this.NATIONAL_ID_TYPE\n })\n }\n\n getRemainingNpids() {\n return ApiCore.getJson('dde/patients/remaining_npids', {\n program_id: this.programID\n })\n }\n\n reassignNpid(docID: string, patientID: number) {\n return ApiCore.postJson('dde/patients/reassign_npid', {\n program_id: this.programID,\n patient_id: patientID,\n doc_id: docID\n })\n }\n\n createNpID(npid: string, patientID: number) {\n return ApiCore.postJson('patient_identifiers', {\n identifier: npid,\n patient_id: patientID,\n identifier_type: this.NATIONAL_ID_TYPE\n })\n }\n\n getLocalAndRemoteDiffs(patientID: number) {\n return ApiCore.getJson('dde/patients/diff', {\n patient_id: patientID,\n program_id: this.programID\n })\n }\n\n updateLocalDiffs(diffs: any, patientID: number) {\n return ApiCore.putJson(`people/${patientID}`, {\n program_id: this.programID, ...diffs\n })\n }\n\n refreshDemographics(patientID: number) {\n return ApiCore.getJson('dde/patients/refresh', {\n program_id: this.programID,\n patient_id: patientID\n })\n }\n\n importPatient(docID: string) {\n return ApiCore.getJson<PatientI>('dde/patients/import_by_doc_id', {\n program_id: this.programID,\n doc_id: docID\n })\n }\n\n mergePatients(primary: DDEclientMergeDataI, secondary: DDEclientMergeDataI) {\n return ApiCore.postJson('dde/patients/merge', {\n program_id: this.programID,\n primary,\n secondary\n })\n }\n\n checkPotentialDuplicates(demographics: Record<string, any>) {\n return ApiCore.getJson(`dde/patients/match_by_demographics`, {\n ...demographics, program_id: this.programID\n }) \n }\n}\n","import ApiCore from \"./api_core\"\nimport { NewUserI, UpdatedUserI, UserFiltersI, UserActivationI, UserI, UserRoleName } from \"./types\"\n\nexport default new class {\n all(params={} as UserFiltersI) {\n return ApiCore.getJson<UserI[]>('users', params)\n }\n\n get(id: number){ \n return ApiCore.getJson<UserI>(`users/${id}`)\n }\n\n create(user: NewUserI) {\n return ApiCore.postJson<UserI>('users', user)\n }\n\n update(id: number, user: UpdatedUserI) {\n return ApiCore.putJson<UserI>(`users/${id}`, user)\n }\n\n activate(id: number) {\n return ApiCore.postJson<UserActivationI>(`users/${id}/activate`, {})\n }\n\n deactivate(id: number) {\n return ApiCore.postJson<UserActivationI>(`users/${id}/deactivate`, {})\n }\n}\n","import { ApiCore } from \".\"\nimport { UserPropertyI } from \"./types\"\n\nexport default new class {\n get(property: string) {\n return ApiCore.getJson<UserPropertyI>('user_properties', { property })\n }\n\n set(property: string, propertyValue: string) {\n return ApiCore.postJson<UserPropertyI>('user_properties', {\n property, property_value: propertyValue\n })\n }\n}","import ApiCore from \"./api_core\";\nimport { ObsFiltersI, ObsValueI, ObservationI } from \"./types\";\n\nexport default new class {\n all(params={} as ObsFiltersI) {\n return ApiCore.getJson<ObservationI>('observations', params)\n }\n\n create(encounterID: number, observations: ObsValueI[]) {\n return ApiCore.postJson<ObservationI>('observations', {\n encounter_id: encounterID, observations\n })\n }\n\n update(id: number, params: ObsValueI) {\n return ApiCore.putJson<ObservationI>(`observations/${id}`, params)\n }\n\n void(id: number, reason: string) {\n return ApiCore.void(`observations/${id}`, { reason })\n }\n}\n","import ApiCore from \"./api_core\"\nimport { DistrictI, LocationI, RegionI, TAI, VillageI } from \"./types\"\n\nexport default new class {\n getCurrentFacility() {\n return ApiCore.getJson<LocationI>('locations/current_facility')\n }\n\n getFacilities(params={} as Record<string, string | number>) {\n return ApiCore.getJson<LocationI[]>('locations', params)\n }\n\n getFacility(locationID: number) {\n return ApiCore.getJson<LocationI>(`locations/${locationID}`)\n }\n\n getRegions() { \n return ApiCore.getJson<RegionI[]>('regions') \n }\n\n getDistricts(regionID: number) {\n return ApiCore.getJson<DistrictI[]>('districts', {region_id: regionID, page_size: 1000})\n }\n\n getTraditionalAuthorities(districtID: number, name='') {\n return ApiCore.getJson<TAI[]>('traditional_authorities', { district_id: districtID, name })\n }\n\n getVillages(traditionalAuthorityID: number, name='') {\n return ApiCore.getJson<VillageI[]>('villages', { traditional_authority_id : traditionalAuthorityID, name})\n }\n\n createAddress(locationName: string, type: 'Village' | 'TA', parentLocationID: number) {\n return ApiCore.postJson<Record<'name', string>>('addresses', {\n address_type: type,\n addresses_name: locationName,\n parent_location: parentLocationID\n })\n }\n\n async getDistrictByID(id: number) {\n const res = await ApiCore.getJson<DistrictI>('/districts', {'district_id': id})\n if(res.ok && res.data) return res.data\n throw new Error(res.errorMessage)\n }\n\n async getTraditionalAuthorityById(id: number | string) {\n const res = await ApiCore.getJson<TAI[]>('/traditional_authorities', { 'traditional_authority_id': id}) \n if (res.ok && res.data) return res.data[0];\n throw new Error(res.errorMessage);\n }\n}\n","import { ApiCore } from \".\";\nimport { DemographicSearchParamsI, PatientI } from \"./types\";\n\nexport default new class {\n create(personId: number, programID: number) {\n return ApiCore.postJson<PatientI>('patients', {\n program_id: programID, person_id: personId\n })\n }\n\n searchBy(searchParams: DemographicSearchParamsI){\n return ApiCore.getJson<PatientI[]>('search/patients', searchParams)\n }\n\n searchByNpid(npid: string) {\n return ApiCore.getJson<PatientI[]>('search/patients/by_npid', { npid })\n }\n\n searchByOtherID(idType: number, identifier: string) {\n return ApiCore.getJson<PatientI[]>('search/patients/by_identifier', { \n type_id: idType, identifier\n })\n }\n\n getVisitDates(patientId: number, programID: number, params={} as Record<string, any>) {\n return ApiCore.getJson<string[]>(`patients/${patientId}/visits`, {\n program_id: programID, ...params\n })\n }\n\n get(patientId: number) {\n return ApiCore.getJson<PatientI>(`patients/${patientId}`)\n }\n\n getAll(patientIds: Array<number>) {\n return ApiCore.getJson<Array<PatientI>>('clients', {\n person_ids: patientIds.join(\",\"),\n });\n }\n\n void(patientId: number, reason: string) {\n return ApiCore.void(`patients/${patientId}`, { reason })\n }\n}\n","import ApiCore from \"./api_core\"\nimport { ModifyPersonI, NewPersonI, PersonI, PersonNameI } from \"./types\"\n\nexport default new class {\n all() {\n return ApiCore.getJson<NewPersonI>('people')\n }\n\n get(personId: number) {\n return ApiCore.getJson<PersonI>(`people/${personId}`)\n }\n\n create(person: NewPersonI) { \n return ApiCore.postJson<PersonI>('people', person) \n }\n\n update(personId: number, programID: number, person: ModifyPersonI) { \n return ApiCore.putJson<PersonI>(`people/${personId}`, { ...person, program_id: programID })\n }\n\n getSimilarFamilyNames(name: string){\n return ApiCore.getJson<string[]>('search/family_name', { search_string: name})\n }\n\n getSimilarMiddleNames(name: string) {\n return ApiCore.getJson<string[]>('search/middle_name', { search_string: name})\n }\n\n getSimilarGivenNames(name: string) {\n return ApiCore.getJson<string[]>('search/given_name', { search_string: name})\n }\n\n getNames(personId: number) { \n return ApiCore.getJson<PersonNameI>(`people/${personId}/names`) \n }\n\n void(personId: number, reason: string) {\n return ApiCore.void('people/'+personId, { reason })\n }\n}\n","import ApiCore from \"./api_core\"\nimport { NewLabOrderI } from \"./types\";\n\nexport default new class {\n createOrder(order: NewLabOrderI) { return ApiCore.postJson('lab/orders', order) }\n\n getTestTypes() { return ApiCore.getJson('lab/test_types') }\n\n getTestTypesBySpecimen(specimenType='') {\n return ApiCore.getJson('lab/test_types', { specimen_type: specimenType });\n }\n\n getSpecimens(testName: string) {\n return ApiCore.getJson('lab/specimen_types', { 'test_type': testName });\n }\n\n verifyAccessionNumber(accessionNumber: string) {\n return ApiCore.getJson('lab/accession_number', { accession_number: accessionNumber })\n }\n}","import ApiCore from \"./api_core\"\nimport { NewDrugOrderI } from \"./types\"\n\nexport default new class {\n createOrder(orders: NewDrugOrderI[]) {\n return ApiCore.postJson('drug_orders', orders)\n }\n\n getDrugs(params={} as Record<string, string | number>) {\n return ApiCore.getJson('drugs', params)\n }\n\n getOPDDrugs(params={} as Record<string, string | number>) {\n return ApiCore.getJson('OPD_drugslist', params)\n }\n}","import ApiCore from \"./api_core\"\nimport { EncounterI, EncounterCountParamsI, EncounterFiltersI, UpdateEncounterI, NewEncounterI } from \"./types\"\n\nexport default new class {\n all(params={} as EncounterFiltersI) {\n return ApiCore.getJson<EncounterI[]>('encounters', params)\n }\n\n get(id: number) {\n return ApiCore.getJson<EncounterI>(`encounters/${id}`)\n }\n\n /**\n Generate a report on counts of various encounters\n POST /reports/encounters\n Optional parameters:\n all - Retrieves all encounters not just those created by current user\n */\n count(params: EncounterCountParamsI) {\n return ApiCore.postJson<Record<string, { M?: number; F?: number}>>('reports/encounters', params)\n }\n\n create(encounter: NewEncounterI) {\n return ApiCore.postJson<EncounterI>('encounters', encounter) \n }\n\n update(id: number, encounter: UpdateEncounterI) {\n return ApiCore.putJson<EncounterI>(`encounters/${id}`, encounter)\n }\n\n void(id: number, reason: string) {\n return ApiCore.void(`encounters/${id}`, { reason })\n }\n}\n"],"mappings":"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