@medplum/core 0.4.1 → 0.5.2

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
@@ -638,13 +638,16 @@ const PREFIX_OPERATORS = [
638
638
  * @returns Parsed search definition.
639
639
  */
640
640
  function parseSearchDefinition(location) {
641
- const resourceType = location.pathname.split('/').pop();
641
+ const resourceType = location.pathname
642
+ .replace(/(^\/)|(\/$)/g, '') // Remove leading and trailing slashes
643
+ .split('/')
644
+ .pop();
642
645
  const params = new URLSearchParams(location.search);
643
- const filters = [];
644
- const sortRules = [];
645
- let fields;
646
- let page = 0;
647
- let count = 10;
646
+ let filters = undefined;
647
+ let sortRules = undefined;
648
+ let fields = undefined;
649
+ let page = undefined;
650
+ let count = undefined;
648
651
  let total = undefined;
649
652
  params.forEach((value, key) => {
650
653
  if (key === '_fields') {
@@ -660,9 +663,11 @@ function parseSearchDefinition(location) {
660
663
  total = value;
661
664
  }
662
665
  else if (key === '_sort') {
666
+ sortRules = sortRules || [];
663
667
  sortRules.push(parseSortRule(value));
664
668
  }
665
669
  else {
670
+ filters = filters || [];
666
671
  filters.push(parseSearchFilter(key, value));
667
672
  }
668
673
  });
@@ -741,13 +746,9 @@ function formatSearchQuery(definition) {
741
746
  params.push('_fields=' + definition.fields.join(','));
742
747
  }
743
748
  if (definition.filters) {
744
- definition.filters.forEach((filter) => {
745
- const modifier = MODIFIER_OPERATORS.includes(filter.operator) ? ':' + filter.operator : '';
746
- const prefix = PREFIX_OPERATORS.includes(filter.operator) ? filter.operator : '';
747
- params.push(`${filter.code}${modifier}=${prefix}${encodeURIComponent(filter.value)}`);
748
- });
749
+ definition.filters.forEach((filter) => params.push(formatFilter(filter)));
749
750
  }
750
- if (definition.sortRules) {
751
+ if (definition.sortRules && definition.sortRules.length > 0) {
751
752
  params.push(formatSortRules(definition.sortRules));
752
753
  }
753
754
  if (definition.page && definition.page > 0) {
@@ -765,6 +766,11 @@ function formatSearchQuery(definition) {
765
766
  params.sort();
766
767
  return '?' + params.join('&');
767
768
  }
769
+ function formatFilter(filter) {
770
+ const modifier = MODIFIER_OPERATORS.includes(filter.operator) ? ':' + filter.operator : '';
771
+ const prefix = PREFIX_OPERATORS.includes(filter.operator) ? filter.operator : '';
772
+ return `${filter.code}${modifier}=${prefix}${encodeURIComponent(filter.value)}`;
773
+ }
768
774
  function formatSortRules(sortRules) {
769
775
  if (!sortRules || sortRules.length === 0) {
770
776
  return '';
@@ -936,6 +942,21 @@ var PropertyType;
936
942
  function createSchema() {
937
943
  return { types: {} };
938
944
  }
945
+ function createTypeSchema(typeName, description) {
946
+ return {
947
+ display: typeName,
948
+ description,
949
+ properties: {},
950
+ searchParams: {
951
+ _lastUpdated: {
952
+ base: [typeName],
953
+ code: '_lastUpdated',
954
+ type: 'date',
955
+ expression: typeName + '.meta.lastUpdated',
956
+ },
957
+ },
958
+ };
959
+ }
939
960
  /**
940
961
  * Indexes a StructureDefinition for fast lookup.
941
962
  * See comments on IndexedStructureDefinition for more details.
@@ -948,11 +969,7 @@ function indexStructureDefinition(schema, structureDefinition) {
948
969
  if (!typeName) {
949
970
  return;
950
971
  }
951
- schema.types[typeName] = {
952
- display: typeName,
953
- description: structureDefinition.description,
954
- properties: {},
955
- };
972
+ schema.types[typeName] = createTypeSchema(typeName, structureDefinition.description);
956
973
  const elements = (_a = structureDefinition.snapshot) === null || _a === void 0 ? void 0 : _a.element;
957
974
  if (elements) {
958
975
  // Filter out any elements missing path or type
@@ -980,12 +997,8 @@ function indexType(schema, element) {
980
997
  const parts = path.split('.');
981
998
  const typeName = buildTypeName(parts);
982
999
  if (!(typeName in schema.types)) {
983
- schema.types[typeName] = {
984
- display: typeName,
985
- description: element.definition,
986
- parentType: buildTypeName(parts.slice(0, parts.length - 1)),
987
- properties: {},
988
- };
1000
+ schema.types[typeName] = createTypeSchema(typeName, element.definition);
1001
+ schema.types[typeName].parentType = buildTypeName(parts.slice(0, parts.length - 1));
989
1002
  }
990
1003
  }
991
1004
  /**
@@ -1033,6 +1046,10 @@ function getPropertyDisplayName(property) {
1033
1046
  // For example, for path "Patient.birthDate"
1034
1047
  // the property name is "birthDate"
1035
1048
  const propertyName = property.path.replaceAll('[x]', '').split('.').pop();
1049
+ // Special case for ID
1050
+ if (propertyName === 'id') {
1051
+ return 'ID';
1052
+ }
1036
1053
  // Split by capital letters
1037
1054
  // Capitalize the first letter of each word
1038
1055
  // Join together with spaces in between
@@ -1334,7 +1351,9 @@ class MedplumClient extends EventTarget {
1334
1351
  SearchParameterList(base: "${encodeURIComponent(resourceType)}") {
1335
1352
  base,
1336
1353
  code,
1337
- type
1354
+ type,
1355
+ expression,
1356
+ target
1338
1357
  }
1339
1358
  }`.replace(/\s+/g, ' ');
1340
1359
  const response = (yield this.graphql(query));
@@ -1671,6 +1690,9 @@ var SearchParameterType;
1671
1690
  */
1672
1691
  function getSearchParameterDetails(structureDefinitions, resourceType, searchParam) {
1673
1692
  var _a, _b, _c, _d;
1693
+ if (searchParam.code === '_lastUpdated') {
1694
+ return { columnName: 'lastUpdated', type: SearchParameterType.DATETIME };
1695
+ }
1674
1696
  const columnName = convertCodeToColumnName(searchParam.code);
1675
1697
  const expression = (_a = getExpressionForResourceType(resourceType, searchParam.expression)) === null || _a === void 0 ? void 0 : _a.split('.');
1676
1698
  if (!expression) {
@@ -1679,20 +1701,21 @@ function getSearchParameterDetails(structureDefinitions, resourceType, searchPar
1679
1701
  return { columnName, type: SearchParameterType.TEXT };
1680
1702
  }
1681
1703
  let baseType = resourceType;
1704
+ let elementDefinition = undefined;
1682
1705
  let propertyType = undefined;
1683
1706
  let array = false;
1684
1707
  for (let i = 1; i < expression.length; i++) {
1685
1708
  const propertyName = expression[i];
1686
- const propertyDef = (_c = (_b = structureDefinitions.types[baseType]) === null || _b === void 0 ? void 0 : _b.properties) === null || _c === void 0 ? void 0 : _c[propertyName];
1687
- if (!propertyDef) {
1709
+ elementDefinition = (_c = (_b = structureDefinitions.types[baseType]) === null || _b === void 0 ? void 0 : _b.properties) === null || _c === void 0 ? void 0 : _c[propertyName];
1710
+ if (!elementDefinition) {
1688
1711
  // This happens on complex properties such as "collected[x]"/"collectedDateTime"/"collectedPeriod"
1689
1712
  // In the future, explore returning multiple column definitions
1690
1713
  return { columnName, type: SearchParameterType.TEXT, array };
1691
1714
  }
1692
- if (propertyDef.max === '*') {
1715
+ if (elementDefinition.max === '*') {
1693
1716
  array = true;
1694
1717
  }
1695
- propertyType = (_d = propertyDef.type) === null || _d === void 0 ? void 0 : _d[0].code;
1718
+ propertyType = (_d = elementDefinition.type) === null || _d === void 0 ? void 0 : _d[0].code;
1696
1719
  if (!propertyType) {
1697
1720
  // This happens when one of parent properties uses contentReference
1698
1721
  // In the future, explore following the reference
@@ -1708,7 +1731,7 @@ function getSearchParameterDetails(structureDefinitions, resourceType, searchPar
1708
1731
  }
1709
1732
  }
1710
1733
  const type = getSearchParameterType(searchParam, propertyType);
1711
- return { columnName, type, array };
1734
+ return { columnName, type, elementDefinition, array };
1712
1735
  }
1713
1736
  /**
1714
1737
  * Converts a hyphen-delimited code to camelCase string.
@@ -1765,5 +1788,5 @@ function simplifyExpression(input) {
1765
1788
  return result;
1766
1789
  }
1767
1790
 
1768
- export { MedplumClient, OperationOutcomeError, Operator, PropertyType, SearchParameterType, accessDenied, allOk, arrayBufferToBase64, arrayBufferToHex, assertOk, badRequest, buildTypeName, capitalize, createReference, createSchema, created, deepEquals, formatAddress, formatFamilyName, formatGivenName, formatHumanName, formatSearchQuery, getDateProperty, getDisplayString, getExpressionForResourceType, getImageSrc, getPropertyDisplayName, getReferenceString, getSearchParameterDetails, getStatus, gone, indexSearchParameter, indexStructureDefinition, isGone, isLowerCase, isNotFound, isOk, isProfileResource, notFound, notModified, parseSearchDefinition, resolveId, stringify };
1791
+ export { MedplumClient, OperationOutcomeError, Operator, PropertyType, SearchParameterType, accessDenied, allOk, arrayBufferToBase64, arrayBufferToHex, assertOk, badRequest, buildTypeName, capitalize, createReference, createSchema, createTypeSchema, created, deepEquals, formatAddress, formatFamilyName, formatGivenName, formatHumanName, formatSearchQuery, getDateProperty, getDisplayString, getExpressionForResourceType, getImageSrc, getPropertyDisplayName, getReferenceString, getSearchParameterDetails, getStatus, gone, indexSearchParameter, indexStructureDefinition, isGone, isLowerCase, isNotFound, isOk, isProfileResource, notFound, notModified, parseSearchDefinition, resolveId, stringify };
1769
1792
  //# sourceMappingURL=index.js.map