oro-sdk-apis 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +35 -0
  3. package/dist/index.d.ts +27 -0
  4. package/dist/index.js +8 -0
  5. package/dist/models/consult.d.ts +102 -0
  6. package/dist/models/diagnosis.d.ts +122 -0
  7. package/dist/models/error.d.ts +12 -0
  8. package/dist/models/guard.d.ts +119 -0
  9. package/dist/models/index.d.ts +8 -0
  10. package/dist/models/practice.d.ts +353 -0
  11. package/dist/models/shared.d.ts +8 -0
  12. package/dist/models/vault.d.ts +124 -0
  13. package/dist/models/workflow.d.ts +106 -0
  14. package/dist/oro-sdk-apis.cjs.development.js +3019 -0
  15. package/dist/oro-sdk-apis.cjs.development.js.map +1 -0
  16. package/dist/oro-sdk-apis.cjs.production.min.js +2 -0
  17. package/dist/oro-sdk-apis.cjs.production.min.js.map +1 -0
  18. package/dist/oro-sdk-apis.esm.js +3051 -0
  19. package/dist/oro-sdk-apis.esm.js.map +1 -0
  20. package/dist/services/api.d.ts +11 -0
  21. package/dist/services/axios.d.ts +14 -0
  22. package/dist/services/consult.d.ts +54 -0
  23. package/dist/services/diagnosis.d.ts +44 -0
  24. package/dist/services/guard.d.ts +92 -0
  25. package/dist/services/index.d.ts +9 -0
  26. package/dist/services/practice.d.ts +98 -0
  27. package/dist/services/teller.d.ts +9 -0
  28. package/dist/services/vault.d.ts +54 -0
  29. package/dist/services/workflow.d.ts +21 -0
  30. package/package.json +62 -0
  31. package/src/index.ts +56 -0
  32. package/src/models/consult.ts +110 -0
  33. package/src/models/diagnosis.ts +141 -0
  34. package/src/models/error.ts +6 -0
  35. package/src/models/guard.ts +136 -0
  36. package/src/models/index.ts +8 -0
  37. package/src/models/practice.ts +411 -0
  38. package/src/models/shared.ts +6 -0
  39. package/src/models/vault.ts +158 -0
  40. package/src/models/workflow.ts +142 -0
  41. package/src/services/api.ts +77 -0
  42. package/src/services/axios.ts +91 -0
  43. package/src/services/consult.ts +264 -0
  44. package/src/services/diagnosis.ts +144 -0
  45. package/src/services/guard.ts +228 -0
  46. package/src/services/index.ts +9 -0
  47. package/src/services/practice.ts +430 -0
  48. package/src/services/teller.ts +39 -0
  49. package/src/services/vault.ts +178 -0
  50. package/src/services/workflow.ts +36 -0
