@oystehr/sdk 4.3.1 → 4.3.3

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 (111) hide show
  1. package/dist/cjs/client/client.cjs +87 -13
  2. package/dist/cjs/client/client.cjs.map +1 -1
  3. package/dist/cjs/client/client.d.ts +3 -0
  4. package/dist/cjs/config.d.ts +6 -0
  5. package/dist/cjs/index.min.cjs +1 -1
  6. package/dist/cjs/index.min.cjs.map +1 -1
  7. package/dist/cjs/logger.cjs +36 -0
  8. package/dist/cjs/logger.cjs.map +1 -0
  9. package/dist/cjs/logger.d.ts +11 -0
  10. package/dist/cjs/resources/classes/erx.cjs +8 -0
  11. package/dist/cjs/resources/classes/erx.cjs.map +1 -1
  12. package/dist/cjs/resources/classes/erx.d.ts +7 -1
  13. package/dist/cjs/resources/classes/index.cjs +6 -6
  14. package/dist/cjs/resources/classes/index.cjs.map +1 -1
  15. package/dist/cjs/resources/classes/index.d.ts +3 -3
  16. package/dist/cjs/resources/classes/rcm.cjs +29 -14
  17. package/dist/cjs/resources/classes/rcm.cjs.map +1 -1
  18. package/dist/cjs/resources/classes/rcm.d.ts +29 -11
  19. package/dist/cjs/resources/classes/user.cjs +9 -0
  20. package/dist/cjs/resources/classes/user.cjs.map +1 -1
  21. package/dist/cjs/resources/classes/user.d.ts +8 -1
  22. package/dist/cjs/resources/classes/zambda.cjs +1 -1
  23. package/dist/cjs/resources/classes/zambda.cjs.map +1 -1
  24. package/dist/cjs/resources/classes/zambdaLogStream.cjs +1 -1
  25. package/dist/cjs/resources/classes/zambdaLogStream.cjs.map +1 -1
  26. package/dist/cjs/resources/types/ErxGetMedicationHistoryParams.d.ts +3 -0
  27. package/dist/cjs/resources/types/ErxGetMedicationHistoryResponse.d.ts +43 -0
  28. package/dist/cjs/resources/types/ErxGetMedicationResponse.d.ts +1 -1
  29. package/dist/cjs/resources/types/RcmGetPayerParams.d.ts +3 -0
  30. package/dist/cjs/resources/types/RcmGetPayerResponse.d.ts +5 -0
  31. package/dist/cjs/resources/types/RcmListPayersParams.d.ts +5 -0
  32. package/dist/cjs/resources/types/RcmListPayersResponse.d.ts +5 -0
  33. package/dist/cjs/resources/types/RcmSetClaimStatusParams.d.ts +7 -0
  34. package/dist/cjs/resources/types/RcmSetClaimStatusResponse.d.ts +5 -0
  35. package/dist/cjs/resources/types/RcmSubmitClaimParams.d.ts +3 -0
  36. package/dist/cjs/resources/types/RcmSubmitClaimResponse.d.ts +5 -0
  37. package/dist/cjs/resources/types/UserChangePasswordParams.d.ts +7 -0
  38. package/dist/cjs/resources/types/index.d.ts +36 -29
  39. package/dist/esm/client/client.d.ts +3 -0
  40. package/dist/esm/client/client.js +88 -15
  41. package/dist/esm/client/client.js.map +1 -1
  42. package/dist/esm/config.d.ts +6 -0
  43. package/dist/esm/index.min.js +1 -1
  44. package/dist/esm/index.min.js.map +1 -1
  45. package/dist/esm/logger.d.ts +11 -0
  46. package/dist/esm/logger.js +34 -0
  47. package/dist/esm/logger.js.map +1 -0
  48. package/dist/esm/resources/classes/erx.d.ts +7 -1
  49. package/dist/esm/resources/classes/erx.js +8 -0
  50. package/dist/esm/resources/classes/erx.js.map +1 -1
  51. package/dist/esm/resources/classes/index.d.ts +3 -3
  52. package/dist/esm/resources/classes/index.js +6 -6
  53. package/dist/esm/resources/classes/index.js.map +1 -1
  54. package/dist/esm/resources/classes/rcm.d.ts +29 -11
  55. package/dist/esm/resources/classes/rcm.js +29 -14
  56. package/dist/esm/resources/classes/rcm.js.map +1 -1
  57. package/dist/esm/resources/classes/user.d.ts +8 -1
  58. package/dist/esm/resources/classes/user.js +9 -0
  59. package/dist/esm/resources/classes/user.js.map +1 -1
  60. package/dist/esm/resources/classes/zambda.js +1 -1
  61. package/dist/esm/resources/classes/zambda.js.map +1 -1
  62. package/dist/esm/resources/classes/zambdaLogStream.js +1 -1
  63. package/dist/esm/resources/classes/zambdaLogStream.js.map +1 -1
  64. package/dist/esm/resources/types/ErxGetMedicationHistoryParams.d.ts +3 -0
  65. package/dist/esm/resources/types/ErxGetMedicationHistoryResponse.d.ts +43 -0
  66. package/dist/esm/resources/types/ErxGetMedicationResponse.d.ts +1 -1
  67. package/dist/esm/resources/types/RcmGetPayerParams.d.ts +3 -0
  68. package/dist/esm/resources/types/RcmGetPayerResponse.d.ts +5 -0
  69. package/dist/esm/resources/types/RcmListPayersParams.d.ts +5 -0
  70. package/dist/esm/resources/types/RcmListPayersResponse.d.ts +5 -0
  71. package/dist/esm/resources/types/RcmSetClaimStatusParams.d.ts +7 -0
  72. package/dist/esm/resources/types/RcmSetClaimStatusResponse.d.ts +5 -0
  73. package/dist/esm/resources/types/RcmSubmitClaimParams.d.ts +3 -0
  74. package/dist/esm/resources/types/RcmSubmitClaimResponse.d.ts +5 -0
  75. package/dist/esm/resources/types/UserChangePasswordParams.d.ts +7 -0
  76. package/dist/esm/resources/types/index.d.ts +36 -29
  77. package/package.json +2 -2
  78. package/src/client/client.ts +95 -15
  79. package/src/config.ts +6 -0
  80. package/src/logger.ts +36 -0
  81. package/src/resources/classes/erx.ts +17 -0
  82. package/src/resources/classes/index.ts +6 -6
  83. package/src/resources/classes/rcm.ts +53 -23
  84. package/src/resources/classes/user.ts +10 -0
  85. package/src/resources/classes/zambda.ts +1 -1
  86. package/src/resources/classes/zambdaLogStream.ts +1 -1
  87. package/src/resources/types/ErxGetMedicationHistoryParams.ts +5 -0
  88. package/src/resources/types/ErxGetMedicationHistoryResponse.ts +45 -0
  89. package/src/resources/types/ErxGetMedicationResponse.ts +1 -1
  90. package/src/resources/types/RcmGetPayerParams.ts +5 -0
  91. package/src/resources/types/RcmGetPayerResponse.ts +7 -0
  92. package/src/resources/types/RcmListPayersParams.ts +7 -0
  93. package/src/resources/types/RcmListPayersResponse.ts +7 -0
  94. package/src/resources/types/RcmSetClaimStatusParams.ts +9 -0
  95. package/src/resources/types/RcmSetClaimStatusResponse.ts +7 -0
  96. package/src/resources/types/RcmSubmitClaimParams.ts +5 -0
  97. package/src/resources/types/RcmSubmitClaimResponse.ts +7 -0
  98. package/src/resources/types/UserChangePasswordParams.ts +9 -0
  99. package/src/resources/types/index.ts +36 -29
  100. package/dist/cjs/resources/types/RcmSubmitProfessionalClaimParams.d.ts +0 -10
  101. package/dist/cjs/resources/types/RcmSubmitProfessionalClaimResponse.d.ts +0 -5
  102. package/dist/cjs/resources/types/RcmValidateProfessionalClaimParams.d.ts +0 -6
  103. package/dist/cjs/resources/types/RcmValidateProfessionalClaimResponse.d.ts +0 -21
  104. package/dist/esm/resources/types/RcmSubmitProfessionalClaimParams.d.ts +0 -10
  105. package/dist/esm/resources/types/RcmSubmitProfessionalClaimResponse.d.ts +0 -5
  106. package/dist/esm/resources/types/RcmValidateProfessionalClaimParams.d.ts +0 -6
  107. package/dist/esm/resources/types/RcmValidateProfessionalClaimResponse.d.ts +0 -21
  108. package/src/resources/types/RcmSubmitProfessionalClaimParams.ts +0 -13
  109. package/src/resources/types/RcmSubmitProfessionalClaimResponse.ts +0 -7
  110. package/src/resources/types/RcmValidateProfessionalClaimParams.ts +0 -9
  111. package/src/resources/types/RcmValidateProfessionalClaimResponse.ts +0 -23
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Success
3
+ */
4
+ export type ErxGetMedicationHistoryResponse = {
5
+ /**
6
+ * Unique identifier for the medication history item.
7
+ */
8
+ id: number;
9
+ /**
10
+ * The Medi-Span identifier for the medication.
11
+ */
12
+ medicationId: number;
13
+ /**
14
+ * National Drug Code (NDC) identifier of medication.
15
+ */
16
+ ndc: string | null;
17
+ /**
18
+ * RxNorm Concept Unique (RxCUI) identifier of medication.
19
+ */
20
+ rxcui: number | null;
21
+ /**
22
+ * Human readable name of medication.
23
+ */
24
+ name: string;
25
+ route: string | null;
26
+ doseForm: string | null;
27
+ strength: string | null;
28
+ dispenseUnit: string | null;
29
+ isBrandName: boolean;
30
+ genericName: string | null;
31
+ isOtc: boolean;
32
+ refills: string;
33
+ daysSupply: number | null;
34
+ quantity: number;
35
+ classification: string | null;
36
+ schedule: number | null;
37
+ directions: string | null;
38
+ substitutionsAllowed: boolean;
39
+ writtenDate: string;
40
+ effectiveDate: string | null;
41
+ lastFillDate: string | null;
42
+ expirationDate: string | null;
43
+ }[];
@@ -7,7 +7,7 @@ export interface ErxGetMedicationResponse {
7
7
  */
8
8
  id: number;
9
9
  /**
10
- * RxNorm Concept Unique (RxCUI) identifier of medication.
10
+ * National Drug Code (NDC) identifier of medication.
11
11
  */
12
12
  ndc?: string | null;
13
13
  /**
@@ -0,0 +1,3 @@
1
+ export interface RcmGetPayerParams {
2
+ id: string;
3
+ }
@@ -0,0 +1,5 @@
1
+ import { Organization } from 'fhir/r4b';
2
+ /**
3
+ * A valid FHIR Organization object corresponding to the payer.
4
+ */
5
+ export type RcmGetPayerResponse = Organization;
@@ -0,0 +1,5 @@
1
+ export interface RcmListPayersParams {
2
+ name?: string;
3
+ identifier?: string;
4
+ includeInactive?: boolean;
5
+ }
@@ -0,0 +1,5 @@
1
+ import { Organization } from 'fhir/r4b';
2
+ /**
3
+ * List of payers matching the search criteria.
4
+ */
5
+ export type RcmListPayersResponse = Organization[];
@@ -0,0 +1,7 @@
1
+ export interface RcmSetClaimStatusParams {
2
+ /**
3
+ * The new status for the claim.
4
+ */
5
+ status: 'accepted' | 'rejected';
6
+ claimId: string;
7
+ }
@@ -0,0 +1,5 @@
1
+ import { ClaimResponse } from 'fhir/r4b';
2
+ /**
3
+ * A valid FHIR ClaimResponse object will be returned with details on the claim result.
4
+ */
5
+ export type RcmSetClaimStatusResponse = ClaimResponse;
@@ -0,0 +1,3 @@
1
+ export interface RcmSubmitClaimParams {
2
+ claimId: string;
3
+ }
@@ -0,0 +1,5 @@
1
+ import { ClaimResponse } from 'fhir/r4b';
2
+ /**
3
+ * A valid FHIR ClaimResponse object will be returned with details on the claim result.
4
+ */
5
+ export type RcmSubmitClaimResponse = ClaimResponse;
@@ -0,0 +1,7 @@
1
+ export interface UserChangePasswordParams {
2
+ /**
3
+ * The new password for the user.
4
+ */
5
+ password: string;
6
+ id: string;
7
+ }
@@ -8,9 +8,6 @@ export * from './Application';
8
8
  export * from './RoleStub';
9
9
  export * from './RoleListItem';
10
10
  export * from './Role';
11
- export * from './ZambdaSchedule';
12
- export * from './ZambdaFunction';
13
- export * from './ZambdaExecuteResult';
14
11
  export * from './Secret';
15
12
  export * from './SecretListItem';
16
13
  export * from './UserListItem';
@@ -87,12 +84,6 @@ export * from './ChargeStatusResponse';
87
84
  export * from './ProjectGetResponse';
88
85
  export * from './ProjectUpdateParams';
89
86
  export * from './ProjectUpdateResponse';
90
- export * from './RcmEligibilityCheckParams';
91
- export * from './RcmEligibilityCheckResponse';
92
- export * from './RcmValidateProfessionalClaimParams';
93
- export * from './RcmValidateProfessionalClaimResponse';
94
- export * from './RcmSubmitProfessionalClaimParams';
95
- export * from './RcmSubmitProfessionalClaimResponse';
96
87
  export * from './RoleListResponse';
97
88
  export * from './RoleCreateParams';
98
89
  export * from './RoleCreateResponse';
@@ -119,6 +110,7 @@ export * from './UserUpdateResponse';
119
110
  export * from './UserDeleteParams';
120
111
  export * from './UserResetMfaParams';
121
112
  export * from './UserResetPasswordLinkParams';
113
+ export * from './UserChangePasswordParams';
122
114
  export * from './UserInviteParams';
123
115
  export * from './UserInviteResponse';
124
116
  export * from './UserListResponse';
@@ -134,26 +126,6 @@ export * from './Z3ListObjectsResponse';
134
126
  export * from './Z3GetPresignedUrlParams';
135
127
  export * from './Z3GetPresignedUrlResponse';
136
128
  export * from './Z3DeleteObjectParams';
137
- export * from './ZambdaListResponse';
138
- export * from './ZambdaCreateParams';
139
- export * from './ZambdaCreateResponse';
140
- export * from './ZambdaGetParams';
141
- export * from './ZambdaGetResponse';
142
- export * from './ZambdaUpdateParams';
143
- export * from './ZambdaUpdateResponse';
144
- export * from './ZambdaDeleteParams';
145
- export * from './ZambdaExecuteParams';
146
- export * from './ZambdaExecuteResponse';
147
- export * from './ZambdaExecutePublicParams';
148
- export * from './ZambdaExecutePublicResponse';
149
- export * from './ZambdaLogStreamListParams';
150
- export * from './ZambdaLogStreamListResponse';
151
- export * from './ZambdaS3UploadParams';
152
- export * from './ZambdaS3UploadResponse';
153
- export * from './ZambdaLogStreamSearchParams';
154
- export * from './ZambdaLogStreamSearchResponse';
155
- export * from './ZambdaLogStreamGetParams';
156
- export * from './ZambdaLogStreamGetResponse';
157
129
  export * from './FaxOnboardResponse';
158
130
  export * from './FaxGetConfigurationResponse';
159
131
  export * from './FaxSendParams';
@@ -184,6 +156,8 @@ export * from './ErxCheckMedicationInteractionsParams';
184
156
  export * from './ErxCheckMedicationInteractionsResponse';
185
157
  export * from './ErxCheckPrecheckInteractionsParams';
186
158
  export * from './ErxCheckPrecheckInteractionsResponse';
159
+ export * from './ErxGetMedicationHistoryParams';
160
+ export * from './ErxGetMedicationHistoryResponse';
187
161
  export * from './ErxAddPatientPharmacyParams';
188
162
  export * from './ErxCancelPrescriptionParams';
189
163
  export * from './ErxSyncPatientParams';
@@ -199,3 +173,36 @@ export * from './TerminologySearchCptParams';
199
173
  export * from './TerminologySearchCptResponse';
200
174
  export * from './TerminologySearchHcpcsParams';
201
175
  export * from './TerminologySearchHcpcsResponse';
176
+ export * from './ZambdaSchedule';
177
+ export * from './ZambdaFunction';
178
+ export * from './ZambdaExecuteResult';
179
+ export * from './ZambdaListResponse';
180
+ export * from './ZambdaCreateParams';
181
+ export * from './ZambdaCreateResponse';
182
+ export * from './ZambdaGetParams';
183
+ export * from './ZambdaGetResponse';
184
+ export * from './ZambdaUpdateParams';
185
+ export * from './ZambdaUpdateResponse';
186
+ export * from './ZambdaDeleteParams';
187
+ export * from './ZambdaExecuteParams';
188
+ export * from './ZambdaExecuteResponse';
189
+ export * from './ZambdaExecutePublicParams';
190
+ export * from './ZambdaExecutePublicResponse';
191
+ export * from './ZambdaLogStreamListParams';
192
+ export * from './ZambdaLogStreamListResponse';
193
+ export * from './ZambdaS3UploadParams';
194
+ export * from './ZambdaS3UploadResponse';
195
+ export * from './ZambdaLogStreamSearchParams';
196
+ export * from './ZambdaLogStreamSearchResponse';
197
+ export * from './ZambdaLogStreamGetParams';
198
+ export * from './ZambdaLogStreamGetResponse';
199
+ export * from './RcmEligibilityCheckParams';
200
+ export * from './RcmEligibilityCheckResponse';
201
+ export * from './RcmSubmitClaimParams';
202
+ export * from './RcmSubmitClaimResponse';
203
+ export * from './RcmSetClaimStatusParams';
204
+ export * from './RcmSetClaimStatusResponse';
205
+ export * from './RcmListPayersParams';
206
+ export * from './RcmListPayersResponse';
207
+ export * from './RcmGetPayerParams';
208
+ export * from './RcmGetPayerResponse';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oystehr/sdk",
3
- "version": "4.3.1",
3
+ "version": "4.3.3",
4
4
  "description": "Oystehr SDK",
5
5
  "scripts": {
6
6
  "lint": "eslint .",
@@ -14,7 +14,7 @@
14
14
  "parser": "tsx debug-parser.ts",
15
15
  "publish-to-npmjs": "npm run build && npm publish",
16
16
  "publish-to-npmjs-next": "npm run build && npm publish --tag next",
17
- "generate": "ts-node --project scripts/tsconfig.json scripts/generate-sdk-v3 project,fax,lab,erx,terminology src/resources"
17
+ "generate": "ts-node --project scripts/tsconfig.json scripts/generate-sdk-v3 project,fax,lab,erx,terminology,zambda,rcm src/resources"
18
18
  },
19
19
  "engines": {
20
20
  "npm": ">=8.0.0",
@@ -1,6 +1,7 @@
1
- import { v4 as uuidv4 } from 'uuid';
1
+ import { v4 as uuidv4, validate as uuidValidate } from 'uuid';
2
2
  import { OystehrConfig } from '../config';
3
3
  import { OystehrFHIRError, OystehrSdkError } from '../errors';
4
+ import { Logger } from '../logger';
4
5
  import { FhirBundle, FhirResource, OperationOutcome } from '../resources/types';
5
6
 
6
7
  type HttpMethod = 'get' | 'put' | 'post' | 'delete' | 'options' | 'head' | 'patch' | 'trace';
@@ -51,17 +52,24 @@ export type FhirFetcherResponse<T extends FhirData<FhirResource> = any> = T;
51
52
 
52
53
  export class SDKResource {
53
54
  protected readonly config: OystehrConfig;
55
+ protected readonly logger: Logger;
54
56
  constructor(config: OystehrConfig) {
55
57
  this.config = config;
58
+ this.logger = new Logger({
59
+ level: this.config.logLevel,
60
+ });
56
61
  }
57
62
 
58
63
  protected request(path: string, method: string, baseUrlThunk: () => string): FetcherFunction {
59
64
  return async (params: any, request?: InternalClientRequest): Promise<FetcherResponse> => {
60
65
  const configThunk = (): OystehrConfig => this.config;
66
+ const loggerThunk = (): Logger => this.logger;
61
67
  try {
62
- return await fetcher(baseUrlThunk, configThunk, path, method)(params, request);
68
+ // must await here to catch
69
+ return await fetcher(baseUrlThunk, configThunk, loggerThunk, path, method)(params, request);
63
70
  } catch (err: any) {
64
71
  const error = err as { message: string; code: number; cause?: unknown };
72
+ this.logger.error(error.message, { code: error.code, cause: error.cause });
65
73
  throw new OystehrSdkError({ message: error.message, code: error.code, cause: error.cause });
66
74
  }
67
75
  };
@@ -72,8 +80,9 @@ export class SDKResource {
72
80
  try {
73
81
  const baseUrlThunk = (): string => this.config.services?.fhirApiUrl ?? defaultFhirApiUrl;
74
82
  const configThunk = (): OystehrConfig => this.config;
83
+ const loggerThunk = (): Logger => this.logger;
75
84
  // must await here to catch
76
- return await fetcher(baseUrlThunk, configThunk, path, method)(params, request);
85
+ return await fetcher(baseUrlThunk, configThunk, loggerThunk, path, method)(params, request);
77
86
  } catch (err: unknown) {
78
87
  // FHIR API error messages are JSON strings
79
88
  const fullError = err as { message: string | Record<string, any>; code: number; cause?: unknown };
@@ -101,7 +110,13 @@ export type FetcherFunction = (
101
110
  ) => Promise<FetcherResponse>;
102
111
 
103
112
  function isInternalClientRequest(request: Record<string, any>): request is InternalClientRequest {
104
- return 'accessToken' in request;
113
+ return (
114
+ 'accessToken' in request ||
115
+ ('projectId' in request && uuidValidate(request.projectId)) ||
116
+ ('contentType' in request && request.contentType?.split('/').length === 2) ||
117
+ 'requestId' in request ||
118
+ ('ifMatch' in request && request.ifMatch.startsWith('W/"'))
119
+ );
105
120
  }
106
121
 
107
122
  /**
@@ -130,6 +145,7 @@ function parseXmlResponse(xmlString: string): Record<string, unknown> | null {
130
145
  function fetcher(
131
146
  baseUrlThunk: () => string,
132
147
  configThunk: () => OystehrConfig,
148
+ loggerThunk: () => Logger,
133
149
  path: string,
134
150
  methodParam: string
135
151
  ): FetcherFunction {
@@ -141,19 +157,21 @@ function fetcher(
141
157
  // or fetcher(baseUrl, path, method)(params) or fetcher(baseUrl, path, method)(). the types for this are handled by Client<Path, Methods>
142
158
  // and this is the backend implementation behind it. the heuristic we're using is that if the first param is an object with an accessToken
143
159
  // and there is no second param, assume the first one is the request object instead
144
- const providedParams: Record<string, unknown> | [any] =
145
- !!params && !request && !Array.isArray(params) && isInternalClientRequest(params)
146
- ? {}
147
- : (params as Record<string, unknown>) ?? {};
148
- const requestCtx =
149
- !!params && !request && !Array.isArray(params) && isInternalClientRequest(params)
150
- ? (params as InternalClientRequest)
151
- : request;
152
- const method = methodParam.toLowerCase() as HttpMethod;
160
+ // eslint-disable-next-line prefer-const
161
+ let [providedParams, requestCtx] = extractParamsAndRequest(params, request);
162
+ requestCtx ??= {};
163
+ requestCtx.requestId ??= uuidv4();
153
164
  const config = configThunk();
165
+ const logger = loggerThunk();
166
+ const method = methodParam.toLowerCase() as HttpMethod;
167
+ logger.debug('Beginning fetch', {
168
+ method,
169
+ path,
170
+ requestId: requestCtx?.requestId,
171
+ });
154
172
  const fetchImpl = config.fetch ?? fetch;
155
173
  const accessToken = requestCtx?.accessToken ?? config.accessToken;
156
- const projectId = requestCtx?.projectId ?? configThunk().projectId;
174
+ const projectId = requestCtx?.projectId ?? config.projectId;
157
175
  let finalPath = path;
158
176
  let finalParams = providedParams;
159
177
  if (!Array.isArray(providedParams)) {
@@ -161,6 +179,11 @@ function fetcher(
161
179
  finalPath = subbedPath;
162
180
  finalParams = addlParams;
163
181
  }
182
+ logger.debug('Substituted parameters in path', {
183
+ method,
184
+ path,
185
+ requestId: requestCtx?.requestId,
186
+ });
164
187
  finalPath = finalPath.replace(/^\//, ''); // remove leading slash
165
188
  const baseUrlEvaluated = baseUrlThunk();
166
189
  const fullBaseUrl = baseUrlEvaluated.endsWith('/') ? baseUrlEvaluated : baseUrlEvaluated + '/';
@@ -185,6 +208,11 @@ function fetcher(
185
208
  body = '{}';
186
209
  }
187
210
  }
211
+ logger.debug('Prepared request body', {
212
+ method,
213
+ path,
214
+ requestId: requestCtx?.requestId,
215
+ });
188
216
 
189
217
  const headers: Record<string, string> = Object.assign(
190
218
  projectId
@@ -198,7 +226,7 @@ function fetcher(
198
226
  },
199
227
  accessToken ? { Authorization: `Bearer ${accessToken}` } : {},
200
228
  requestCtx?.ifMatch ? { 'If-Match': requestCtx.ifMatch } : {},
201
- { 'x-oystehr-request-id': requestCtx?.requestId ?? uuidv4() }
229
+ { 'x-oystehr-request-id': requestCtx?.requestId }
202
230
  );
203
231
  const retryConfig: ConstructedRetryConfig = {
204
232
  retries: config.retry?.retries ?? 3,
@@ -210,6 +238,12 @@ function fetcher(
210
238
  };
211
239
  retryConfig.retryOn.push(...STATUS_CODES_TO_RETRY);
212
240
  return retry(async () => {
241
+ logger.info('Request start', {
242
+ method,
243
+ url,
244
+ requestId: requestCtx?.requestId,
245
+ });
246
+ const now = Date.now();
213
247
  const response = await fetchImpl(
214
248
  new Request(url, {
215
249
  method: method.toUpperCase(),
@@ -217,6 +251,12 @@ function fetcher(
217
251
  headers,
218
252
  })
219
253
  );
254
+ logger.info('Request end', {
255
+ method,
256
+ url,
257
+ duration: Date.now() - now,
258
+ requestId: requestCtx?.requestId,
259
+ });
220
260
  const responseBody = response.body ? await response.text() : null;
221
261
  let responseJson: Record<string, unknown> | null;
222
262
  const contentType = response.headers.get('content-type');
@@ -225,10 +265,30 @@ function fetcher(
225
265
  responseBody &&
226
266
  (contentType?.includes('application/json') || contentType?.includes('application/fhir+json'))
227
267
  ) {
268
+ logger.time('Deserialized JSON response', {
269
+ method,
270
+ url,
271
+ requestId: requestCtx?.requestId,
272
+ });
228
273
  responseJson = JSON.parse(responseBody);
274
+ logger.timeEnd('Deserialized JSON response', {
275
+ method,
276
+ url,
277
+ requestId: requestCtx?.requestId,
278
+ });
229
279
  } else if (responseBody && (contentType?.includes('application/xml') || contentType?.includes('text/xml'))) {
230
280
  // Parse XML response into { status, output } structure
281
+ logger.time('Deserialized XML response', {
282
+ method,
283
+ url,
284
+ requestId: requestCtx?.requestId,
285
+ });
231
286
  responseJson = parseXmlResponse(responseBody);
287
+ logger.timeEnd('Deserialized XML response', {
288
+ method,
289
+ url,
290
+ requestId: requestCtx?.requestId,
291
+ });
232
292
  } else {
233
293
  responseJson = null;
234
294
  }
@@ -236,6 +296,11 @@ function fetcher(
236
296
  // ignore JSON.parse errors
237
297
  responseJson = null;
238
298
  }
299
+ logger.debug('Deserialized response', {
300
+ method,
301
+ url,
302
+ requestId: requestCtx?.requestId,
303
+ });
239
304
  const isError = !response.ok || response.status >= 400;
240
305
  if (isError) {
241
306
  const errObj = {
@@ -349,3 +414,18 @@ export function addParamsToSearch(params: Record<string, unknown>, search: URLSe
349
414
  search.append(key, value as string);
350
415
  }
351
416
  }
417
+
418
+ export function extractParamsAndRequest(
419
+ params?: Record<string, unknown> | [any] | InternalClientRequest,
420
+ request?: InternalClientRequest
421
+ ): [Record<string, unknown>, InternalClientRequest | undefined] {
422
+ const providedParams: Record<string, unknown> | [any] =
423
+ !!params && !request && !Array.isArray(params) && isInternalClientRequest(params)
424
+ ? {}
425
+ : (params as Record<string, unknown>) ?? {};
426
+ const requestCtx =
427
+ !!params && !request && !Array.isArray(params) && isInternalClientRequest(params)
428
+ ? (params as InternalClientRequest)
429
+ : request;
430
+ return [providedParams, requestCtx];
431
+ }
package/src/config.ts CHANGED
@@ -10,6 +10,10 @@ export interface OystehrConfig {
10
10
  * Optional Oystehr Project ID. Required for developer accessTokens.
11
11
  */
12
12
  projectId?: string;
13
+ /**
14
+ * Optional log level for the SDK logger. Possible values are 'error', 'info', and 'debug'.
15
+ */
16
+ logLevel?: 'error' | 'info' | 'debug';
13
17
  fhirApiUrl?: string;
14
18
  projectApiUrl?: string;
15
19
  services?: {
@@ -18,7 +22,9 @@ export interface OystehrConfig {
18
22
  fhirApiUrl?: string;
19
23
  labApiUrl?: string;
20
24
  projectApiUrl?: string;
25
+ rcmApiUrl?: string;
21
26
  terminologyApiUrl?: string;
27
+ zambdaApiUrl?: string;
22
28
  };
23
29
  /**
24
30
  * Optionally provide a custom fetch implementation. This must conform to the
package/src/logger.ts ADDED
@@ -0,0 +1,36 @@
1
+ export class Logger {
2
+ _level?: 'error' | 'info' | 'debug';
3
+ constructor({ level }: { level?: 'error' | 'info' | 'debug' }) {
4
+ this._level = level;
5
+ }
6
+
7
+ error(message: string, extra: Record<string, any> = {}): void {
8
+ if (this._level && ['error', 'info', 'debug'].includes(this._level)) {
9
+ console.error(JSON.stringify({ message, ...extra }));
10
+ }
11
+ }
12
+
13
+ info(message: string, extra: Record<string, any> = {}): void {
14
+ if (this._level && ['info', 'debug'].includes(this._level)) {
15
+ console.info(JSON.stringify({ message, ...extra }));
16
+ }
17
+ }
18
+
19
+ debug(message: string, extra: Record<string, any> = {}): void {
20
+ if (this._level && ['debug'].includes(this._level)) {
21
+ console.debug(JSON.stringify({ message, ...extra }));
22
+ }
23
+ }
24
+
25
+ time(message: string, extra: Record<string, any> = {}): void {
26
+ if (this._level && ['debug'].includes(this._level)) {
27
+ console.time(JSON.stringify({ message, ...extra }));
28
+ }
29
+ }
30
+
31
+ timeEnd(message: string, extra: Record<string, any> = {}): void {
32
+ if (this._level && ['debug'].includes(this._level)) {
33
+ console.timeEnd(JSON.stringify({ message, ...extra }));
34
+ }
35
+ }
36
+ }
@@ -15,6 +15,8 @@ import {
15
15
  ErxConnectPractitionerResponse,
16
16
  ErxEnrollPractitionerParams,
17
17
  ErxGetConfigurationResponse,
18
+ ErxGetMedicationHistoryParams,
19
+ ErxGetMedicationHistoryResponse,
18
20
  ErxGetMedicationParams,
19
21
  ErxGetMedicationResponse,
20
22
  ErxSearchAllergensParams,
@@ -135,6 +137,21 @@ export class Erx extends SDKResource {
135
137
  this.#baseUrlThunk.bind(this)
136
138
  )(params, request);
137
139
  }
140
+ /**
141
+ * Retrieve claims-based medication history for a patient. This endpoint requires the patient to be synced with the upstream eRx provider.
142
+ * Action: `eRx:GetMedicationHistory`
143
+ * Access Policy Resource: `eRx:Patient`
144
+ */
145
+ getMedicationHistory(
146
+ params: ErxGetMedicationHistoryParams,
147
+ request?: OystehrClientRequest
148
+ ): Promise<ErxGetMedicationHistoryResponse> {
149
+ return this.request(
150
+ '/patient/{patientId}/medication-history',
151
+ 'get',
152
+ this.#baseUrlThunk.bind(this)
153
+ )(params, request);
154
+ }
138
155
  /**
139
156
  * Adds pharmacy for a patient with the upstream eRx provider, setting it as primary if specified.
140
157
  * Action: `eRx:AddPatientPharmacy`
@@ -36,19 +36,19 @@ export class Oystehr {
36
36
  readonly paymentMethod: PaymentMethod;
37
37
  readonly charge: Charge;
38
38
  readonly project: Project;
39
- readonly rcm: Rcm;
40
39
  readonly role: Role;
41
40
  readonly secret: Secret;
42
41
  readonly telemed: Telemed;
43
42
  readonly user: User;
44
43
  readonly version: Version;
45
44
  readonly z3: Z3;
46
- readonly zambda: Zambda;
47
- readonly zambdaLogStream: ZambdaLogStream;
48
45
  readonly fax: Fax;
49
46
  readonly lab: Lab;
50
47
  readonly erx: Erx;
51
48
  readonly terminology: Terminology;
49
+ readonly zambda: Zambda;
50
+ readonly zambdaLogStream: ZambdaLogStream;
51
+ readonly rcm: Rcm;
52
52
  readonly fhir: Fhir;
53
53
  constructor(config: OystehrConfig) {
54
54
  this.config = config;
@@ -64,19 +64,19 @@ export class Oystehr {
64
64
  this.paymentMethod = new PaymentMethod(config);
65
65
  this.charge = new Charge(config);
66
66
  this.project = new Project(config);
67
- this.rcm = new Rcm(config);
68
67
  this.role = new Role(config);
69
68
  this.secret = new Secret(config);
70
69
  this.telemed = new Telemed(config);
71
70
  this.user = new User(config);
72
71
  this.version = new Version(config);
73
72
  this.z3 = new Z3(config);
74
- this.zambda = new Zambda(config);
75
- this.zambdaLogStream = new ZambdaLogStream(config);
76
73
  this.fax = new Fax(config);
77
74
  this.lab = new Lab(config);
78
75
  this.erx = new Erx(config);
79
76
  this.terminology = new Terminology(config);
77
+ this.zambda = new Zambda(config);
78
+ this.zambdaLogStream = new ZambdaLogStream(config);
79
+ this.rcm = new Rcm(config);
80
80
  this.fhir = new Fhir(config);
81
81
  }
82
82
  }