@oystehr/sdk 4.3.3 → 4.3.5

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 (40) hide show
  1. package/README.md +1 -1
  2. package/dist/cjs/config.d.ts +15 -0
  3. package/dist/cjs/index.min.cjs +1 -1
  4. package/dist/cjs/index.min.cjs.map +1 -1
  5. package/dist/cjs/resources/classes/fhir-ext.cjs +294 -19
  6. package/dist/cjs/resources/classes/fhir-ext.cjs.map +1 -1
  7. package/dist/cjs/resources/classes/fhir-ext.d.ts +2 -1
  8. package/dist/cjs/resources/classes/fhir.cjs +1 -0
  9. package/dist/cjs/resources/classes/fhir.cjs.map +1 -1
  10. package/dist/cjs/resources/classes/fhir.d.ts +1 -0
  11. package/dist/cjs/resources/classes/index.cjs +7 -0
  12. package/dist/cjs/resources/classes/index.cjs.map +1 -1
  13. package/dist/cjs/resources/types/RcmListPayersParams.d.ts +4 -0
  14. package/dist/cjs/resources/types/RcmListPayersResponse.d.ts +9 -1
  15. package/dist/cjs/resources/types/TelemedCreateMeetingParams.d.ts +4 -0
  16. package/dist/cjs/resources/types/fhir.d.ts +16 -3
  17. package/dist/esm/config.d.ts +15 -0
  18. package/dist/esm/index.min.js +1 -1
  19. package/dist/esm/index.min.js.map +1 -1
  20. package/dist/esm/resources/classes/fhir-ext.d.ts +2 -1
  21. package/dist/esm/resources/classes/fhir-ext.js +294 -20
  22. package/dist/esm/resources/classes/fhir-ext.js.map +1 -1
  23. package/dist/esm/resources/classes/fhir.d.ts +1 -0
  24. package/dist/esm/resources/classes/fhir.js +2 -1
  25. package/dist/esm/resources/classes/fhir.js.map +1 -1
  26. package/dist/esm/resources/classes/index.js +7 -0
  27. package/dist/esm/resources/classes/index.js.map +1 -1
  28. package/dist/esm/resources/types/RcmListPayersParams.d.ts +4 -0
  29. package/dist/esm/resources/types/RcmListPayersResponse.d.ts +9 -1
  30. package/dist/esm/resources/types/TelemedCreateMeetingParams.d.ts +4 -0
  31. package/dist/esm/resources/types/fhir.d.ts +16 -3
  32. package/package.json +1 -1
  33. package/src/config.ts +16 -0
  34. package/src/resources/classes/fhir-ext.ts +331 -19
  35. package/src/resources/classes/fhir.ts +1 -0
  36. package/src/resources/classes/index.ts +7 -0
  37. package/src/resources/types/RcmListPayersParams.ts +4 -0
  38. package/src/resources/types/RcmListPayersResponse.ts +9 -1
  39. package/src/resources/types/TelemedCreateMeetingParams.ts +4 -0
  40. package/src/resources/types/fhir.ts +20 -0
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../../../src/resources/classes/index.ts"],"sourcesContent":["// AUTOGENERATED -- DO NOT EDIT\n\nimport { OystehrConfig } from '../../config';\nimport { Application } from './application';\nimport { Charge } from './charge';\nimport { Conversation } from './conversation';\nimport { Developer } from './developer';\nimport { Erx } from './erx';\nimport { Fax } from './fax';\nimport { Fhir } from './fhir';\nimport { Lab } from './lab';\nimport { M2m } from './m2m';\nimport { Messaging } from './messaging';\nimport { PaymentMethod } from './paymentMethod';\nimport { Project } from './project';\nimport { Rcm } from './rcm';\nimport { Role } from './role';\nimport { Secret } from './secret';\nimport { Telemed } from './telemed';\nimport { Terminology } from './terminology';\nimport { TransactionalSMS } from './transactionalSMS';\nimport { User } from './user';\nimport { Version } from './version';\nimport { Z3 } from './z3';\nimport { Zambda } from './zambda';\nimport { ZambdaLogStream } from './zambdaLogStream';\n\nexport class Oystehr {\n readonly config: OystehrConfig;\n readonly application: Application;\n readonly developer: Developer;\n readonly m2m: M2m;\n readonly messaging: Messaging;\n readonly conversation: Conversation;\n readonly transactionalSMS: TransactionalSMS;\n readonly paymentMethod: PaymentMethod;\n readonly charge: Charge;\n readonly project: Project;\n readonly role: Role;\n readonly secret: Secret;\n readonly telemed: Telemed;\n readonly user: User;\n readonly version: Version;\n readonly z3: Z3;\n readonly fax: Fax;\n readonly lab: Lab;\n readonly erx: Erx;\n readonly terminology: Terminology;\n readonly zambda: Zambda;\n readonly zambdaLogStream: ZambdaLogStream;\n readonly rcm: Rcm;\n readonly fhir: Fhir;\n constructor(config: OystehrConfig) {\n this.config = config;\n this.config.services ??= {};\n this.config.services['projectApiUrl'] ??= config.projectApiUrl;\n this.config.services['fhirApiUrl'] ??= config.fhirApiUrl;\n this.application = new Application(config);\n this.developer = new Developer(config);\n this.m2m = new M2m(config);\n this.messaging = new Messaging(config);\n this.conversation = new Conversation(config);\n this.transactionalSMS = new TransactionalSMS(config);\n this.paymentMethod = new PaymentMethod(config);\n this.charge = new Charge(config);\n this.project = new Project(config);\n this.role = new Role(config);\n this.secret = new Secret(config);\n this.telemed = new Telemed(config);\n this.user = new User(config);\n this.version = new Version(config);\n this.z3 = new Z3(config);\n this.fax = new Fax(config);\n this.lab = new Lab(config);\n this.erx = new Erx(config);\n this.terminology = new Terminology(config);\n this.zambda = new Zambda(config);\n this.zambdaLogStream = new ZambdaLogStream(config);\n this.rcm = new Rcm(config);\n this.fhir = new Fhir(config);\n }\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAAA;sBA2Ba,OAAO,CAAA;AACT,IAAA,MAAM;AACN,IAAA,WAAW;AACX,IAAA,SAAS;AACT,IAAA,GAAG;AACH,IAAA,SAAS;AACT,IAAA,YAAY;AACZ,IAAA,gBAAgB;AAChB,IAAA,aAAa;AACb,IAAA,MAAM;AACN,IAAA,OAAO;AACP,IAAA,IAAI;AACJ,IAAA,MAAM;AACN,IAAA,OAAO;AACP,IAAA,IAAI;AACJ,IAAA,OAAO;AACP,IAAA,EAAE;AACF,IAAA,GAAG;AACH,IAAA,GAAG;AACH,IAAA,GAAG;AACH,IAAA,WAAW;AACX,IAAA,MAAM;AACN,IAAA,eAAe;AACf,IAAA,GAAG;AACH,IAAA,IAAI;AACb,IAAA,WAAA,CAAY,MAAqB,EAAA;AAC/B,QAAA,IAAI,CAAC,MAAM,GAAG,MAAM;AACpB,QAAA,IAAI,CAAC,MAAM,CAAC,QAAQ,KAAK,EAAE;QAC3B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAC,KAAK,MAAM,CAAC,aAAa;QAC9D,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC,KAAK,MAAM,CAAC,UAAU;QACxD,IAAI,CAAC,WAAW,GAAG,IAAI,WAAW,CAAC,MAAM,CAAC;QAC1C,IAAI,CAAC,SAAS,GAAG,IAAI,SAAS,CAAC,MAAM,CAAC;QACtC,IAAI,CAAC,GAAG,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC;QAC1B,IAAI,CAAC,SAAS,GAAG,IAAI,SAAS,CAAC,MAAM,CAAC;QACtC,IAAI,CAAC,YAAY,GAAG,IAAI,YAAY,CAAC,MAAM,CAAC;QAC5C,IAAI,CAAC,gBAAgB,GAAG,IAAI,gBAAgB,CAAC,MAAM,CAAC;QACpD,IAAI,CAAC,aAAa,GAAG,IAAI,aAAa,CAAC,MAAM,CAAC;QAC9C,IAAI,CAAC,MAAM,GAAG,IAAI,MAAM,CAAC,MAAM,CAAC;QAChC,IAAI,CAAC,OAAO,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC;QAClC,IAAI,CAAC,IAAI,GAAG,IAAI,IAAI,CAAC,MAAM,CAAC;QAC5B,IAAI,CAAC,MAAM,GAAG,IAAI,MAAM,CAAC,MAAM,CAAC;QAChC,IAAI,CAAC,OAAO,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC;QAClC,IAAI,CAAC,IAAI,GAAG,IAAI,IAAI,CAAC,MAAM,CAAC;QAC5B,IAAI,CAAC,OAAO,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC;QAClC,IAAI,CAAC,EAAE,GAAG,IAAI,EAAE,CAAC,MAAM,CAAC;QACxB,IAAI,CAAC,GAAG,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC;QAC1B,IAAI,CAAC,GAAG,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC;QAC1B,IAAI,CAAC,GAAG,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC;QAC1B,IAAI,CAAC,WAAW,GAAG,IAAI,WAAW,CAAC,MAAM,CAAC;QAC1C,IAAI,CAAC,MAAM,GAAG,IAAI,MAAM,CAAC,MAAM,CAAC;QAChC,IAAI,CAAC,eAAe,GAAG,IAAI,eAAe,CAAC,MAAM,CAAC;QAClD,IAAI,CAAC,GAAG,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC;QAC1B,IAAI,CAAC,IAAI,GAAG,IAAI,IAAI,CAAC,MAAM,CAAC;IAC9B;AACD;;;;"}
1
+ {"version":3,"file":"index.js","sources":["../../../../src/resources/classes/index.ts"],"sourcesContent":["// AUTOGENERATED -- DO NOT EDIT\n\nimport { OystehrConfig } from '../../config';\nimport { OystehrSdkError } from '../../errors';\nimport { Application } from './application';\nimport { Charge } from './charge';\nimport { Conversation } from './conversation';\nimport { Developer } from './developer';\nimport { Erx } from './erx';\nimport { Fax } from './fax';\nimport { Fhir } from './fhir';\nimport { Lab } from './lab';\nimport { M2m } from './m2m';\nimport { Messaging } from './messaging';\nimport { PaymentMethod } from './paymentMethod';\nimport { Project } from './project';\nimport { Rcm } from './rcm';\nimport { Role } from './role';\nimport { Secret } from './secret';\nimport { Telemed } from './telemed';\nimport { Terminology } from './terminology';\nimport { TransactionalSMS } from './transactionalSMS';\nimport { User } from './user';\nimport { Version } from './version';\nimport { Z3 } from './z3';\nimport { Zambda } from './zambda';\nimport { ZambdaLogStream } from './zambdaLogStream';\n\nexport class Oystehr {\n readonly config: OystehrConfig;\n readonly application: Application;\n readonly developer: Developer;\n readonly m2m: M2m;\n readonly messaging: Messaging;\n readonly conversation: Conversation;\n readonly transactionalSMS: TransactionalSMS;\n readonly paymentMethod: PaymentMethod;\n readonly charge: Charge;\n readonly project: Project;\n readonly role: Role;\n readonly secret: Secret;\n readonly telemed: Telemed;\n readonly user: User;\n readonly version: Version;\n readonly z3: Z3;\n readonly fax: Fax;\n readonly lab: Lab;\n readonly erx: Erx;\n readonly terminology: Terminology;\n readonly zambda: Zambda;\n readonly zambdaLogStream: ZambdaLogStream;\n readonly rcm: Rcm;\n readonly fhir: Fhir;\n constructor(config: OystehrConfig) {\n if (config.workspaceTag && config.ignoreTags) {\n throw new OystehrSdkError({\n message: 'workspaceTag and ignoreTags are mutually exclusive and cannot both be set in config',\n code: 400,\n });\n }\n this.config = config;\n this.config.services ??= {};\n this.config.services['projectApiUrl'] ??= config.projectApiUrl;\n this.config.services['fhirApiUrl'] ??= config.fhirApiUrl;\n this.application = new Application(config);\n this.developer = new Developer(config);\n this.m2m = new M2m(config);\n this.messaging = new Messaging(config);\n this.conversation = new Conversation(config);\n this.transactionalSMS = new TransactionalSMS(config);\n this.paymentMethod = new PaymentMethod(config);\n this.charge = new Charge(config);\n this.project = new Project(config);\n this.role = new Role(config);\n this.secret = new Secret(config);\n this.telemed = new Telemed(config);\n this.user = new User(config);\n this.version = new Version(config);\n this.z3 = new Z3(config);\n this.fax = new Fax(config);\n this.lab = new Lab(config);\n this.erx = new Erx(config);\n this.terminology = new Terminology(config);\n this.zambda = new Zambda(config);\n this.zambdaLogStream = new ZambdaLogStream(config);\n this.rcm = new Rcm(config);\n this.fhir = new Fhir(config);\n }\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAAA;sBA4Ba,OAAO,CAAA;AACT,IAAA,MAAM;AACN,IAAA,WAAW;AACX,IAAA,SAAS;AACT,IAAA,GAAG;AACH,IAAA,SAAS;AACT,IAAA,YAAY;AACZ,IAAA,gBAAgB;AAChB,IAAA,aAAa;AACb,IAAA,MAAM;AACN,IAAA,OAAO;AACP,IAAA,IAAI;AACJ,IAAA,MAAM;AACN,IAAA,OAAO;AACP,IAAA,IAAI;AACJ,IAAA,OAAO;AACP,IAAA,EAAE;AACF,IAAA,GAAG;AACH,IAAA,GAAG;AACH,IAAA,GAAG;AACH,IAAA,WAAW;AACX,IAAA,MAAM;AACN,IAAA,eAAe;AACf,IAAA,GAAG;AACH,IAAA,IAAI;AACb,IAAA,WAAA,CAAY,MAAqB,EAAA;QAC/B,IAAI,MAAM,CAAC,YAAY,IAAI,MAAM,CAAC,UAAU,EAAE;YAC5C,MAAM,IAAI,eAAe,CAAC;AACxB,gBAAA,OAAO,EAAE,qFAAqF;AAC9F,gBAAA,IAAI,EAAE,GAAG;AACV,aAAA,CAAC;QACJ;AACA,QAAA,IAAI,CAAC,MAAM,GAAG,MAAM;AACpB,QAAA,IAAI,CAAC,MAAM,CAAC,QAAQ,KAAK,EAAE;QAC3B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAC,KAAK,MAAM,CAAC,aAAa;QAC9D,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC,KAAK,MAAM,CAAC,UAAU;QACxD,IAAI,CAAC,WAAW,GAAG,IAAI,WAAW,CAAC,MAAM,CAAC;QAC1C,IAAI,CAAC,SAAS,GAAG,IAAI,SAAS,CAAC,MAAM,CAAC;QACtC,IAAI,CAAC,GAAG,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC;QAC1B,IAAI,CAAC,SAAS,GAAG,IAAI,SAAS,CAAC,MAAM,CAAC;QACtC,IAAI,CAAC,YAAY,GAAG,IAAI,YAAY,CAAC,MAAM,CAAC;QAC5C,IAAI,CAAC,gBAAgB,GAAG,IAAI,gBAAgB,CAAC,MAAM,CAAC;QACpD,IAAI,CAAC,aAAa,GAAG,IAAI,aAAa,CAAC,MAAM,CAAC;QAC9C,IAAI,CAAC,MAAM,GAAG,IAAI,MAAM,CAAC,MAAM,CAAC;QAChC,IAAI,CAAC,OAAO,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC;QAClC,IAAI,CAAC,IAAI,GAAG,IAAI,IAAI,CAAC,MAAM,CAAC;QAC5B,IAAI,CAAC,MAAM,GAAG,IAAI,MAAM,CAAC,MAAM,CAAC;QAChC,IAAI,CAAC,OAAO,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC;QAClC,IAAI,CAAC,IAAI,GAAG,IAAI,IAAI,CAAC,MAAM,CAAC;QAC5B,IAAI,CAAC,OAAO,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC;QAClC,IAAI,CAAC,EAAE,GAAG,IAAI,EAAE,CAAC,MAAM,CAAC;QACxB,IAAI,CAAC,GAAG,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC;QAC1B,IAAI,CAAC,GAAG,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC;QAC1B,IAAI,CAAC,GAAG,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC;QAC1B,IAAI,CAAC,WAAW,GAAG,IAAI,WAAW,CAAC,MAAM,CAAC;QAC1C,IAAI,CAAC,MAAM,GAAG,IAAI,MAAM,CAAC,MAAM,CAAC;QAChC,IAAI,CAAC,eAAe,GAAG,IAAI,eAAe,CAAC,MAAM,CAAC;QAClD,IAAI,CAAC,GAAG,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC;QAC1B,IAAI,CAAC,IAAI,GAAG,IAAI,IAAI,CAAC,MAAM,CAAC;IAC9B;AACD;;;;"}
@@ -2,4 +2,8 @@ export interface RcmListPayersParams {
2
2
  name?: string;
3
3
  identifier?: string;
4
4
  includeInactive?: boolean;
5
+ cursor?: string;
6
+ limit?: number;
7
+ sort?: 'id' | 'name';
8
+ sortOrder?: 'asc' | 'desc';
5
9
  }
@@ -2,4 +2,12 @@ import { Organization } from 'fhir/r4b';
2
2
  /**
3
3
  * List of payers matching the search criteria.
4
4
  */
5
- export type RcmListPayersResponse = Organization[];
5
+ export interface RcmListPayersResponse {
6
+ data: Organization[];
7
+ metadata: {
8
+ /**
9
+ * Cursor to fetch the next page of results. Null if there are no further pages.
10
+ */
11
+ nextCursor: string | null;
12
+ };
13
+ }
@@ -4,4 +4,8 @@ export interface TelemedCreateMeetingParams {
4
4
  * Well formed Encounter with the https://extensions.fhir.oystehr.com/encounter-other-participants extension specified optionally.
5
5
  */
6
6
  encounter: Encounter;
7
+ /**
8
+ * If true, audio from the meeting will be recorded and stored as an MP4 file in Z3. Defaults to false.
9
+ */
10
+ recordAudio?: boolean;
7
11
  }
@@ -1,6 +1,6 @@
1
1
  import type { Operation } from 'fast-json-patch';
2
- import type { Binary as BinaryR4B, Bundle as BundleR4B, BundleEntry as BundleEntryR4B, FhirResource as FhirResourceR4B, OperationOutcome as OperationOutcomeR4B } from 'fhir/r4b';
3
- import type { Binary as BinaryR5, Bundle as BundleR5, BundleEntry as BundleEntryR5, FhirResource as FhirResourceR5, OperationOutcome as OperationOutcomeR5 } from 'fhir/r5';
2
+ import type { Binary as BinaryR4B, Bundle as BundleR4B, BundleEntry as BundleEntryR4B, Coding as CodingR4B, FhirResource as FhirResourceR4B, OperationOutcome as OperationOutcomeR4B, Resource as ResourceR4B } from 'fhir/r4b';
3
+ import type { Binary as BinaryR5, Bundle as BundleR5, BundleEntry as BundleEntryR5, Coding as CodingR5, FhirResource as FhirResourceR5, OperationOutcome as OperationOutcomeR5, Resource as ResourceR5 } from 'fhir/r5';
4
4
  export type FhirResource = FhirResourceR4B | FhirResourceR5;
5
5
  export type FhirBundle<F extends FhirResource> = F extends FhirResourceR4B ? BundleR4B<F> : BundleR5<F>;
6
6
  export type EntrylessFhirBundle<F extends FhirResource> = F extends FhirResourceR4B ? Omit<BundleR4B<F>, 'entry'> : Omit<BundleR5<F>, 'entry'>;
@@ -28,6 +28,8 @@ export type TransactionBundle<F extends FhirResource> = EntrylessFhirBundle<F> &
28
28
  export type BundleEntry<F extends FhirResource> = F extends FhirResourceR4B ? BundleEntryR4B<F> : BundleEntryR5<F>;
29
29
  export type Binary<F extends FhirResource> = F extends FhirResourceR4B ? BinaryR4B : BinaryR5;
30
30
  export type OperationOutcome = OperationOutcomeR4B | OperationOutcomeR5;
31
+ export type Coding = CodingR4B | CodingR5;
32
+ export type Resource = ResourceR4B | ResourceR5;
31
33
  export type SearchParam = {
32
34
  name: string;
33
35
  value: string | number;
@@ -56,6 +58,9 @@ export interface FhirDeleteParams<T extends FhirResource> {
56
58
  resourceType: T['resourceType'];
57
59
  id: string;
58
60
  }
61
+ export interface GenerateFriendlyPatientIdParams {
62
+ id: string;
63
+ }
59
64
  export interface FhirHistorySearchParams<T extends FhirResource> {
60
65
  resourceType: T['resourceType'];
61
66
  id: string;
@@ -89,6 +94,14 @@ export interface BatchInputPostRequest<F extends FhirResource> extends BatchInpu
89
94
  resource: F;
90
95
  fullUrl?: string;
91
96
  }
97
+ /**
98
+ * A batch POST to a `_search` endpoint (e.g. `Patient/_search`). Search parameters
99
+ * may be appended to the URL as query parameters. Unlike a create POST there is no
100
+ * resource body.
101
+ */
102
+ export interface BatchInputSearchPostRequest extends BatchInputBaseRequest {
103
+ method: 'POST';
104
+ }
92
105
  export interface BatchInputBinaryPatchRequest<F extends FhirResource> extends BatchInputBaseRequest {
93
106
  method: 'PATCH';
94
107
  ifMatch?: string;
@@ -100,7 +113,7 @@ export interface BatchInputJSONPatchRequest extends BatchInputBaseRequest {
100
113
  operations: Operation[];
101
114
  }
102
115
  export type BatchInputPatchRequest<F extends FhirResource> = BatchInputBinaryPatchRequest<F> | BatchInputJSONPatchRequest;
103
- export type BatchInputRequest<F extends FhirResource> = BatchInputGetRequest | BatchInputHeadRequest | BatchInputPutRequest<F> | BatchInputPatchRequest<F> | BatchInputPostRequest<F> | BatchInputDeleteRequest;
116
+ export type BatchInputRequest<F extends FhirResource> = BatchInputGetRequest | BatchInputHeadRequest | BatchInputPutRequest<F> | BatchInputPatchRequest<F> | BatchInputPostRequest<F> | BatchInputSearchPostRequest | BatchInputDeleteRequest;
104
117
  export interface BatchInput<F extends FhirResource> {
105
118
  requests: BatchInputRequest<F>[];
106
119
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oystehr/sdk",
3
- "version": "4.3.3",
3
+ "version": "4.3.5",
4
4
  "description": "Oystehr SDK",
5
5
  "scripts": {
6
6
  "lint": "eslint .",
package/src/config.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import type { Coding } from './resources/types/fhir';
2
+
1
3
  /**
2
4
  * Configuration for the Oystehr SDK client
3
5
  */
@@ -62,6 +64,20 @@ export interface OystehrConfig {
62
64
  */
63
65
  retryOn?: number[];
64
66
  };
67
+ /**
68
+ * Optional workspace tag configuration. When set, all FHIR searches will be
69
+ * filtered to only return resources with this tag, and all FHIR mutations
70
+ * (create, update, patch) will have this tag injected automatically.
71
+ * Mutually exclusive with `ignoreTags`.
72
+ */
73
+ workspaceTag?: Coding;
74
+ /**
75
+ * Optional list of tags to ignore. When set, all FHIR searches will be
76
+ * filtered to exclude resources matching any of these tags, and mutations
77
+ * will throw an error if the resource carries any of these tags.
78
+ * Mutually exclusive with `workspaceTag`.
79
+ */
80
+ ignoreTags?: Coding[];
65
81
  }
66
82
 
67
83
  let globalConfig: OystehrConfig;
@@ -1,3 +1,4 @@
1
+ import type { Operation } from 'fast-json-patch';
1
2
  import { Address as AddressR4B, HumanName as HumanNameR4B } from 'fhir/r4b';
2
3
  import { Address as AddressR5, HumanName as HumanNameR5 } from 'fhir/r5';
3
4
  import {
@@ -7,6 +8,7 @@ import {
7
8
  Binary,
8
9
  Bundle,
9
10
  BundleEntry,
11
+ Coding,
10
12
  FhirBundle,
11
13
  FhirCreateParams,
12
14
  FhirDeleteParams,
@@ -18,10 +20,15 @@ import {
18
20
  FhirResourceReturnValue,
19
21
  FhirSearchParams,
20
22
  FhirUpdateParams,
23
+ GenerateFriendlyPatientIdParams,
21
24
  OperationOutcome,
25
+ Resource,
26
+ SearchParam,
22
27
  TransactionBundle,
23
28
  } from '../..';
24
29
  import { addParamsToSearch, FhirFetcherResponse, OystehrClientRequest, SDKResource } from '../../client/client';
30
+ import { OystehrConfig } from '../../config';
31
+ import { OystehrFHIRError, OystehrSdkError } from '../../errors';
25
32
 
26
33
  // Code adapted from https://github.com/sindresorhus/uint8array-extras
27
34
  const MAX_BLOCK_SIZE = 65_535;
@@ -37,6 +44,209 @@ function stringToBase64(input: string): string {
37
44
  return base64;
38
45
  }
39
46
 
47
+ function base64ToString(input: string): string {
48
+ const binaryString = globalThis.atob(input);
49
+ const bytes = new Uint8Array(binaryString.length);
50
+ for (let i = 0; i < binaryString.length; i++) {
51
+ bytes[i] = binaryString.charCodeAt(i);
52
+ }
53
+ return new globalThis.TextDecoder().decode(bytes);
54
+ }
55
+
56
+ // ─── Tag-mode helpers ────────────────────────────────────────────────────────
57
+
58
+ /** Converts a Coding to the FHIR _tag parameter value format "system|code". */
59
+ function codingToTagValue(coding: Coding): string {
60
+ return coding.system ? `${coding.system}|${coding.code ?? ''}` : coding.code ?? '';
61
+ }
62
+
63
+ /** Returns true if two Codings match on system (treating absent as empty string) and code. */
64
+ function codingMatches(a: Coding, b: Coding): boolean {
65
+ return (a.system ?? '') === (b.system ?? '') && (a.code ?? '') === (b.code ?? '');
66
+ }
67
+
68
+ /**
69
+ * Appends _tag (tag-workspace mode) or _tag:not (ignore-tags mode) search
70
+ * params to an existing SearchParam array and returns the new array.
71
+ */
72
+ function applyTagSearchParams(config: OystehrConfig, params: SearchParam[] | undefined): SearchParam[] {
73
+ const out: SearchParam[] = params ? [...params] : [];
74
+ if (config.workspaceTag) {
75
+ out.push({ name: '_tag', value: codingToTagValue(config.workspaceTag) });
76
+ } else if (config.ignoreTags?.length) {
77
+ for (const tag of config.ignoreTags) {
78
+ out.push({ name: '_tag:not', value: codingToTagValue(tag) });
79
+ }
80
+ }
81
+ return out;
82
+ }
83
+
84
+ /**
85
+ * In ignore-tags mode: throws OystehrSdkError if the resource carries any ignored tag.
86
+ * In tag-workspace mode: injects the workspace tag into resource.meta.tag if not already present.
87
+ * Returns the (possibly cloned) resource.
88
+ */
89
+ function applyTagToResource<T extends FhirResource>(config: OystehrConfig, resource: T): T {
90
+ const resourceLike = resource as unknown as Resource;
91
+
92
+ if (config.ignoreTags?.length) {
93
+ const resourceTags = (resourceLike.meta?.tag ?? []) as Coding[];
94
+ for (const ignored of config.ignoreTags) {
95
+ if (resourceTags.some((t) => codingMatches(t, ignored))) {
96
+ throw new OystehrSdkError({
97
+ message: `Resource has an ignored tag (system: "${ignored.system ?? ''}", code: "${
98
+ ignored.code ?? ''
99
+ }") and cannot be mutated in ignoreTags mode`,
100
+ code: 400,
101
+ });
102
+ }
103
+ }
104
+ return resource;
105
+ }
106
+
107
+ if (config.workspaceTag) {
108
+ const tag = config.workspaceTag;
109
+ const existingTags = (resourceLike.meta?.tag ?? []) as Coding[];
110
+ if (!existingTags.some((t) => codingMatches(t, tag))) {
111
+ return {
112
+ ...resource,
113
+ meta: {
114
+ ...resourceLike.meta,
115
+ tag: [...existingTags, tag],
116
+ },
117
+ } as T;
118
+ }
119
+ }
120
+
121
+ return resource;
122
+ }
123
+
124
+ /**
125
+ * In ignore-tags mode: throws OystehrSdkError if any operation value resembles an ignored tag.
126
+ * In tag-workspace mode: guards against removal or loss of the workspace tag:
127
+ * - add/replace of the tag array: ensures workspace tag is present in the value
128
+ * - add/replace of meta: ensures workspace tag is present in meta.tag
129
+ * - remove of /meta/tag or /meta: keeps the remove and appends an operation to restore the workspace tag
130
+ * - add of a single tag (path ends in /-): left unchanged (workspace tag already on the resource)
131
+ */
132
+ function applyTagToPatchOperations(config: OystehrConfig, operations: Operation[]): Operation[] {
133
+ if (config.ignoreTags?.length) {
134
+ for (const op of operations) {
135
+ if (op.op === 'add' || op.op === 'replace' || op.op === 'test') {
136
+ const opValue: unknown = op.value;
137
+ if (opValue !== null && opValue !== undefined && typeof opValue === 'object') {
138
+ const v = opValue as Coding;
139
+ if (v.code !== undefined) {
140
+ for (const ignored of config.ignoreTags) {
141
+ if (codingMatches(v, ignored)) {
142
+ throw new OystehrSdkError({
143
+ message: `Patch operation contains an ignored tag (system: "${ignored.system ?? ''}", code: "${
144
+ ignored.code ?? ''
145
+ }") and cannot be applied in ignoreTags mode`,
146
+ code: 400,
147
+ });
148
+ }
149
+ }
150
+ }
151
+ }
152
+ }
153
+ }
154
+ return operations;
155
+ }
156
+
157
+ if (config.workspaceTag) {
158
+ const tag = config.workspaceTag;
159
+ return operations.reduce<Operation[]>((result, op) => {
160
+ // remove /meta/tag — restore workspace tag afterwards
161
+ if (op.op === 'remove' && op.path === '/meta/tag') {
162
+ result.push(op);
163
+ result.push({ op: 'add' as const, path: '/meta/tag', value: [tag] });
164
+ return result;
165
+ }
166
+
167
+ // remove /meta — restore workspace tag afterwards
168
+ if (op.op === 'remove' && op.path === '/meta') {
169
+ result.push(op);
170
+ result.push({ op: 'add' as const, path: '/meta', value: { tag: [tag] } });
171
+ return result;
172
+ }
173
+
174
+ // add/replace the entire tag array — ensure workspace tag is present
175
+ if ((op.op === 'add' || op.op === 'replace') && op.path === '/meta/tag') {
176
+ const tags: Coding[] = Array.isArray(op.value) ? (op.value as Coding[]) : [];
177
+ if (!tags.some((t) => codingMatches(t, tag))) {
178
+ result.push({ ...op, value: [...tags, tag] });
179
+ } else {
180
+ result.push(op);
181
+ }
182
+ return result;
183
+ }
184
+
185
+ // add/replace the entire meta object — ensure workspace tag is present in meta.tag
186
+ if ((op.op === 'add' || op.op === 'replace') && op.path === '/meta') {
187
+ const metaValue: { tag?: Coding[] } =
188
+ op.value != null && typeof op.value === 'object' ? (op.value as { tag?: Coding[] }) : {};
189
+ const tags = metaValue.tag ?? [];
190
+ if (!tags.some((t) => codingMatches(t, tag))) {
191
+ result.push({ ...op, value: { ...metaValue, tag: [...tags, tag] } });
192
+ } else {
193
+ result.push(op);
194
+ }
195
+ return result;
196
+ }
197
+
198
+ // All other operations (including add /meta/tag/- for individual tags) pass through unchanged.
199
+ // Workspace tag is assumed already present on the resource from create/update.
200
+ result.push(op);
201
+ return result;
202
+ }, []);
203
+ }
204
+
205
+ return operations;
206
+ }
207
+
208
+ /**
209
+ * Throws OystehrFHIRError (404) if the retrieved resource violates the tag configuration:
210
+ * - workspaceTag mode: resource must carry the workspace tag
211
+ * - ignoreTags mode: resource must not carry any ignored tag
212
+ */
213
+ function assertRetrievedResource(config: OystehrConfig, resource: FhirResource): void {
214
+ const resourceLike = resource as unknown as Resource;
215
+ const resourceTags = (resourceLike.meta?.tag ?? []) as Coding[];
216
+
217
+ if (config.workspaceTag) {
218
+ const tag = config.workspaceTag;
219
+ if (!resourceTags.some((t) => codingMatches(t, tag))) {
220
+ throw new OystehrFHIRError({
221
+ error: {
222
+ resourceType: 'OperationOutcome',
223
+ id: 'not-found',
224
+ issue: [{ severity: 'error', code: 'not-found', details: { text: 'Not found' } }],
225
+ },
226
+ code: 404,
227
+ });
228
+ }
229
+ return;
230
+ }
231
+
232
+ if (config.ignoreTags?.length) {
233
+ for (const ignored of config.ignoreTags) {
234
+ if (resourceTags.some((t) => codingMatches(t, ignored))) {
235
+ throw new OystehrFHIRError({
236
+ error: {
237
+ resourceType: 'OperationOutcome',
238
+ id: 'not-found',
239
+ issue: [{ severity: 'error', code: 'not-found', details: { text: 'Not found' } }],
240
+ },
241
+ code: 404,
242
+ });
243
+ }
244
+ }
245
+ }
246
+ }
247
+
248
+ // ─────────────────────────────────────────────────────────────────────────────
249
+
40
250
  /**
41
251
  * Optional parameter that can be passed to the client methods. It allows
42
252
  * overriding the access token or project ID, and setting various headers,
@@ -64,10 +274,11 @@ export async function search<T extends FhirResource>(
64
274
  params: FhirSearchParams<T>,
65
275
  request?: OystehrClientRequest
66
276
  ): Promise<FhirFetcherResponse<Bundle<T>>> {
67
- const { resourceType, params: searchParams } = params;
277
+ const { resourceType } = params;
278
+ const taggedParams = applyTagSearchParams(this.config, params.params);
68
279
  let paramMap: Record<string, (string | number)[]> | undefined;
69
- if (searchParams) {
70
- paramMap = Object.entries(searchParams).reduce((acc, [_, param]) => {
280
+ if (taggedParams.length) {
281
+ paramMap = taggedParams.reduce((acc, param) => {
71
282
  if (!acc[param.name]) {
72
283
  acc[param.name] = [];
73
284
  }
@@ -96,8 +307,9 @@ export async function create<T extends FhirResource>(
96
307
  params: FhirCreateParams<T>,
97
308
  request?: OystehrClientRequest
98
309
  ): Promise<FhirFetcherResponse<FhirResourceReturnValue<T>>> {
99
- const { resourceType } = params;
100
- return this.fhirRequest(`/${resourceType}`, 'POST')(params as unknown as Record<string, unknown>, request);
310
+ const tagged = applyTagToResource(this.config, params);
311
+ const { resourceType } = tagged;
312
+ return this.fhirRequest(`/${resourceType}`, 'POST')(tagged as unknown as Record<string, unknown>, request);
101
313
  }
102
314
 
103
315
  export async function get<T extends FhirResource>(
@@ -105,7 +317,9 @@ export async function get<T extends FhirResource>(
105
317
  { resourceType, id }: FhirGetParams<T>,
106
318
  request?: OystehrClientRequest
107
319
  ): Promise<FhirFetcherResponse<FhirResourceReturnValue<T>>> {
108
- return this.fhirRequest<FhirResourceReturnValue<T>>(`/${resourceType}/${id}`, 'GET')({}, request);
320
+ const result = await this.fhirRequest<FhirResourceReturnValue<T>>(`/${resourceType}/${id}`, 'GET')({}, request);
321
+ assertRetrievedResource(this.config, result);
322
+ return result;
109
323
  }
110
324
 
111
325
  export async function update<T extends FhirResource>(
@@ -113,8 +327,9 @@ export async function update<T extends FhirResource>(
113
327
  params: FhirUpdateParams<T>,
114
328
  request?: OystehrFHIRUpdateClientRequest
115
329
  ): Promise<FhirFetcherResponse<FhirResourceReturnValue<T>>> {
116
- const { id, resourceType } = params;
117
- return this.fhirRequest(`/${resourceType}/${id}`, 'PUT')(params as unknown as Record<string, unknown>, {
330
+ const tagged = applyTagToResource(this.config, params);
331
+ const { id, resourceType } = tagged;
332
+ return this.fhirRequest(`/${resourceType}/${id}`, 'PUT')(tagged as unknown as Record<string, unknown>, {
118
333
  ...request,
119
334
  ifMatch: request?.optimisticLockingVersionId ? `W/"${request.optimisticLockingVersionId}"` : undefined,
120
335
  });
@@ -125,7 +340,8 @@ export async function patch<T extends FhirResource>(
125
340
  { resourceType, id, operations }: FhirPatchParams<T>,
126
341
  request?: OystehrFHIRUpdateClientRequest
127
342
  ): Promise<FhirFetcherResponse<FhirResourceReturnValue<T>>> {
128
- return this.fhirRequest(`/${resourceType}/${id}`, 'PATCH')(operations, {
343
+ const taggedOperations = applyTagToPatchOperations(this.config, operations);
344
+ return this.fhirRequest(`/${resourceType}/${id}`, 'PATCH')(taggedOperations, {
129
345
  ...request,
130
346
  contentType: 'application/json-patch+json',
131
347
  ifMatch: request?.optimisticLockingVersionId ? `W/"${request.optimisticLockingVersionId}"` : undefined,
@@ -180,10 +396,50 @@ export async function history<T extends FhirResource>(
180
396
  return this.fhirRequest(`/${resourceType}/${id}/_history?_total=accurate`, 'GET')({}, request);
181
397
  }
182
398
 
399
+ /**
400
+ * Returns true when a batch GET/HEAD URL is a search (e.g. "Patient" or "Patient?name=foo")
401
+ * rather than a direct retrieval (e.g. "Patient/abc-123").
402
+ * A retrieval URL has a path segment after the resource type that is not a FHIR operation
403
+ * (operations start with "_", e.g. "_search" or "_history").
404
+ */
405
+ function isBatchSearchUrl(url: string): boolean {
406
+ const path = url.split('?')[0];
407
+ const segments = path.split('/').filter(Boolean);
408
+ // Only one segment → bare resource type, always a search
409
+ if (segments.length <= 1) return true;
410
+ // Two or more segments: second segment is an ID if it doesn't start with '_'
411
+ return segments[1].startsWith('_');
412
+ }
413
+
414
+ /** Returns true when a batch POST URL targets a `_search` endpoint (e.g. "Patient/_search"). */
415
+ function isBatchSearchPostUrl(url: string): boolean {
416
+ return url.split('?')[0].endsWith('/_search');
417
+ }
418
+
183
419
  function batchInputRequestToBundleEntryItem<T extends FhirResource>(
184
- request: BatchInputRequest<T>
420
+ request: BatchInputRequest<T>,
421
+ config: OystehrConfig
185
422
  ): BundleEntry<T | Binary<T>> {
186
- const { method, url } = request;
423
+ const { method } = request;
424
+ let url = request.url;
425
+
426
+ // Inject tag search params into search request URLs before URL encoding.
427
+ // GET/HEAD: only for search URLs (not retrievals like Patient/<id>).
428
+ // POST: only for _search endpoints (not creates).
429
+ if (
430
+ ((method === 'GET' || method === 'HEAD') && isBatchSearchUrl(url)) ||
431
+ (method === 'POST' && isBatchSearchPostUrl(url))
432
+ ) {
433
+ if (config.workspaceTag) {
434
+ url += (url.includes('?') ? '&' : '?') + `_tag=${codingToTagValue(config.workspaceTag)}`;
435
+ }
436
+ if (config.ignoreTags?.length) {
437
+ for (const tag of config.ignoreTags) {
438
+ url += (url.includes('?') ? '&' : '?') + `_tag:not=${codingToTagValue(tag)}`;
439
+ }
440
+ }
441
+ }
442
+
187
443
  const baseRequest = {
188
444
  request: {
189
445
  method,
@@ -222,7 +478,7 @@ function batchInputRequestToBundleEntryItem<T extends FhirResource>(
222
478
 
223
479
  // PUT updates require a full resource
224
480
  if (method === 'PUT') {
225
- const { resource } = request;
481
+ const resource = applyTagToResource(config, request.resource);
226
482
  return {
227
483
  request: {
228
484
  ...baseRequest.request,
@@ -235,15 +491,24 @@ function batchInputRequestToBundleEntryItem<T extends FhirResource>(
235
491
  // PATCH can be Binary resource or JSON patch
236
492
  if (method === 'PATCH') {
237
493
  if ('resource' in request) {
494
+ // Binary patch — decode operations, apply tag transforms, re-encode
495
+ let patchResource = request.resource;
496
+ const binaryData = patchResource.data;
497
+ if (binaryData) {
498
+ const operations = JSON.parse(base64ToString(binaryData)) as Operation[];
499
+ const taggedOperations = applyTagToPatchOperations(config, operations);
500
+ patchResource = { ...patchResource, data: stringToBase64(JSON.stringify(taggedOperations)) } as Binary<T>;
501
+ }
238
502
  return {
239
503
  request: {
240
504
  ...baseRequest.request,
241
505
  ifMatch: request.ifMatch,
242
506
  },
243
- resource: request.resource,
507
+ resource: patchResource,
244
508
  } as BundleEntry<Binary<T>>;
245
509
  }
246
- const data = stringToBase64(JSON.stringify(request.operations));
510
+ const operations = applyTagToPatchOperations(config, request.operations);
511
+ const data = stringToBase64(JSON.stringify(operations));
247
512
  return {
248
513
  ...baseRequest,
249
514
  resource: {
@@ -254,9 +519,15 @@ function batchInputRequestToBundleEntryItem<T extends FhirResource>(
254
519
  } as BundleEntry<Binary<T>>;
255
520
  }
256
521
 
522
+ // POST _search — no resource body; tag params were already injected into the URL above
523
+ if (method === 'POST' && isBatchSearchPostUrl(url)) {
524
+ return baseRequest as BundleEntry<T>;
525
+ }
526
+
257
527
  // POST creates require a full resource
258
- if (method === 'POST') {
259
- const { resource, fullUrl } = request;
528
+ if (method === 'POST' && 'resource' in request) {
529
+ const resource = applyTagToResource(config, request.resource);
530
+ const { fullUrl } = request;
260
531
  return {
261
532
  ...baseRequest,
262
533
  resource: resource as T,
@@ -284,13 +555,35 @@ export async function batch<BundleContentType extends FhirResource>(
284
555
  {
285
556
  resourceType: 'Bundle',
286
557
  type: 'batch',
287
- entry: input.requests.map(batchInputRequestToBundleEntryItem),
558
+ entry: input.requests.map((req) => batchInputRequestToBundleEntryItem(req, this.config)),
288
559
  },
289
560
  request
290
561
  );
562
+ // Validate each GET/HEAD retrieval entry against the tag config.
563
+ // Violations are replaced with a synthetic 404 OperationOutcome entry; batch entries are independent.
564
+ const rawEntries = resp.entry as Array<BundleEntry<BundleContentType>> | undefined;
565
+ const processedEntries: Array<BundleEntry<BundleContentType>> | undefined =
566
+ this.config.workspaceTag || this.config.ignoreTags?.length
567
+ ? rawEntries?.map((entry, i) => {
568
+ const req = input.requests[i];
569
+ if (!req || !entry?.resource) return entry;
570
+ if ((req.method === 'GET' || req.method === 'HEAD') && !isBatchSearchUrl(req.url)) {
571
+ try {
572
+ assertRetrievedResource(this.config, entry.resource);
573
+ } catch (err) {
574
+ if (!(err instanceof OystehrFHIRError)) throw err;
575
+ return {
576
+ request: entry.request,
577
+ response: { status: '404', outcome: err.cause },
578
+ } as unknown as BundleEntry<BundleContentType>;
579
+ }
580
+ }
581
+ return entry;
582
+ })
583
+ : rawEntries;
291
584
  const bundle: BatchBundle<BundleContentType> = {
292
585
  ...resp,
293
- entry: resp.entry as Array<BundleEntry<BundleContentType>> | undefined,
586
+ entry: processedEntries,
294
587
  unbundle: function (this: { entry?: Array<BundleEntry<BundleContentType>> | undefined }) {
295
588
  return (
296
589
  this.entry
@@ -317,10 +610,21 @@ export async function transaction<BundleContentType extends FhirResource>(
317
610
  {
318
611
  resourceType: 'Bundle',
319
612
  type: 'transaction',
320
- entry: input.requests.map(batchInputRequestToBundleEntryItem),
613
+ entry: input.requests.map((req) => batchInputRequestToBundleEntryItem(req, this.config)),
321
614
  },
322
615
  request
323
616
  );
617
+ // Validate each GET/HEAD retrieval entry against the tag config.
618
+ // A violation throws OystehrFHIRError(404) — transactions are all-or-nothing.
619
+ if (this.config.workspaceTag || this.config.ignoreTags?.length) {
620
+ (resp.entry as Array<BundleEntry<BundleContentType>> | undefined)?.forEach((entry, i) => {
621
+ const req = input.requests[i];
622
+ if (!req || !entry?.resource) return;
623
+ if ((req.method === 'GET' || req.method === 'HEAD') && !isBatchSearchUrl(req.url)) {
624
+ assertRetrievedResource(this.config, entry.resource);
625
+ }
626
+ });
627
+ }
324
628
  const bundle: TransactionBundle<BundleContentType> = {
325
629
  ...resp,
326
630
  entry: resp.entry as Array<BundleEntry<BundleContentType>> | undefined,
@@ -335,6 +639,14 @@ export async function transaction<BundleContentType extends FhirResource>(
335
639
  return bundle;
336
640
  }
337
641
 
642
+ export async function generateFriendlyPatientId(
643
+ this: SDKResource,
644
+ { id }: GenerateFriendlyPatientIdParams,
645
+ request?: OystehrClientRequest
646
+ ): Promise<FhirFetcherResponse<FhirResource>> {
647
+ return this.fhirRequest(`/Patient/${id}/$generate-friendly-patient-id`, 'POST')({}, request);
648
+ }
649
+
338
650
  export function formatAddress(
339
651
  address: AddressR4B | AddressR5,
340
652
  options?: { all?: boolean; use?: boolean; lineSeparator?: string }
@@ -26,6 +26,7 @@ export class Fhir extends SDKResource {
26
26
  history = ext.history;
27
27
  batch = ext.batch;
28
28
  transaction = ext.transaction;
29
+ generateFriendlyPatientId = ext.generateFriendlyPatientId;
29
30
  formatAddress = ext.formatAddress;
30
31
  formatHumanName = ext.formatHumanName;
31
32
  }
@@ -1,6 +1,7 @@
1
1
  // AUTOGENERATED -- DO NOT EDIT
2
2
 
3
3
  import { OystehrConfig } from '../../config';
4
+ import { OystehrSdkError } from '../../errors';
4
5
  import { Application } from './application';
5
6
  import { Charge } from './charge';
6
7
  import { Conversation } from './conversation';
@@ -51,6 +52,12 @@ export class Oystehr {
51
52
  readonly rcm: Rcm;
52
53
  readonly fhir: Fhir;
53
54
  constructor(config: OystehrConfig) {
55
+ if (config.workspaceTag && config.ignoreTags) {
56
+ throw new OystehrSdkError({
57
+ message: 'workspaceTag and ignoreTags are mutually exclusive and cannot both be set in config',
58
+ code: 400,
59
+ });
60
+ }
54
61
  this.config = config;
55
62
  this.config.services ??= {};
56
63
  this.config.services['projectApiUrl'] ??= config.projectApiUrl;
@@ -4,4 +4,8 @@ export interface RcmListPayersParams {
4
4
  name?: string;
5
5
  identifier?: string;
6
6
  includeInactive?: boolean;
7
+ cursor?: string;
8
+ limit?: number;
9
+ sort?: 'id' | 'name';
10
+ sortOrder?: 'asc' | 'desc';
7
11
  }