@medplum/core 0.9.12 → 0.9.15

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.
package/dist/esm/index.js CHANGED
@@ -566,6 +566,165 @@ function capitalize(word) {
566
566
  function isLowerCase(c) {
567
567
  return c === c.toLowerCase();
568
568
  }
569
+ /**
570
+ * Tries to find a code string for a given system within a given codeable concept.
571
+ * @param concept The codeable concept.
572
+ * @param system The system string.
573
+ * @returns The code if found; otherwise undefined.
574
+ */
575
+ function getCodeBySystem(concept, system) {
576
+ var _a, _b;
577
+ return (_b = (_a = concept === null || concept === void 0 ? void 0 : concept.coding) === null || _a === void 0 ? void 0 : _a.find((coding) => coding.system === system)) === null || _b === void 0 ? void 0 : _b.code;
578
+ }
579
+ /**
580
+ * Sets a code for a given system within a given codeable concept.
581
+ * @param concept The codeable concept.
582
+ * @param system The system string.
583
+ * @param code The code value.
584
+ */
585
+ function setCodeBySystem(concept, system, code) {
586
+ var _a, _b;
587
+ if (!concept.coding) {
588
+ concept.coding = [];
589
+ }
590
+ const coding = (_a = concept.coding) === null || _a === void 0 ? void 0 : _a.find((c) => c.system === system);
591
+ if (coding) {
592
+ coding.code = code;
593
+ }
594
+ else {
595
+ (_b = concept.coding) === null || _b === void 0 ? void 0 : _b.push({ system, code });
596
+ }
597
+ }
598
+ /**
599
+ * Tries to find an observation interval for the given patient and value.
600
+ * @param definition The observation definition.
601
+ * @param patient The patient.
602
+ * @param value The observation value.
603
+ * @returns The observation interval if found; otherwise undefined.
604
+ */
605
+ function findObservationInterval(definition, patient, value, category) {
606
+ var _a;
607
+ return (_a = definition.qualifiedInterval) === null || _a === void 0 ? void 0 : _a.find((interval) => {
608
+ var _a;
609
+ return observationIntervalMatchesPatient(interval, patient) &&
610
+ observationIntervalMatchesValue(interval, value, (_a = definition.quantitativeDetails) === null || _a === void 0 ? void 0 : _a.decimalPrecision) &&
611
+ (category === undefined || interval.category === category);
612
+ });
613
+ }
614
+ /**
615
+ * Returns true if the patient matches the observation interval.
616
+ * @param interval The observation interval.
617
+ * @param patient The patient.
618
+ * @returns True if the patient matches the observation interval.
619
+ */
620
+ function observationIntervalMatchesPatient(interval, patient) {
621
+ return observationIntervalMatchesGender(interval, patient) && observationIntervalMatchesAge(interval, patient);
622
+ }
623
+ /**
624
+ * Returns true if the patient gender matches the observation interval.
625
+ * @param interval The observation interval.
626
+ * @param patient The patient.
627
+ * @returns True if the patient gender matches the observation interval.
628
+ */
629
+ function observationIntervalMatchesGender(interval, patient) {
630
+ return !interval.gender || interval.gender === patient.gender;
631
+ }
632
+ /**
633
+ * Returns true if the patient age matches the observation interval.
634
+ * @param interval The observation interval.
635
+ * @param patient The patient.
636
+ * @returns True if the patient age matches the observation interval.
637
+ */
638
+ function observationIntervalMatchesAge(interval, patient) {
639
+ return !interval.age || matchesRange(calculateAge(patient.birthDate).years, interval.age);
640
+ }
641
+ /**
642
+ * Returns true if the value matches the observation interval.
643
+ * @param interval The observation interval.
644
+ * @param value The observation value.
645
+ * @param precision Optional precision in number of digits.
646
+ * @returns True if the value matches the observation interval.
647
+ */
648
+ function observationIntervalMatchesValue(interval, value, precision) {
649
+ return !!interval.range && matchesRange(value, interval.range, precision);
650
+ }
651
+ /**
652
+ * Returns true if the value is in the range accounting for precision.
653
+ * @param value The numeric value.
654
+ * @param range The numeric range.
655
+ * @param precision Optional precision in number of digits.
656
+ * @returns True if the value is within the range.
657
+ */
658
+ function matchesRange(value, range, precision) {
659
+ var _a, _b;
660
+ return ((((_a = range.low) === null || _a === void 0 ? void 0 : _a.value) === undefined || preciseGreaterThanOrEquals(value, range.low.value, precision)) &&
661
+ (((_b = range.high) === null || _b === void 0 ? void 0 : _b.value) === undefined || preciseLessThanOrEquals(value, range.high.value, precision)));
662
+ }
663
+ /**
664
+ * Returns true if the two numbers are equal to the given precision.
665
+ * @param a The first number.
666
+ * @param b The second number.
667
+ * @param precision Optional precision in number of digits.
668
+ * @returns True if the two numbers are equal to the given precision.
669
+ */
670
+ function preciseEquals(a, b, precision) {
671
+ if (precision) {
672
+ return Math.abs(a - b) < Math.pow(10, -precision);
673
+ }
674
+ else {
675
+ return a === b;
676
+ }
677
+ }
678
+ /**
679
+ * Returns true if the first number is less than the second number to the given precision.
680
+ * @param a The first number.
681
+ * @param b The second number.
682
+ * @param precision Optional precision in number of digits.
683
+ * @returns True if the first number is less than the second number to the given precision.
684
+ */
685
+ function preciseLessThan(a, b, precision) {
686
+ if (precision) {
687
+ return a < b && Math.abs(a - b) > Math.pow(10, -precision);
688
+ }
689
+ else {
690
+ return a < b;
691
+ }
692
+ }
693
+ /**
694
+ * Returns true if the first number is greater than the second number to the given precision.
695
+ * @param a The first number.
696
+ * @param b The second number.
697
+ * @param precision Optional precision in number of digits.
698
+ * @returns True if the first number is greater than the second number to the given precision.
699
+ */
700
+ function preciseGreaterThan(a, b, precision) {
701
+ if (precision) {
702
+ return a > b && Math.abs(a - b) > Math.pow(10, -precision);
703
+ }
704
+ else {
705
+ return a > b;
706
+ }
707
+ }
708
+ /**
709
+ * Returns true if the first number is less than or equal to the second number to the given precision.
710
+ * @param a The first number.
711
+ * @param b The second number.
712
+ * @param precision Optional precision in number of digits.
713
+ * @returns True if the first number is less than or equal to the second number to the given precision.
714
+ */
715
+ function preciseLessThanOrEquals(a, b, precision) {
716
+ return preciseLessThan(a, b, precision) || preciseEquals(a, b, precision);
717
+ }
718
+ /**
719
+ * Returns true if the first number is greater than or equal to the second number to the given precision.
720
+ * @param a The first number.
721
+ * @param b The second number.
722
+ * @param precision Optional precision in number of digits.
723
+ * @returns True if the first number is greater than or equal to the second number to the given precision.
724
+ */
725
+ function preciseGreaterThanOrEquals(a, b, precision) {
726
+ return preciseGreaterThan(a, b, precision) || preciseEquals(a, b, precision);
727
+ }
569
728
 
570
729
  /**
571
730
  * Returns a cryptographically secure random string.
@@ -655,155 +814,6 @@ function parseJWTPayload(token) {
655
814
  return decodePayload(payload);
656
815
  }
657
816
 
658
- const OK_ID = 'ok';
659
- const CREATED_ID = 'created';
660
- const GONE_ID = 'gone';
661
- const NOT_MODIFIED_ID = 'not-modified';
662
- const NOT_FOUND_ID = 'not-found';
663
- const ACCESS_DENIED = 'access-denied';
664
- const allOk = {
665
- resourceType: 'OperationOutcome',
666
- id: OK_ID,
667
- issue: [
668
- {
669
- severity: 'information',
670
- code: 'information',
671
- details: {
672
- text: 'All OK',
673
- },
674
- },
675
- ],
676
- };
677
- const created = {
678
- resourceType: 'OperationOutcome',
679
- id: CREATED_ID,
680
- issue: [
681
- {
682
- severity: 'information',
683
- code: 'information',
684
- details: {
685
- text: 'Created',
686
- },
687
- },
688
- ],
689
- };
690
- const notModified = {
691
- resourceType: 'OperationOutcome',
692
- id: NOT_MODIFIED_ID,
693
- issue: [
694
- {
695
- severity: 'information',
696
- code: 'information',
697
- details: {
698
- text: 'Not Modified',
699
- },
700
- },
701
- ],
702
- };
703
- const notFound = {
704
- resourceType: 'OperationOutcome',
705
- id: NOT_FOUND_ID,
706
- issue: [
707
- {
708
- severity: 'error',
709
- code: 'not-found',
710
- details: {
711
- text: 'Not found',
712
- },
713
- },
714
- ],
715
- };
716
- const gone = {
717
- resourceType: 'OperationOutcome',
718
- id: GONE_ID,
719
- issue: [
720
- {
721
- severity: 'error',
722
- code: 'gone',
723
- details: {
724
- text: 'Gone',
725
- },
726
- },
727
- ],
728
- };
729
- const accessDenied = {
730
- resourceType: 'OperationOutcome',
731
- id: ACCESS_DENIED,
732
- issue: [
733
- {
734
- severity: 'error',
735
- code: 'access-denied',
736
- details: {
737
- text: 'Access Denied',
738
- },
739
- },
740
- ],
741
- };
742
- function badRequest(details, expression) {
743
- return {
744
- resourceType: 'OperationOutcome',
745
- issue: [
746
- {
747
- severity: 'error',
748
- code: 'invalid',
749
- details: {
750
- text: details,
751
- },
752
- expression: expression ? [expression] : undefined,
753
- },
754
- ],
755
- };
756
- }
757
- function isOk(outcome) {
758
- return outcome.id === OK_ID || outcome.id === CREATED_ID || outcome.id === NOT_MODIFIED_ID;
759
- }
760
- function isNotFound(outcome) {
761
- return outcome.id === NOT_FOUND_ID;
762
- }
763
- function isGone(outcome) {
764
- return outcome.id === GONE_ID;
765
- }
766
- function getStatus(outcome) {
767
- if (outcome.id === OK_ID) {
768
- return 200;
769
- }
770
- else if (outcome.id === CREATED_ID) {
771
- return 201;
772
- }
773
- else if (outcome.id === NOT_MODIFIED_ID) {
774
- return 304;
775
- }
776
- else if (outcome.id === ACCESS_DENIED) {
777
- return 403;
778
- }
779
- else if (outcome.id === NOT_FOUND_ID) {
780
- return 404;
781
- }
782
- else if (outcome.id === GONE_ID) {
783
- return 410;
784
- }
785
- else {
786
- return 400;
787
- }
788
- }
789
- /**
790
- * Asserts that the operation completed successfully and that the resource is defined.
791
- * @param outcome The operation outcome.
792
- * @param resource The resource that may or may not have been returned.
793
- */
794
- function assertOk(outcome, resource) {
795
- if (!isOk(outcome) || resource === undefined) {
796
- throw new OperationOutcomeError(outcome);
797
- }
798
- }
799
- class OperationOutcomeError extends Error {
800
- constructor(outcome) {
801
- var _a, _b;
802
- super((_b = (_a = outcome === null || outcome === void 0 ? void 0 : outcome.issue) === null || _a === void 0 ? void 0 : _a[0].details) === null || _b === void 0 ? void 0 : _b.text);
803
- this.outcome = outcome;
804
- }
805
- }
806
-
807
817
  var _ReadablePromise_suspender, _ReadablePromise_status, _ReadablePromise_response, _ReadablePromise_error, _a;
808
818
  /**
809
819
  * The ReadablePromise class wraps a request promise suitable for React Suspense.
@@ -1645,7 +1655,13 @@ class MedplumClient extends EventTarget {
1645
1655
  */
1646
1656
  getCachedReference(reference) {
1647
1657
  const refString = reference.reference;
1658
+ if (!refString) {
1659
+ return undefined;
1660
+ }
1648
1661
  const [resourceType, id] = refString.split('/');
1662
+ if (!resourceType || !id) {
1663
+ return undefined;
1664
+ }
1649
1665
  return this.getCached(resourceType, id);
1650
1666
  }
1651
1667
  /**
@@ -1691,6 +1707,9 @@ class MedplumClient extends EventTarget {
1691
1707
  return new ReadablePromise(Promise.reject(new Error('Missing reference')));
1692
1708
  }
1693
1709
  const [resourceType, id] = refString.split('/');
1710
+ if (!resourceType || !id) {
1711
+ return new ReadablePromise(Promise.reject(new Error('Invalid reference')));
1712
+ }
1694
1713
  return this.readResource(resourceType, id);
1695
1714
  }
1696
1715
  /**
@@ -2228,8 +2247,8 @@ _MedplumClient_fetch = new WeakMap(), _MedplumClient_createPdf = new WeakMap(),
2228
2247
  return undefined;
2229
2248
  }
2230
2249
  const obj = yield response.json();
2231
- if ((obj === null || obj === void 0 ? void 0 : obj.resourceType) === 'OperationOutcome' && !isOk(obj)) {
2232
- return Promise.reject(obj);
2250
+ if (response.status >= 400) {
2251
+ throw obj;
2233
2252
  }
2234
2253
  return obj;
2235
2254
  });
@@ -5018,6 +5037,155 @@ class Hl7Field {
5018
5037
  }
5019
5038
  }
5020
5039
 
5040
+ const OK_ID = 'ok';
5041
+ const CREATED_ID = 'created';
5042
+ const GONE_ID = 'gone';
5043
+ const NOT_MODIFIED_ID = 'not-modified';
5044
+ const NOT_FOUND_ID = 'not-found';
5045
+ const ACCESS_DENIED = 'access-denied';
5046
+ const allOk = {
5047
+ resourceType: 'OperationOutcome',
5048
+ id: OK_ID,
5049
+ issue: [
5050
+ {
5051
+ severity: 'information',
5052
+ code: 'information',
5053
+ details: {
5054
+ text: 'All OK',
5055
+ },
5056
+ },
5057
+ ],
5058
+ };
5059
+ const created = {
5060
+ resourceType: 'OperationOutcome',
5061
+ id: CREATED_ID,
5062
+ issue: [
5063
+ {
5064
+ severity: 'information',
5065
+ code: 'information',
5066
+ details: {
5067
+ text: 'Created',
5068
+ },
5069
+ },
5070
+ ],
5071
+ };
5072
+ const notModified = {
5073
+ resourceType: 'OperationOutcome',
5074
+ id: NOT_MODIFIED_ID,
5075
+ issue: [
5076
+ {
5077
+ severity: 'information',
5078
+ code: 'information',
5079
+ details: {
5080
+ text: 'Not Modified',
5081
+ },
5082
+ },
5083
+ ],
5084
+ };
5085
+ const notFound = {
5086
+ resourceType: 'OperationOutcome',
5087
+ id: NOT_FOUND_ID,
5088
+ issue: [
5089
+ {
5090
+ severity: 'error',
5091
+ code: 'not-found',
5092
+ details: {
5093
+ text: 'Not found',
5094
+ },
5095
+ },
5096
+ ],
5097
+ };
5098
+ const gone = {
5099
+ resourceType: 'OperationOutcome',
5100
+ id: GONE_ID,
5101
+ issue: [
5102
+ {
5103
+ severity: 'error',
5104
+ code: 'gone',
5105
+ details: {
5106
+ text: 'Gone',
5107
+ },
5108
+ },
5109
+ ],
5110
+ };
5111
+ const accessDenied = {
5112
+ resourceType: 'OperationOutcome',
5113
+ id: ACCESS_DENIED,
5114
+ issue: [
5115
+ {
5116
+ severity: 'error',
5117
+ code: 'access-denied',
5118
+ details: {
5119
+ text: 'Access Denied',
5120
+ },
5121
+ },
5122
+ ],
5123
+ };
5124
+ function badRequest(details, expression) {
5125
+ return {
5126
+ resourceType: 'OperationOutcome',
5127
+ issue: [
5128
+ {
5129
+ severity: 'error',
5130
+ code: 'invalid',
5131
+ details: {
5132
+ text: details,
5133
+ },
5134
+ expression: expression ? [expression] : undefined,
5135
+ },
5136
+ ],
5137
+ };
5138
+ }
5139
+ function isOk(outcome) {
5140
+ return outcome.id === OK_ID || outcome.id === CREATED_ID || outcome.id === NOT_MODIFIED_ID;
5141
+ }
5142
+ function isNotFound(outcome) {
5143
+ return outcome.id === NOT_FOUND_ID;
5144
+ }
5145
+ function isGone(outcome) {
5146
+ return outcome.id === GONE_ID;
5147
+ }
5148
+ function getStatus(outcome) {
5149
+ if (outcome.id === OK_ID) {
5150
+ return 200;
5151
+ }
5152
+ else if (outcome.id === CREATED_ID) {
5153
+ return 201;
5154
+ }
5155
+ else if (outcome.id === NOT_MODIFIED_ID) {
5156
+ return 304;
5157
+ }
5158
+ else if (outcome.id === ACCESS_DENIED) {
5159
+ return 403;
5160
+ }
5161
+ else if (outcome.id === NOT_FOUND_ID) {
5162
+ return 404;
5163
+ }
5164
+ else if (outcome.id === GONE_ID) {
5165
+ return 410;
5166
+ }
5167
+ else {
5168
+ return 400;
5169
+ }
5170
+ }
5171
+ /**
5172
+ * Asserts that the operation completed successfully and that the resource is defined.
5173
+ * @param outcome The operation outcome.
5174
+ * @param resource The resource that may or may not have been returned.
5175
+ */
5176
+ function assertOk(outcome, resource) {
5177
+ if (!isOk(outcome) || resource === undefined) {
5178
+ throw new OperationOutcomeError(outcome);
5179
+ }
5180
+ }
5181
+ class OperationOutcomeError extends Error {
5182
+ constructor(outcome) {
5183
+ var _a, _b;
5184
+ super((_b = (_a = outcome === null || outcome === void 0 ? void 0 : outcome.issue) === null || _a === void 0 ? void 0 : _a[0].details) === null || _b === void 0 ? void 0 : _b.text);
5185
+ this.outcome = outcome;
5186
+ }
5187
+ }
5188
+
5021
5189
  const DEFAULT_SEARCH_COUNT = 20;
5022
5190
  /**
5023
5191
  * Search operators.
@@ -5349,5 +5517,5 @@ function simplifyExpression(input) {
5349
5517
  return result;
5350
5518
  }
5351
5519
 
5352
- export { COMPONENT_SEPARATOR, DEFAULT_SEARCH_COUNT, FIELD_SEPARATOR, Hl7Field, Hl7Message, Hl7Segment, LRUCache, MedplumClient, OperationOutcomeError, Operator, PropertyType, ReadablePromise, SEGMENT_SEPARATOR, SearchParameterType, accessDenied, allOk, arrayBufferToBase64, arrayBufferToHex, assertOk, badRequest, buildTypeName, calculateAge, calculateAgeString, capitalize, createReference, createSchema, createTypeSchema, created, deepEquals$1 as deepEquals, evalFhirPath, formatAddress, formatFamilyName, formatGivenName, formatHumanName, formatSearchQuery, getDateProperty, getDisplayString, getExpressionForResourceType, getExtensionValue, getIdentifier, getImageSrc, getPropertyDisplayName, getQuestionnaireAnswers, getReferenceString, getSearchParameterDetails, getStatus, gone, indexSearchParameter, indexStructureDefinition, isGone, isLowerCase, isNotFound, isObject$1 as isObject, isOk, isProfileResource, isStringArray, isUUID, notFound, notModified, parseFhirPath, parseSearchDefinition, resolveId, stringify, tokenize };
5520
+ export { COMPONENT_SEPARATOR, DEFAULT_SEARCH_COUNT, FIELD_SEPARATOR, Hl7Field, Hl7Message, Hl7Segment, LRUCache, MedplumClient, OperationOutcomeError, Operator, PropertyType, ReadablePromise, SEGMENT_SEPARATOR, SearchParameterType, accessDenied, allOk, arrayBufferToBase64, arrayBufferToHex, assertOk, badRequest, buildTypeName, calculateAge, calculateAgeString, capitalize, createReference, createSchema, createTypeSchema, created, deepEquals$1 as deepEquals, evalFhirPath, findObservationInterval, formatAddress, formatFamilyName, formatGivenName, formatHumanName, formatSearchQuery, getCodeBySystem, getDateProperty, getDisplayString, getExpressionForResourceType, getExtensionValue, getIdentifier, getImageSrc, getPropertyDisplayName, getQuestionnaireAnswers, getReferenceString, getSearchParameterDetails, getStatus, gone, indexSearchParameter, indexStructureDefinition, isGone, isLowerCase, isNotFound, isObject$1 as isObject, isOk, isProfileResource, isStringArray, isUUID, matchesRange, notFound, notModified, parseFhirPath, parseSearchDefinition, preciseEquals, preciseGreaterThan, preciseGreaterThanOrEquals, preciseLessThan, preciseLessThanOrEquals, resolveId, setCodeBySystem, stringify, tokenize };
5353
5521
  //# sourceMappingURL=index.js.map