@@ -0,0 +1,142 @@
1
+ export interface IndexedData<T> {
2
+ [key: string]: T
3
+ }
4
+
5
+ export type SelectedAnswerData = string | string[]
6
+ export type SelectedAnswersData = IndexedData<SelectedAnswerData>[]
7
+
8
+ export interface ChoiceInputData {
9
+ text: string
10
+ className?: string
11
+ order?: number
12
+ }
13
+
14
+ export interface RadioInputIconOptionsData {
15
+ variant: 'icon'
16
+ icon: string
17
+ }
18
+
19
+ export interface RadioInputData extends ChoiceInputData {
20
+ options?: RadioInputIconOptionsData
21
+ }
22
+
23
+ export interface RadioCardInputData extends RadioInputData {
24
+ bodyText: string
25
+ }
26
+ export interface EntryData {
27
+ id?: number
28
+ label?: string
29
+ summaryLabel?: string
30
+ summaryHidden?: boolean
31
+ className?: string
32
+ triggers?: string[]
33
+ }
34
+
35
+ export enum MetadataCategory { //these are generic metadata categories
36
+ ChildPersonal = 'ChildPersonal',
37
+ Consultation = 'Consultation',
38
+ DataRetrieval = 'DataRetrieval',
39
+ Followup = 'Followup',
40
+ Recovery = 'Recovery',
41
+ Medical = 'Medical',
42
+ OtherPersonal = 'OtherPersonal',
43
+ Personal = 'Personal',
44
+ Preference = 'Preference',
45
+ Prescription = 'Prescription',
46
+ Raw = 'Raw',
47
+ }
48
+
49
+ export interface GenericQuestionData<T, A = IndexedData<ChoiceInputData>>
50
+ extends EntryData {
51
+ kind: T
52
+ metaCategory: MetadataCategory
53
+ answers?: A
54
+ formValidation?: any[] // use yup-ast expressions
55
+ placeholder?: string
56
+ defaultValue?: any
57
+ value?: string
58
+ }
59
+
60
+ export interface GroupedGenericQuestionData<
61
+ T,
62
+ A = IndexedData<ChoiceInputData>
63
+ > extends GenericQuestionData<T, A> {
64
+ inline?: boolean
65
+ inlineLabel?: boolean
66
+ order?: number
67
+ }
68
+
69
+ export type QuestionData =
70
+ | GenericQuestionData<'title' | 'paragraph' | 'checkbox', void>
71
+ | GenericQuestionData<
72
+ | 'text'
73
+ | 'date'
74
+ | 'number'
75
+ | 'images'
76
+ | 'images-alias'
77
+ | 'body-parts'
78
+ | 'pharmacy-picker'
79
+ | 'place-address'
80
+ >
81
+ | GenericQuestionData<
82
+ 'checkbox-group' | 'select' | 'multiple',
83
+ IndexedData<ChoiceInputData>
84
+ >
85
+ | GroupedGenericQuestionData<'radio', IndexedData<RadioInputData>>
86
+ | GroupedGenericQuestionData<'radio-card', IndexedData<RadioCardInputData>>
87
+
88
+ export interface FieldData {
89
+ type: 'field'
90
+ className?: string
91
+ id: string
92
+ }
93
+
94
+ export interface FieldGroupData {
95
+ type: 'field-group'
96
+ className?: string
97
+ fieldsAndGroups: (FieldData | FieldGroupData)[]
98
+ name?: string
99
+ inline?: boolean
100
+ fullWidth?: boolean
101
+ }
102
+
103
+ export interface WorkflowPageData {
104
+ className?: string
105
+ groups?: FieldGroupData[]
106
+ highlightMsg?: string
107
+ questions: IndexedData<QuestionData>
108
+ title?: string
109
+ triggers?: string[]
110
+ }
111
+
112
+ export interface WorkflowData {
113
+ createdAt: string
114
+ culDeSacs: EntryData[]
115
+ id: string
116
+ locale?: string
117
+ pages: WorkflowPageData[]
118
+ summaryImageFieldName?: string // this field is used to show the consult summary image
119
+ summarySymptomsFieldName?: string // this field is used to show the consult summary symptoms
120
+ selectedAnswers?: SelectedAnswersData
121
+ }
122
+
123
+ /**
124
+ * This interface describes a workflow prepared and ready to be sent to vault
125
+ */
126
+ export interface WorkflowUploadedImage {
127
+ idbId?: string
128
+ name: string
129
+ imageData?: string
130
+ }
131
+ export interface PopulatedWorkflowField {
132
+ answer: SelectedAnswerData | WorkflowUploadedImage[] // Actual answer from the workflow
133
+ displayedAnswer?: any // This answer is to be used only when it's impossible to get data from workflow
134
+ kind: string // If we don't store question. We will need that field to at least know the field type
135
+ }
136
+
137
+ export interface PopulatedWorkflowData {
138
+ workflowId: string // The workflow id to refer
139
+ workflowCreatedAt: string // The workflow version
140
+ locale?: string
141
+ fields: Record<string, PopulatedWorkflowField> // key corresponds to the QuestionData key in the workflow
142
+ }
@@ -0,0 +1,77 @@
1
+ import type { AxiosRequestConfig } from 'axios'
2
+ import createAuthRefreshInterceptor from 'axios-auth-refresh'
3
+ import { AuthRefreshFunc, Tokens } from '../models'
4
+ import { AxiosService } from './axios'
5
+ import { GuardRequestConfig } from './guard'
6
+
7
+
8
+ export class APIService extends AxiosService {
9
+ private authRefreshFn?: AuthRefreshFunc
10
+
11
+ constructor(
12
+ config?: AxiosRequestConfig,
13
+ private tokenRefreshFailureCallback?: (err: Error) => void
14
+ ) {
15
+ super(config)
16
+ const self = this
17
+
18
+ this.axios.interceptors.request.use(
19
+ config => {
20
+ const token = (config as GuardRequestConfig).useRefreshToken
21
+ ? self.getTokens().refreshToken
22
+ : self.getTokens().accessToken
23
+
24
+ config.headers = {
25
+ ...config.headers,
26
+ Authorization: `Bearer ${token}`,
27
+ }
28
+ return config;
29
+ },
30
+ error => {
31
+ Promise.reject(error)
32
+ }
33
+ );
34
+
35
+ createAuthRefreshInterceptor(this.axios, async function (failedRequest) {
36
+ if (self.authRefreshFn) {
37
+ try {
38
+ let tokenResp = await self.authRefreshFn(self.getTokens().refreshToken)
39
+ self.setTokens({
40
+ accessToken: tokenResp.accessToken,
41
+ refreshToken: tokenResp.refreshToken
42
+ })
43
+ failedRequest.response.config.headers['Authorization'] = `Bearer ${self.getTokens().accessToken}`
44
+ return Promise.resolve()
45
+
46
+ } catch (e) {
47
+ console.error('an error occured while refreshing tokens (notifying callback)', e)
48
+ if (self.tokenRefreshFailureCallback)
49
+ self.tokenRefreshFailureCallback(failedRequest)
50
+ return Promise.resolve() // We keep it like that. Otherwise, it seems to break the api service will it is not needed
51
+ // return Promise.reject(e)
52
+ }
53
+ }
54
+ console.error('The request could not refresh the token (authRefreshFn was not set)', failedRequest)
55
+ return Promise.resolve() // We keep it like that. Otherwise, it seems to break the api service will it is not needed
56
+ // return Promise.reject(failedRequest)
57
+
58
+ }, { statusCodes: [401, 403] })
59
+ }
60
+
61
+ public setAuthRefreshFn(fn: AuthRefreshFunc) {
62
+ this.authRefreshFn = fn
63
+ }
64
+
65
+ public setTokens(tokens: Tokens) {
66
+ localStorage.setItem('tokens', JSON.stringify(tokens))
67
+ }
68
+
69
+ public getTokens(): Tokens {
70
+ let tokens : Tokens = {}
71
+ const item = localStorage.getItem('tokens')
72
+ if (item) {
73
+ tokens = JSON.parse(item)
74
+ }
75
+ return tokens
76
+ }
77
+ }
@@ -0,0 +1,91 @@
1
+ import type { AxiosRequestConfig } from 'axios'
2
+ import axios, { AxiosInstance } from 'axios'
3
+
4
+
5
+ export class AxiosService {
6
+ protected axios: AxiosInstance
7
+
8
+ constructor(
9
+ config?: AxiosRequestConfig
10
+ ) {
11
+ if (!config) config = {}
12
+
13
+ this.axios = axios.create(config)
14
+ }
15
+
16
+ protected async apiRequest(config: AxiosRequestConfig, url: string, data?: any) {
17
+ if (!config.headers) config.headers = {}
18
+
19
+ config.headers['Content-Type'] = 'application/json'
20
+
21
+ return this.axios({
22
+ ...config,
23
+ url,
24
+ data: data,
25
+ }).then((res) => {
26
+ return res.data
27
+ })
28
+ }
29
+
30
+ protected async apiRequestHeader(config: AxiosRequestConfig, url: string, headerToRetrieve?: string, data?: any,) {
31
+ if (!config.headers) config.headers = {}
32
+
33
+ config.headers['Content-Type'] = 'application/json'
34
+
35
+ return this.axios({
36
+ ...config,
37
+ url,
38
+ data: data,
39
+ }).then((res) => {
40
+ if (headerToRetrieve) {
41
+ return res.headers[headerToRetrieve] ?? res.headers[headerToRetrieve.toLowerCase()]
42
+ }
43
+
44
+ return res.headers
45
+ })
46
+ }
47
+
48
+ public get<T = any>(url: string, config?: AxiosRequestConfig): Promise<T> {
49
+ return this.apiRequest({ ...config, method: 'get' }, url)
50
+ }
51
+
52
+ public deleteRequest<T = any>(
53
+ url: string,
54
+ config?: AxiosRequestConfig
55
+ ): Promise<T> {
56
+ return this.apiRequest({ ...config, method: 'delete' }, url)
57
+ }
58
+
59
+ public post<T = any>(
60
+ url: string,
61
+ data?: any,
62
+ config?: AxiosRequestConfig
63
+ ): Promise<T> {
64
+ return this.apiRequest({ ...config, method: 'post' }, url, data)
65
+ }
66
+
67
+ public put<T = any>(
68
+ url: string,
69
+ data: any,
70
+ config?: AxiosRequestConfig
71
+ ): Promise<T> {
72
+ return this.apiRequest({ ...config, method: 'put' }, url, data)
73
+ }
74
+
75
+ public patch<T = any>(
76
+ url: string,
77
+ data: any,
78
+ config?: AxiosRequestConfig
79
+ ): Promise<T> {
80
+ return this.apiRequest({ ...config, method: 'patch' }, url, data)
81
+ }
82
+
83
+ public head<T = any>(
84
+ url: string,
85
+ config?: AxiosRequestConfig,
86
+ headerToRetrieve?: string,
87
+ data?: any
88
+ ): Promise<T> {
89
+ return this.apiRequestHeader({ ...config, method: 'head' }, url, headerToRetrieve, data)
90
+ }
91
+ }
@@ -0,0 +1,264 @@
1
+ import { APIService } from './api'
2
+ import {
3
+ Uuid,
4
+ Consult,
5
+ ConsultRequest,
6
+ MedicalStatus,
7
+ ConsultTransmission,
8
+ TransmissionKind,
9
+ TransmissionStatus,
10
+ } from '../models'
11
+
12
+ export class ConsultService {
13
+ constructor(private api: APIService, private baseURL: string) {}
14
+
15
+ public consultCreate(c: ConsultRequest): Promise<Consult> {
16
+ return this.api.post<Consult>(`${this.baseURL}/v1/consults`, c)
17
+ }
18
+
19
+ /**
20
+ * This function returns the number of consults using parameters
21
+ * @param uuidPractice the practice uuid
22
+ * @param uuidRequester the requester uuid
23
+ * @param statusesMedical an array containing MedicalStatus to include
24
+ * @param statusesExclude an array containing MedicalStatus to exclude
25
+ * @param shortId a shortId matcher (will match all consult with a shortId starting with this `shortId`)
26
+ * @param columnToSortTo the list of columns separated by commas, to sort to (in order of sorting)
27
+ * @param orderToSortTo the type of sorting to do ('asc' for ascending or 'desc' for descending)
28
+ * @param perPage the number of item to retrieve per "page"
29
+ * @param indexPage the actual index of the page to retrieve (0 based: 0 is the first items)
30
+ * @param filterAssignedDoctor the uuid of the doctor for which to filter with
31
+ * @param filterCurrentPractitioner the uuid of the current assistant assigned to filter with
32
+ * @param filterIsoLocality the of isoLocality to filter with
33
+ * @returns a number of consult
34
+ */
35
+ public countConsults(
36
+ uuidPractice?: Uuid,
37
+ uuidRequester?: Uuid,
38
+ statusesMedical?: MedicalStatus[],
39
+ statusesExclude?: MedicalStatus[],
40
+ shortId?: string,
41
+ columnToSortTo?: string[],
42
+ orderToSortTo?: string[],
43
+ perPage?: number,
44
+ indexPage?: number,
45
+ filterAssignedDoctor?: string,
46
+ filterCurrentPractitioner?: string,
47
+ filterIsoLocality?: string[]
48
+ ): Promise<number> {
49
+ return this.api
50
+ .head<any>(
51
+ `${this.baseURL}/v1/consults`,
52
+ {
53
+ params: {
54
+ uuidPractice,
55
+ uuidRequester,
56
+ statusesMedical,
57
+ statusesExclude,
58
+ shortId,
59
+ perPage,
60
+ page: indexPage,
61
+ sortColumns: columnToSortTo,
62
+ orderColumns: orderToSortTo,
63
+ filterAssignedDoctor,
64
+ filterCurrentPractitioner,
65
+ filterIsoLocality,
66
+ },
67
+ },
68
+ 'Content-Range'
69
+ )
70
+ .then((resContentRange) => {
71
+ if (
72
+ !resContentRange ||
73
+ (typeof resContentRange !== 'string' &&
74
+ typeof resContentRange !== 'number')
75
+ ) {
76
+ return 0
77
+ }
78
+
79
+ if (typeof resContentRange === 'number') {
80
+ return resContentRange
81
+ }
82
+
83
+ return parseInt(resContentRange)
84
+ })
85
+ }
86
+
87
+ /**
88
+ * This function get consults using parameters
89
+ * @param uuidPractice the practice uuid
90
+ * @param uuidRequester the requester uuid
91
+ * @param statusesMedical an array containing MedicalStatus to include
92
+ * @param statusesExclude an array containing MedicalStatus to exclude
93
+ * @param shortId a shortId matcher (will match all consult with a shortId starting with this `shortId`)
94
+ * @param columnToSortTo the list of columns separated by commas, to sort to (in order of sorting)
95
+ * @param orderToSortTo the type of sorting to do ('asc' for ascending or 'desc' for descending)
96
+ * @param perPage the number of item to retrieve per "page"
97
+ * @param indexPage the actual index of the page to retrieve (0 based: 0 is the first items)
98
+ * @param filterAssignedDoctor the uuid of the doctor for which to filter with
99
+ * @param filterCurrentPractitioner the uuid of the current assistant assigned to filter with
100
+ * @param filterIsoLocality the of isoLocality to filter with
101
+ * @returns a list of consult
102
+ */
103
+ public getConsults(
104
+ uuidPractice?: Uuid,
105
+ uuidRequester?: Uuid,
106
+ statusesMedical?: MedicalStatus[],
107
+ statusesExclude?: MedicalStatus[],
108
+ shortId?: string,
109
+ columnToSortTo?: string[],
110
+ orderToSortTo?: string[],
111
+ perPage?: number,
112
+ indexPage?: number,
113
+ filterAssignedDoctor?: string,
114
+ filterCurrentPractitioner?: string,
115
+ filterIsoLocality?: string[]
116
+ ): Promise<Consult[]> {
117
+ return this.api.get<Consult[]>(`${this.baseURL}/v1/consults`, {
118
+ params: {
119
+ uuidPractice,
120
+ uuidRequester,
121
+ statusesMedical,
122
+ statusesExclude,
123
+ shortId,
124
+ perPage,
125
+ page: indexPage,
126
+ sortColumns: columnToSortTo,
127
+ orderColumns: orderToSortTo,
128
+ filterAssignedDoctor,
129
+ filterCurrentPractitioner,
130
+ filterIsoLocality,
131
+ },
132
+ })
133
+ }
134
+
135
+ public getConsultByUUID(
136
+ uuidConsult: Uuid,
137
+ uuidPractice?: Uuid
138
+ ): Promise<Consult> {
139
+ return this.api.get<Consult>(
140
+ `${this.baseURL}/v1/consults/${uuidConsult}`,
141
+ { params: { uuidPractice } }
142
+ )
143
+ }
144
+
145
+ public updateConsultByUUID(
146
+ uuidConsult: Uuid,
147
+ consult: {
148
+ statusMedical?: MedicalStatus
149
+ uuidAssignedDoctor?: Uuid
150
+ neverExpires?: boolean
151
+ },
152
+ uuidPractice?: Uuid,
153
+ uuidRequester?: Uuid
154
+ ): Promise<Consult> {
155
+ return this.api.put<Consult>(
156
+ `${this.baseURL}/v1/consults/${uuidConsult}`,
157
+ consult,
158
+ {
159
+ params: {
160
+ uuidPractice,
161
+ uuidRequester,
162
+ },
163
+ }
164
+ )
165
+ }
166
+
167
+ public getConsultFaxStatuses(
168
+ uuidConsult: string
169
+ ): Promise<ConsultTransmission[]> {
170
+ return this.api.get<ConsultTransmission[]>(
171
+ `${this.baseURL}/v1/consults/${uuidConsult}/transmissions`,
172
+ {
173
+ params: {
174
+ kind: TransmissionKind.Fax,
175
+ },
176
+ }
177
+ )
178
+ }
179
+
180
+ public postConsultTransmission(
181
+ uuidConsult: string,
182
+ nameDriver: string = 'Documo',
183
+ addressOrPhoneToSendTo?: string,
184
+ file?: File,
185
+ nameReceiver?: string,
186
+ txtTransmissionTitle?: string,
187
+ txtTransmissionNotes?: string
188
+ // numTry ?: number,
189
+ // delay ?: number,
190
+ ): Promise<ConsultTransmission> {
191
+ let data = new FormData()
192
+
193
+ data.append('nameDriverReceiver', nameDriver)
194
+ if (addressOrPhoneToSendTo) {
195
+ data.append('addressReceiver', addressOrPhoneToSendTo)
196
+ }
197
+ if (file) {
198
+ data.append('file', file)
199
+ }
200
+ if (nameReceiver) {
201
+ data.append('nameReceiver', nameReceiver)
202
+ }
203
+ if (txtTransmissionTitle) {
204
+ data.append('txtTransmissionTitle', txtTransmissionTitle)
205
+ }
206
+ if (txtTransmissionNotes) {
207
+ data.append('txtTransmissionNotes', txtTransmissionNotes)
208
+ }
209
+
210
+ return this.api.post<ConsultTransmission>(
211
+ `${this.baseURL}/v1/consults/${uuidConsult}/transmissions`,
212
+ data,
213
+ {
214
+ headers: { 'Content-Type': 'multipart/form-data;' },
215
+ }
216
+ )
217
+ }
218
+
219
+ public postConsultFax(
220
+ uuidConsult: string,
221
+ addressReceiver: string,
222
+ file: File
223
+ ): Promise<ConsultTransmission> {
224
+ return this.postConsultTransmission(
225
+ uuidConsult,
226
+ 'Documo',
227
+ addressReceiver,
228
+ file
229
+ )
230
+ }
231
+
232
+ public postConsultEmail(
233
+ uuidConsult: string,
234
+ file: File
235
+ ): Promise<ConsultTransmission> {
236
+ return this.postConsultTransmission(
237
+ uuidConsult,
238
+ 'Pharmacierge',
239
+ undefined,
240
+ file
241
+ )
242
+ }
243
+
244
+ public retryConsultFax(
245
+ uuidConsult: string,
246
+ transmissionId: string
247
+ ): Promise<ConsultTransmission> {
248
+ return this.api.put<ConsultTransmission>(
249
+ `${this.baseURL}/v1/consults/${uuidConsult}/transmissions/${transmissionId}`,
250
+ { status: TransmissionStatus.Retrying }
251
+ )
252
+ }
253
+
254
+ public updateConsultTransmissionStatus(
255
+ transmissionId: string,
256
+ uuidConsult: string,
257
+ newStatus: TransmissionStatus
258
+ ): Promise<ConsultTransmission> {
259
+ return this.api.put<ConsultTransmission>(
260
+ `${this.baseURL}/v1/consults/${uuidConsult}/transmissions/${transmissionId}`,
261
+ { status: newStatus }
262
+ )
263
+ }
264
+ }