@medplum/core 0.9.8 → 0.9.11
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/cody-pdf-test.js +1 -1
- package/dist/cjs/index.js +226 -307
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/index.min.js +1 -1
- package/dist/cjs/index.min.js.map +1 -1
- package/dist/esm/index.js +226 -307
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/index.min.js +1 -1
- package/dist/esm/index.min.js.map +1 -1
- package/dist/types/client.d.ts +59 -15
- package/package.json +2 -2
- package/test9-2.pdf +0 -0
- package/test9-3.pdf +0 -0
- package/test9-4.pdf +0 -0
- package/test9.pdf +0 -0
- package/dist/types/pdf.d.ts +0 -5
package/dist/esm/index.js
CHANGED
|
@@ -804,91 +804,6 @@ class OperationOutcomeError extends Error {
|
|
|
804
804
|
}
|
|
805
805
|
}
|
|
806
806
|
|
|
807
|
-
/*
|
|
808
|
-
* This file attempts a unified "generatePdf" function that works both client-side and server-side.
|
|
809
|
-
* On client-side, it checks for a global "pdfMake" variable.
|
|
810
|
-
* On server-side, it dynamically loads "pdfmake" from the node_modules.
|
|
811
|
-
*/
|
|
812
|
-
function generatePdf(docDefinition, tableLayouts, fonts) {
|
|
813
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
814
|
-
// Setup sane defaults
|
|
815
|
-
// See: https://pdfmake.github.io/docs/0.1/document-definition-object/styling/
|
|
816
|
-
docDefinition.pageSize = docDefinition.pageSize || 'LETTER';
|
|
817
|
-
docDefinition.pageMargins = docDefinition.pageMargins || [60, 60, 60, 60];
|
|
818
|
-
docDefinition.pageOrientation = docDefinition.pageOrientation || 'portrait';
|
|
819
|
-
docDefinition.defaultStyle = docDefinition.defaultStyle || {};
|
|
820
|
-
docDefinition.defaultStyle.font = docDefinition.defaultStyle.font || 'Helvetica';
|
|
821
|
-
docDefinition.defaultStyle.fontSize = docDefinition.defaultStyle.fontSize || 11;
|
|
822
|
-
docDefinition.defaultStyle.lineHeight = docDefinition.defaultStyle.lineHeight || 2.0;
|
|
823
|
-
if (typeof pdfMake === 'undefined') {
|
|
824
|
-
return generatePdfServerSide(docDefinition, tableLayouts, fonts);
|
|
825
|
-
}
|
|
826
|
-
else {
|
|
827
|
-
return generatePdfClientSide(docDefinition, tableLayouts, fonts);
|
|
828
|
-
}
|
|
829
|
-
});
|
|
830
|
-
}
|
|
831
|
-
function generatePdfServerSide(docDefinition, tableLayouts, fonts) {
|
|
832
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
833
|
-
if (!fonts) {
|
|
834
|
-
fonts = {
|
|
835
|
-
Helvetica: {
|
|
836
|
-
normal: 'Helvetica',
|
|
837
|
-
bold: 'Helvetica-Bold',
|
|
838
|
-
italics: 'Helvetica-Oblique',
|
|
839
|
-
bolditalics: 'Helvetica-BoldOblique',
|
|
840
|
-
},
|
|
841
|
-
Roboto: {
|
|
842
|
-
normal: 'https://static.medplum.com/fonts/Roboto-Regular.ttf',
|
|
843
|
-
bold: 'https://static.medplum.com/fonts/Roboto-Medium.ttf',
|
|
844
|
-
italics: 'https://static.medplum.com/fonts/Roboto-Italic.ttf',
|
|
845
|
-
bolditalics: 'https://static.medplum.com/fonts/Roboto-MediumItalic.ttf',
|
|
846
|
-
},
|
|
847
|
-
Avenir: {
|
|
848
|
-
normal: 'https://static.medplum.com/fonts/avenir.ttf',
|
|
849
|
-
},
|
|
850
|
-
};
|
|
851
|
-
}
|
|
852
|
-
return new Promise((resolve, reject) => {
|
|
853
|
-
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
854
|
-
const PdfPrinter = require('pdfmake');
|
|
855
|
-
const printer = new PdfPrinter(fonts);
|
|
856
|
-
const pdfDoc = printer.createPdfKitDocument(docDefinition, { tableLayouts });
|
|
857
|
-
const chunks = [];
|
|
858
|
-
pdfDoc.on('data', (chunk) => chunks.push(chunk));
|
|
859
|
-
pdfDoc.on('end', () => resolve(Buffer.concat(chunks)));
|
|
860
|
-
pdfDoc.on('error', reject);
|
|
861
|
-
pdfDoc.end();
|
|
862
|
-
});
|
|
863
|
-
});
|
|
864
|
-
}
|
|
865
|
-
function generatePdfClientSide(docDefinition, tableLayouts, fonts) {
|
|
866
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
867
|
-
if (!fonts) {
|
|
868
|
-
fonts = {
|
|
869
|
-
Helvetica: {
|
|
870
|
-
normal: 'https://static.medplum.com/fonts/Helvetica.ttf',
|
|
871
|
-
bold: 'https://static.medplum.com/fonts/Helvetica-bold.ttf',
|
|
872
|
-
italics: 'https://static.medplum.com/fonts/Helvetica-italic.ttf',
|
|
873
|
-
bolditalics: 'https://static.medplum.com/fonts/Helvetica-bold-italic.ttf',
|
|
874
|
-
},
|
|
875
|
-
Roboto: {
|
|
876
|
-
normal: 'https://static.medplum.com/fonts/Roboto-Regular.ttf',
|
|
877
|
-
bold: 'https://static.medplum.com/fonts/Roboto-Medium.ttf',
|
|
878
|
-
italics: 'https://static.medplum.com/fonts/Roboto-Italic.ttf',
|
|
879
|
-
bolditalics: 'https://static.medplum.com/fonts/Roboto-MediumItalic.ttf',
|
|
880
|
-
},
|
|
881
|
-
Avenir: {
|
|
882
|
-
normal: 'https://static.medplum.com/fonts/avenir.ttf',
|
|
883
|
-
},
|
|
884
|
-
};
|
|
885
|
-
}
|
|
886
|
-
return new Promise((resolve) => {
|
|
887
|
-
pdfMake.createPdf(docDefinition, tableLayouts, fonts).getBlob(resolve);
|
|
888
|
-
});
|
|
889
|
-
});
|
|
890
|
-
}
|
|
891
|
-
|
|
892
807
|
var _ReadablePromise_suspender, _ReadablePromise_status, _ReadablePromise_response, _ReadablePromise_error, _a;
|
|
893
808
|
/**
|
|
894
809
|
* The ReadablePromise class wraps a request promise suitable for React Suspense.
|
|
@@ -965,206 +880,6 @@ class ReadablePromise {
|
|
|
965
880
|
}
|
|
966
881
|
_ReadablePromise_suspender = new WeakMap(), _ReadablePromise_status = new WeakMap(), _ReadablePromise_response = new WeakMap(), _ReadablePromise_error = new WeakMap(), _a = Symbol.toStringTag;
|
|
967
882
|
|
|
968
|
-
const DEFAULT_SEARCH_COUNT = 20;
|
|
969
|
-
/**
|
|
970
|
-
* Search operators.
|
|
971
|
-
* These operators represent "modifiers" and "prefixes" in FHIR search.
|
|
972
|
-
* See: https://www.hl7.org/fhir/search.html
|
|
973
|
-
*/
|
|
974
|
-
var Operator;
|
|
975
|
-
(function (Operator) {
|
|
976
|
-
Operator["EQUALS"] = "eq";
|
|
977
|
-
Operator["NOT_EQUALS"] = "ne";
|
|
978
|
-
// Numbers
|
|
979
|
-
Operator["GREATER_THAN"] = "gt";
|
|
980
|
-
Operator["LESS_THAN"] = "lt";
|
|
981
|
-
Operator["GREATER_THAN_OR_EQUALS"] = "ge";
|
|
982
|
-
Operator["LESS_THAN_OR_EQUALS"] = "le";
|
|
983
|
-
// Dates
|
|
984
|
-
Operator["STARTS_AFTER"] = "sa";
|
|
985
|
-
Operator["ENDS_BEFORE"] = "eb";
|
|
986
|
-
Operator["APPROXIMATELY"] = "ap";
|
|
987
|
-
// String
|
|
988
|
-
Operator["CONTAINS"] = "contains";
|
|
989
|
-
Operator["EXACT"] = "exact";
|
|
990
|
-
// Token
|
|
991
|
-
Operator["TEXT"] = "text";
|
|
992
|
-
Operator["ABOVE"] = "above";
|
|
993
|
-
Operator["BELOW"] = "below";
|
|
994
|
-
Operator["IN"] = "in";
|
|
995
|
-
Operator["NOT_IN"] = "not-in";
|
|
996
|
-
Operator["OF_TYPE"] = "of-type";
|
|
997
|
-
})(Operator || (Operator = {}));
|
|
998
|
-
const MODIFIER_OPERATORS = [
|
|
999
|
-
Operator.CONTAINS,
|
|
1000
|
-
Operator.EXACT,
|
|
1001
|
-
Operator.TEXT,
|
|
1002
|
-
Operator.ABOVE,
|
|
1003
|
-
Operator.BELOW,
|
|
1004
|
-
Operator.IN,
|
|
1005
|
-
Operator.NOT_IN,
|
|
1006
|
-
Operator.OF_TYPE,
|
|
1007
|
-
];
|
|
1008
|
-
const PREFIX_OPERATORS = [
|
|
1009
|
-
Operator.NOT_EQUALS,
|
|
1010
|
-
Operator.GREATER_THAN,
|
|
1011
|
-
Operator.LESS_THAN,
|
|
1012
|
-
Operator.GREATER_THAN_OR_EQUALS,
|
|
1013
|
-
Operator.LESS_THAN_OR_EQUALS,
|
|
1014
|
-
Operator.STARTS_AFTER,
|
|
1015
|
-
Operator.ENDS_BEFORE,
|
|
1016
|
-
Operator.APPROXIMATELY,
|
|
1017
|
-
];
|
|
1018
|
-
/**
|
|
1019
|
-
* Parses a URL into a SearchRequest.
|
|
1020
|
-
*
|
|
1021
|
-
* See the FHIR search spec: http://hl7.org/fhir/r4/search.html
|
|
1022
|
-
*
|
|
1023
|
-
* @param url The URL to parse.
|
|
1024
|
-
* @returns Parsed search definition.
|
|
1025
|
-
*/
|
|
1026
|
-
function parseSearchDefinition(url) {
|
|
1027
|
-
const location = new URL(url, 'https://example.com/');
|
|
1028
|
-
const resourceType = location.pathname
|
|
1029
|
-
.replace(/(^\/)|(\/$)/g, '') // Remove leading and trailing slashes
|
|
1030
|
-
.split('/')
|
|
1031
|
-
.pop();
|
|
1032
|
-
const params = new URLSearchParams(location.search);
|
|
1033
|
-
let filters = undefined;
|
|
1034
|
-
let sortRules = undefined;
|
|
1035
|
-
let fields = undefined;
|
|
1036
|
-
let offset = undefined;
|
|
1037
|
-
let count = undefined;
|
|
1038
|
-
let total = undefined;
|
|
1039
|
-
params.forEach((value, key) => {
|
|
1040
|
-
if (key === '_fields') {
|
|
1041
|
-
fields = value.split(',');
|
|
1042
|
-
}
|
|
1043
|
-
else if (key === '_offset') {
|
|
1044
|
-
offset = parseInt(value);
|
|
1045
|
-
}
|
|
1046
|
-
else if (key === '_count') {
|
|
1047
|
-
count = parseInt(value);
|
|
1048
|
-
}
|
|
1049
|
-
else if (key === '_total') {
|
|
1050
|
-
total = value;
|
|
1051
|
-
}
|
|
1052
|
-
else if (key === '_sort') {
|
|
1053
|
-
sortRules = sortRules || [];
|
|
1054
|
-
sortRules.push(parseSortRule(value));
|
|
1055
|
-
}
|
|
1056
|
-
else {
|
|
1057
|
-
filters = filters || [];
|
|
1058
|
-
filters.push(parseSearchFilter(key, value));
|
|
1059
|
-
}
|
|
1060
|
-
});
|
|
1061
|
-
return {
|
|
1062
|
-
resourceType,
|
|
1063
|
-
filters,
|
|
1064
|
-
fields,
|
|
1065
|
-
offset,
|
|
1066
|
-
count,
|
|
1067
|
-
total,
|
|
1068
|
-
sortRules,
|
|
1069
|
-
};
|
|
1070
|
-
}
|
|
1071
|
-
/**
|
|
1072
|
-
* Parses a URL query parameter into a sort rule.
|
|
1073
|
-
*
|
|
1074
|
-
* By default, the sort rule is the field name.
|
|
1075
|
-
*
|
|
1076
|
-
* Sort rules can be reversed into descending order by prefixing the field name with a minus sign.
|
|
1077
|
-
*
|
|
1078
|
-
* See sorting: http://hl7.org/fhir/r4/search.html#_sort
|
|
1079
|
-
*
|
|
1080
|
-
* @param value The URL parameter value.
|
|
1081
|
-
* @returns The parsed sort rule.
|
|
1082
|
-
*/
|
|
1083
|
-
function parseSortRule(value) {
|
|
1084
|
-
if (value.startsWith('-')) {
|
|
1085
|
-
return { code: value.substring(1), descending: true };
|
|
1086
|
-
}
|
|
1087
|
-
else {
|
|
1088
|
-
return { code: value };
|
|
1089
|
-
}
|
|
1090
|
-
}
|
|
1091
|
-
/**
|
|
1092
|
-
* Parses a URL query parameter into a search filter.
|
|
1093
|
-
*
|
|
1094
|
-
* FHIR search filters can be specified as modifiers or prefixes.
|
|
1095
|
-
*
|
|
1096
|
-
* For string properties, modifiers are appended to the key, e.g. "name:contains=eve".
|
|
1097
|
-
*
|
|
1098
|
-
* For date and numeric properties, prefixes are prepended to the value, e.g. "birthdate=gt2000".
|
|
1099
|
-
*
|
|
1100
|
-
* See the FHIR search spec: http://hl7.org/fhir/r4/search.html
|
|
1101
|
-
*
|
|
1102
|
-
* @param key The URL parameter key.
|
|
1103
|
-
* @param value The URL parameter value.
|
|
1104
|
-
* @returns The parsed search filter.
|
|
1105
|
-
*/
|
|
1106
|
-
function parseSearchFilter(key, value) {
|
|
1107
|
-
let code = key;
|
|
1108
|
-
let operator = Operator.EQUALS;
|
|
1109
|
-
for (const modifier of MODIFIER_OPERATORS) {
|
|
1110
|
-
const modifierIndex = code.indexOf(':' + modifier);
|
|
1111
|
-
if (modifierIndex !== -1) {
|
|
1112
|
-
operator = modifier;
|
|
1113
|
-
code = code.substring(0, modifierIndex);
|
|
1114
|
-
}
|
|
1115
|
-
}
|
|
1116
|
-
for (const prefix of PREFIX_OPERATORS) {
|
|
1117
|
-
if (value.match(new RegExp('^' + prefix + '\\d'))) {
|
|
1118
|
-
operator = prefix;
|
|
1119
|
-
value = value.substring(prefix.length);
|
|
1120
|
-
}
|
|
1121
|
-
}
|
|
1122
|
-
return { code, operator, value };
|
|
1123
|
-
}
|
|
1124
|
-
/**
|
|
1125
|
-
* Formats a search definition object into a query string.
|
|
1126
|
-
* Note: The return value does not include the resource type.
|
|
1127
|
-
* @param {!SearchRequest} definition The search definition.
|
|
1128
|
-
* @returns Formatted URL.
|
|
1129
|
-
*/
|
|
1130
|
-
function formatSearchQuery(definition) {
|
|
1131
|
-
const params = [];
|
|
1132
|
-
if (definition.fields) {
|
|
1133
|
-
params.push('_fields=' + definition.fields.join(','));
|
|
1134
|
-
}
|
|
1135
|
-
if (definition.filters) {
|
|
1136
|
-
definition.filters.forEach((filter) => params.push(formatFilter(filter)));
|
|
1137
|
-
}
|
|
1138
|
-
if (definition.sortRules && definition.sortRules.length > 0) {
|
|
1139
|
-
params.push(formatSortRules(definition.sortRules));
|
|
1140
|
-
}
|
|
1141
|
-
if (definition.offset !== undefined) {
|
|
1142
|
-
params.push('_offset=' + definition.offset);
|
|
1143
|
-
}
|
|
1144
|
-
if (definition.count !== undefined) {
|
|
1145
|
-
params.push('_count=' + definition.count);
|
|
1146
|
-
}
|
|
1147
|
-
if (definition.total !== undefined) {
|
|
1148
|
-
params.push('_total=' + definition.total);
|
|
1149
|
-
}
|
|
1150
|
-
if (params.length === 0) {
|
|
1151
|
-
return '';
|
|
1152
|
-
}
|
|
1153
|
-
params.sort();
|
|
1154
|
-
return '?' + params.join('&');
|
|
1155
|
-
}
|
|
1156
|
-
function formatFilter(filter) {
|
|
1157
|
-
const modifier = MODIFIER_OPERATORS.includes(filter.operator) ? ':' + filter.operator : '';
|
|
1158
|
-
const prefix = PREFIX_OPERATORS.includes(filter.operator) ? filter.operator : '';
|
|
1159
|
-
return `${filter.code}${modifier}=${prefix}${encodeURIComponent(filter.value)}`;
|
|
1160
|
-
}
|
|
1161
|
-
function formatSortRules(sortRules) {
|
|
1162
|
-
if (!sortRules || sortRules.length === 0) {
|
|
1163
|
-
return '';
|
|
1164
|
-
}
|
|
1165
|
-
return '_sort=' + sortRules.map((sr) => (sr.descending ? '-' + sr.code : sr.code)).join(',');
|
|
1166
|
-
}
|
|
1167
|
-
|
|
1168
883
|
var _ClientStorage_storage, _MemoryStorage_data;
|
|
1169
884
|
/**
|
|
1170
885
|
* The ClientStorage class is a utility class for storing strings and objects.
|
|
@@ -1453,7 +1168,7 @@ function getPropertyDisplayName(property) {
|
|
|
1453
1168
|
|
|
1454
1169
|
// PKCE auth ased on:
|
|
1455
1170
|
// https://aws.amazon.com/blogs/security/how-to-add-authentication-single-page-web-application-with-amazon-cognito-oauth2-implementation/
|
|
1456
|
-
var _MedplumClient_instances, _MedplumClient_fetch, _MedplumClient_storage, _MedplumClient_schema, _MedplumClient_requestCache, _MedplumClient_baseUrl, _MedplumClient_clientId, _MedplumClient_authorizeUrl, _MedplumClient_tokenUrl, _MedplumClient_logoutUrl, _MedplumClient_onUnauthenticated, _MedplumClient_accessToken, _MedplumClient_refreshToken, _MedplumClient_refreshPromise, _MedplumClient_profilePromise, _MedplumClient_profile, _MedplumClient_config, _MedplumClient_addLogin, _MedplumClient_refreshProfile, _MedplumClient_request, _MedplumClient_addFetchOptionsDefaults, _MedplumClient_setRequestContentType, _MedplumClient_setRequestBody, _MedplumClient_handleUnauthenticated, _MedplumClient_startPkce, _MedplumClient_requestAuthorization, _MedplumClient_refresh, _MedplumClient_fetchTokens, _MedplumClient_verifyTokens, _MedplumClient_setupStorageListener;
|
|
1171
|
+
var _MedplumClient_instances, _MedplumClient_fetch, _MedplumClient_createPdf, _MedplumClient_storage, _MedplumClient_schema, _MedplumClient_requestCache, _MedplumClient_baseUrl, _MedplumClient_clientId, _MedplumClient_authorizeUrl, _MedplumClient_tokenUrl, _MedplumClient_logoutUrl, _MedplumClient_onUnauthenticated, _MedplumClient_accessToken, _MedplumClient_refreshToken, _MedplumClient_refreshPromise, _MedplumClient_profilePromise, _MedplumClient_profile, _MedplumClient_config, _MedplumClient_addLogin, _MedplumClient_refreshProfile, _MedplumClient_request, _MedplumClient_addFetchOptionsDefaults, _MedplumClient_setRequestContentType, _MedplumClient_setRequestBody, _MedplumClient_handleUnauthenticated, _MedplumClient_startPkce, _MedplumClient_requestAuthorization, _MedplumClient_refresh, _MedplumClient_fetchTokens, _MedplumClient_verifyTokens, _MedplumClient_setupStorageListener;
|
|
1457
1172
|
const DEFAULT_BASE_URL = 'https://api.medplum.com/';
|
|
1458
1173
|
const DEFAULT_SCOPE = 'launch/patient openid fhirUser offline_access user/*.*';
|
|
1459
1174
|
const DEFAULT_RESOURCE_CACHE_SIZE = 1000;
|
|
@@ -1513,6 +1228,7 @@ class MedplumClient extends EventTarget {
|
|
|
1513
1228
|
super();
|
|
1514
1229
|
_MedplumClient_instances.add(this);
|
|
1515
1230
|
_MedplumClient_fetch.set(this, void 0);
|
|
1231
|
+
_MedplumClient_createPdf.set(this, void 0);
|
|
1516
1232
|
_MedplumClient_storage.set(this, void 0);
|
|
1517
1233
|
_MedplumClient_schema.set(this, void 0);
|
|
1518
1234
|
_MedplumClient_requestCache.set(this, void 0);
|
|
@@ -1537,6 +1253,7 @@ class MedplumClient extends EventTarget {
|
|
|
1537
1253
|
}
|
|
1538
1254
|
}
|
|
1539
1255
|
__classPrivateFieldSet(this, _MedplumClient_fetch, (options === null || options === void 0 ? void 0 : options.fetch) || window.fetch.bind(window), "f");
|
|
1256
|
+
__classPrivateFieldSet(this, _MedplumClient_createPdf, options === null || options === void 0 ? void 0 : options.createPdf, "f");
|
|
1540
1257
|
__classPrivateFieldSet(this, _MedplumClient_storage, new ClientStorage(), "f");
|
|
1541
1258
|
__classPrivateFieldSet(this, _MedplumClient_schema, createSchema(), "f");
|
|
1542
1259
|
__classPrivateFieldSet(this, _MedplumClient_requestCache, new LRUCache((_a = options === null || options === void 0 ? void 0 : options.resourceCacheSize) !== null && _a !== void 0 ? _a : DEFAULT_RESOURCE_CACHE_SIZE), "f");
|
|
@@ -1781,12 +1498,9 @@ class MedplumClient extends EventTarget {
|
|
|
1781
1498
|
* @param query The FHIR search query or structured query object.
|
|
1782
1499
|
* @returns The well-formed FHIR URL.
|
|
1783
1500
|
*/
|
|
1784
|
-
fhirSearchUrl(query) {
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
}
|
|
1788
|
-
const url = this.fhirUrl(query.resourceType);
|
|
1789
|
-
url.search = formatSearchQuery(query);
|
|
1501
|
+
fhirSearchUrl(resourceType, query) {
|
|
1502
|
+
const url = this.fhirUrl(resourceType);
|
|
1503
|
+
url.search = query.toString();
|
|
1790
1504
|
return url;
|
|
1791
1505
|
}
|
|
1792
1506
|
/**
|
|
@@ -1843,8 +1557,8 @@ class MedplumClient extends EventTarget {
|
|
|
1843
1557
|
* @param query The search query as either a string or a structured search object.
|
|
1844
1558
|
* @returns Promise to the search result bundle.
|
|
1845
1559
|
*/
|
|
1846
|
-
search(query, options = {}) {
|
|
1847
|
-
return this.get(this.fhirSearchUrl(query), options);
|
|
1560
|
+
search(resourceType, query, options = {}) {
|
|
1561
|
+
return this.get(this.fhirSearchUrl(resourceType, query), options);
|
|
1848
1562
|
}
|
|
1849
1563
|
/**
|
|
1850
1564
|
* Sends a FHIR search request for a single resource.
|
|
@@ -1865,17 +1579,18 @@ class MedplumClient extends EventTarget {
|
|
|
1865
1579
|
* @param query The search query as either a string or a structured search object.
|
|
1866
1580
|
* @returns Promise to the search result bundle.
|
|
1867
1581
|
*/
|
|
1868
|
-
searchOne(query, options = {}) {
|
|
1869
|
-
const
|
|
1870
|
-
|
|
1871
|
-
|
|
1582
|
+
searchOne(resourceType, query, options = {}) {
|
|
1583
|
+
const url = this.fhirSearchUrl(resourceType, query);
|
|
1584
|
+
url.searchParams.set('_count', '1');
|
|
1585
|
+
url.searchParams.sort();
|
|
1586
|
+
const cacheKey = url.toString() + '-searchOne';
|
|
1872
1587
|
if (!(options === null || options === void 0 ? void 0 : options.cache)) {
|
|
1873
1588
|
const cached = __classPrivateFieldGet(this, _MedplumClient_requestCache, "f").get(cacheKey);
|
|
1874
1589
|
if (cached) {
|
|
1875
1590
|
return cached;
|
|
1876
1591
|
}
|
|
1877
1592
|
}
|
|
1878
|
-
const promise = new ReadablePromise(this.search(
|
|
1593
|
+
const promise = new ReadablePromise(this.search(resourceType, url.searchParams, options).then((b) => { var _a, _b; return (_b = (_a = b.entry) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.resource; }));
|
|
1879
1594
|
__classPrivateFieldGet(this, _MedplumClient_requestCache, "f").set(cacheKey, promise);
|
|
1880
1595
|
return promise;
|
|
1881
1596
|
}
|
|
@@ -1898,15 +1613,16 @@ class MedplumClient extends EventTarget {
|
|
|
1898
1613
|
* @param query The search query as either a string or a structured search object.
|
|
1899
1614
|
* @returns Promise to the search result bundle.
|
|
1900
1615
|
*/
|
|
1901
|
-
searchResources(query, options = {}) {
|
|
1902
|
-
const
|
|
1616
|
+
searchResources(resourceType, query, options = {}) {
|
|
1617
|
+
const url = this.fhirSearchUrl(resourceType, query);
|
|
1618
|
+
const cacheKey = url.toString() + '-searchResources';
|
|
1903
1619
|
if (!(options === null || options === void 0 ? void 0 : options.cache)) {
|
|
1904
1620
|
const cached = __classPrivateFieldGet(this, _MedplumClient_requestCache, "f").get(cacheKey);
|
|
1905
1621
|
if (cached) {
|
|
1906
1622
|
return cached;
|
|
1907
1623
|
}
|
|
1908
1624
|
}
|
|
1909
|
-
const promise = new ReadablePromise(this.search(query, options).then((b) => { var _a, _b; return (_b = (_a = b.entry) === null || _a === void 0 ? void 0 : _a.map((e) => e.resource)) !== null && _b !== void 0 ? _b : []; }));
|
|
1625
|
+
const promise = new ReadablePromise(this.search(resourceType, query, options).then((b) => { var _a, _b; return (_b = (_a = b.entry) === null || _a === void 0 ? void 0 : _a.map((e) => e.resource)) !== null && _b !== void 0 ? _b : []; }));
|
|
1910
1626
|
__classPrivateFieldGet(this, _MedplumClient_requestCache, "f").set(cacheKey, promise);
|
|
1911
1627
|
return promise;
|
|
1912
1628
|
}
|
|
@@ -2163,7 +1879,7 @@ class MedplumClient extends EventTarget {
|
|
|
2163
1879
|
createResourceIfNoneExist(resource, query) {
|
|
2164
1880
|
var _a;
|
|
2165
1881
|
return __awaiter(this, void 0, void 0, function* () {
|
|
2166
|
-
return (_a = (yield this.searchOne(
|
|
1882
|
+
return ((_a = (yield this.searchOne(resource.resourceType, query))) !== null && _a !== void 0 ? _a : this.createResource(resource));
|
|
2167
1883
|
});
|
|
2168
1884
|
}
|
|
2169
1885
|
/**
|
|
@@ -2219,7 +1935,10 @@ class MedplumClient extends EventTarget {
|
|
|
2219
1935
|
*/
|
|
2220
1936
|
createPdf(docDefinition, filename, tableLayouts, fonts) {
|
|
2221
1937
|
return __awaiter(this, void 0, void 0, function* () {
|
|
2222
|
-
|
|
1938
|
+
if (!__classPrivateFieldGet(this, _MedplumClient_createPdf, "f")) {
|
|
1939
|
+
throw new Error('PDF creation not enabled');
|
|
1940
|
+
}
|
|
1941
|
+
const blob = yield __classPrivateFieldGet(this, _MedplumClient_createPdf, "f").call(this, docDefinition, tableLayouts, fonts);
|
|
2223
1942
|
return this.createBinary(blob, filename, 'application/pdf');
|
|
2224
1943
|
});
|
|
2225
1944
|
}
|
|
@@ -2482,7 +2201,7 @@ class MedplumClient extends EventTarget {
|
|
|
2482
2201
|
});
|
|
2483
2202
|
}
|
|
2484
2203
|
}
|
|
2485
|
-
_MedplumClient_fetch = new WeakMap(), _MedplumClient_storage = new WeakMap(), _MedplumClient_schema = new WeakMap(), _MedplumClient_requestCache = new WeakMap(), _MedplumClient_baseUrl = new WeakMap(), _MedplumClient_clientId = new WeakMap(), _MedplumClient_authorizeUrl = new WeakMap(), _MedplumClient_tokenUrl = new WeakMap(), _MedplumClient_logoutUrl = new WeakMap(), _MedplumClient_onUnauthenticated = new WeakMap(), _MedplumClient_accessToken = new WeakMap(), _MedplumClient_refreshToken = new WeakMap(), _MedplumClient_refreshPromise = new WeakMap(), _MedplumClient_profilePromise = new WeakMap(), _MedplumClient_profile = new WeakMap(), _MedplumClient_config = new WeakMap(), _MedplumClient_instances = new WeakSet(), _MedplumClient_addLogin = function _MedplumClient_addLogin(newLogin) {
|
|
2204
|
+
_MedplumClient_fetch = new WeakMap(), _MedplumClient_createPdf = new WeakMap(), _MedplumClient_storage = new WeakMap(), _MedplumClient_schema = new WeakMap(), _MedplumClient_requestCache = new WeakMap(), _MedplumClient_baseUrl = new WeakMap(), _MedplumClient_clientId = new WeakMap(), _MedplumClient_authorizeUrl = new WeakMap(), _MedplumClient_tokenUrl = new WeakMap(), _MedplumClient_logoutUrl = new WeakMap(), _MedplumClient_onUnauthenticated = new WeakMap(), _MedplumClient_accessToken = new WeakMap(), _MedplumClient_refreshToken = new WeakMap(), _MedplumClient_refreshPromise = new WeakMap(), _MedplumClient_profilePromise = new WeakMap(), _MedplumClient_profile = new WeakMap(), _MedplumClient_config = new WeakMap(), _MedplumClient_instances = new WeakSet(), _MedplumClient_addLogin = function _MedplumClient_addLogin(newLogin) {
|
|
2486
2205
|
const logins = this.getLogins().filter((login) => { var _a, _b; return ((_a = login.profile) === null || _a === void 0 ? void 0 : _a.reference) !== ((_b = newLogin.profile) === null || _b === void 0 ? void 0 : _b.reference); });
|
|
2487
2206
|
logins.push(newLogin);
|
|
2488
2207
|
__classPrivateFieldGet(this, _MedplumClient_storage, "f").setObject('logins', logins);
|
|
@@ -2552,8 +2271,8 @@ _MedplumClient_fetch = new WeakMap(), _MedplumClient_storage = new WeakMap(), _M
|
|
|
2552
2271
|
}, _MedplumClient_setRequestBody = function _MedplumClient_setRequestBody(options, data) {
|
|
2553
2272
|
if (typeof data === 'string' ||
|
|
2554
2273
|
(typeof Blob !== 'undefined' && data instanceof Blob) ||
|
|
2555
|
-
(typeof
|
|
2556
|
-
(typeof
|
|
2274
|
+
(typeof File !== 'undefined' && data instanceof File) ||
|
|
2275
|
+
(typeof Uint8Array !== 'undefined' && data instanceof Uint8Array)) {
|
|
2557
2276
|
options.body = data;
|
|
2558
2277
|
}
|
|
2559
2278
|
else if (data) {
|
|
@@ -5311,6 +5030,206 @@ class Hl7Field {
|
|
|
5311
5030
|
}
|
|
5312
5031
|
}
|
|
5313
5032
|
|
|
5033
|
+
const DEFAULT_SEARCH_COUNT = 20;
|
|
5034
|
+
/**
|
|
5035
|
+
* Search operators.
|
|
5036
|
+
* These operators represent "modifiers" and "prefixes" in FHIR search.
|
|
5037
|
+
* See: https://www.hl7.org/fhir/search.html
|
|
5038
|
+
*/
|
|
5039
|
+
var Operator;
|
|
5040
|
+
(function (Operator) {
|
|
5041
|
+
Operator["EQUALS"] = "eq";
|
|
5042
|
+
Operator["NOT_EQUALS"] = "ne";
|
|
5043
|
+
// Numbers
|
|
5044
|
+
Operator["GREATER_THAN"] = "gt";
|
|
5045
|
+
Operator["LESS_THAN"] = "lt";
|
|
5046
|
+
Operator["GREATER_THAN_OR_EQUALS"] = "ge";
|
|
5047
|
+
Operator["LESS_THAN_OR_EQUALS"] = "le";
|
|
5048
|
+
// Dates
|
|
5049
|
+
Operator["STARTS_AFTER"] = "sa";
|
|
5050
|
+
Operator["ENDS_BEFORE"] = "eb";
|
|
5051
|
+
Operator["APPROXIMATELY"] = "ap";
|
|
5052
|
+
// String
|
|
5053
|
+
Operator["CONTAINS"] = "contains";
|
|
5054
|
+
Operator["EXACT"] = "exact";
|
|
5055
|
+
// Token
|
|
5056
|
+
Operator["TEXT"] = "text";
|
|
5057
|
+
Operator["ABOVE"] = "above";
|
|
5058
|
+
Operator["BELOW"] = "below";
|
|
5059
|
+
Operator["IN"] = "in";
|
|
5060
|
+
Operator["NOT_IN"] = "not-in";
|
|
5061
|
+
Operator["OF_TYPE"] = "of-type";
|
|
5062
|
+
})(Operator || (Operator = {}));
|
|
5063
|
+
const MODIFIER_OPERATORS = [
|
|
5064
|
+
Operator.CONTAINS,
|
|
5065
|
+
Operator.EXACT,
|
|
5066
|
+
Operator.TEXT,
|
|
5067
|
+
Operator.ABOVE,
|
|
5068
|
+
Operator.BELOW,
|
|
5069
|
+
Operator.IN,
|
|
5070
|
+
Operator.NOT_IN,
|
|
5071
|
+
Operator.OF_TYPE,
|
|
5072
|
+
];
|
|
5073
|
+
const PREFIX_OPERATORS = [
|
|
5074
|
+
Operator.NOT_EQUALS,
|
|
5075
|
+
Operator.GREATER_THAN,
|
|
5076
|
+
Operator.LESS_THAN,
|
|
5077
|
+
Operator.GREATER_THAN_OR_EQUALS,
|
|
5078
|
+
Operator.LESS_THAN_OR_EQUALS,
|
|
5079
|
+
Operator.STARTS_AFTER,
|
|
5080
|
+
Operator.ENDS_BEFORE,
|
|
5081
|
+
Operator.APPROXIMATELY,
|
|
5082
|
+
];
|
|
5083
|
+
/**
|
|
5084
|
+
* Parses a URL into a SearchRequest.
|
|
5085
|
+
*
|
|
5086
|
+
* See the FHIR search spec: http://hl7.org/fhir/r4/search.html
|
|
5087
|
+
*
|
|
5088
|
+
* @param url The URL to parse.
|
|
5089
|
+
* @returns Parsed search definition.
|
|
5090
|
+
*/
|
|
5091
|
+
function parseSearchDefinition(url) {
|
|
5092
|
+
const location = new URL(url, 'https://example.com/');
|
|
5093
|
+
const resourceType = location.pathname
|
|
5094
|
+
.replace(/(^\/)|(\/$)/g, '') // Remove leading and trailing slashes
|
|
5095
|
+
.split('/')
|
|
5096
|
+
.pop();
|
|
5097
|
+
const params = new URLSearchParams(location.search);
|
|
5098
|
+
let filters = undefined;
|
|
5099
|
+
let sortRules = undefined;
|
|
5100
|
+
let fields = undefined;
|
|
5101
|
+
let offset = undefined;
|
|
5102
|
+
let count = undefined;
|
|
5103
|
+
let total = undefined;
|
|
5104
|
+
params.forEach((value, key) => {
|
|
5105
|
+
if (key === '_fields') {
|
|
5106
|
+
fields = value.split(',');
|
|
5107
|
+
}
|
|
5108
|
+
else if (key === '_offset') {
|
|
5109
|
+
offset = parseInt(value);
|
|
5110
|
+
}
|
|
5111
|
+
else if (key === '_count') {
|
|
5112
|
+
count = parseInt(value);
|
|
5113
|
+
}
|
|
5114
|
+
else if (key === '_total') {
|
|
5115
|
+
total = value;
|
|
5116
|
+
}
|
|
5117
|
+
else if (key === '_sort') {
|
|
5118
|
+
sortRules = sortRules || [];
|
|
5119
|
+
sortRules.push(parseSortRule(value));
|
|
5120
|
+
}
|
|
5121
|
+
else {
|
|
5122
|
+
filters = filters || [];
|
|
5123
|
+
filters.push(parseSearchFilter(key, value));
|
|
5124
|
+
}
|
|
5125
|
+
});
|
|
5126
|
+
return {
|
|
5127
|
+
resourceType,
|
|
5128
|
+
filters,
|
|
5129
|
+
fields,
|
|
5130
|
+
offset,
|
|
5131
|
+
count,
|
|
5132
|
+
total,
|
|
5133
|
+
sortRules,
|
|
5134
|
+
};
|
|
5135
|
+
}
|
|
5136
|
+
/**
|
|
5137
|
+
* Parses a URL query parameter into a sort rule.
|
|
5138
|
+
*
|
|
5139
|
+
* By default, the sort rule is the field name.
|
|
5140
|
+
*
|
|
5141
|
+
* Sort rules can be reversed into descending order by prefixing the field name with a minus sign.
|
|
5142
|
+
*
|
|
5143
|
+
* See sorting: http://hl7.org/fhir/r4/search.html#_sort
|
|
5144
|
+
*
|
|
5145
|
+
* @param value The URL parameter value.
|
|
5146
|
+
* @returns The parsed sort rule.
|
|
5147
|
+
*/
|
|
5148
|
+
function parseSortRule(value) {
|
|
5149
|
+
if (value.startsWith('-')) {
|
|
5150
|
+
return { code: value.substring(1), descending: true };
|
|
5151
|
+
}
|
|
5152
|
+
else {
|
|
5153
|
+
return { code: value };
|
|
5154
|
+
}
|
|
5155
|
+
}
|
|
5156
|
+
/**
|
|
5157
|
+
* Parses a URL query parameter into a search filter.
|
|
5158
|
+
*
|
|
5159
|
+
* FHIR search filters can be specified as modifiers or prefixes.
|
|
5160
|
+
*
|
|
5161
|
+
* For string properties, modifiers are appended to the key, e.g. "name:contains=eve".
|
|
5162
|
+
*
|
|
5163
|
+
* For date and numeric properties, prefixes are prepended to the value, e.g. "birthdate=gt2000".
|
|
5164
|
+
*
|
|
5165
|
+
* See the FHIR search spec: http://hl7.org/fhir/r4/search.html
|
|
5166
|
+
*
|
|
5167
|
+
* @param key The URL parameter key.
|
|
5168
|
+
* @param value The URL parameter value.
|
|
5169
|
+
* @returns The parsed search filter.
|
|
5170
|
+
*/
|
|
5171
|
+
function parseSearchFilter(key, value) {
|
|
5172
|
+
let code = key;
|
|
5173
|
+
let operator = Operator.EQUALS;
|
|
5174
|
+
for (const modifier of MODIFIER_OPERATORS) {
|
|
5175
|
+
const modifierIndex = code.indexOf(':' + modifier);
|
|
5176
|
+
if (modifierIndex !== -1) {
|
|
5177
|
+
operator = modifier;
|
|
5178
|
+
code = code.substring(0, modifierIndex);
|
|
5179
|
+
}
|
|
5180
|
+
}
|
|
5181
|
+
for (const prefix of PREFIX_OPERATORS) {
|
|
5182
|
+
if (value.match(new RegExp('^' + prefix + '\\d'))) {
|
|
5183
|
+
operator = prefix;
|
|
5184
|
+
value = value.substring(prefix.length);
|
|
5185
|
+
}
|
|
5186
|
+
}
|
|
5187
|
+
return { code, operator, value };
|
|
5188
|
+
}
|
|
5189
|
+
/**
|
|
5190
|
+
* Formats a search definition object into a query string.
|
|
5191
|
+
* Note: The return value does not include the resource type.
|
|
5192
|
+
* @param {!SearchRequest} definition The search definition.
|
|
5193
|
+
* @returns Formatted URL.
|
|
5194
|
+
*/
|
|
5195
|
+
function formatSearchQuery(definition) {
|
|
5196
|
+
const params = [];
|
|
5197
|
+
if (definition.fields) {
|
|
5198
|
+
params.push('_fields=' + definition.fields.join(','));
|
|
5199
|
+
}
|
|
5200
|
+
if (definition.filters) {
|
|
5201
|
+
definition.filters.forEach((filter) => params.push(formatFilter(filter)));
|
|
5202
|
+
}
|
|
5203
|
+
if (definition.sortRules && definition.sortRules.length > 0) {
|
|
5204
|
+
params.push(formatSortRules(definition.sortRules));
|
|
5205
|
+
}
|
|
5206
|
+
if (definition.offset !== undefined) {
|
|
5207
|
+
params.push('_offset=' + definition.offset);
|
|
5208
|
+
}
|
|
5209
|
+
if (definition.count !== undefined) {
|
|
5210
|
+
params.push('_count=' + definition.count);
|
|
5211
|
+
}
|
|
5212
|
+
if (definition.total !== undefined) {
|
|
5213
|
+
params.push('_total=' + definition.total);
|
|
5214
|
+
}
|
|
5215
|
+
if (params.length === 0) {
|
|
5216
|
+
return '';
|
|
5217
|
+
}
|
|
5218
|
+
params.sort();
|
|
5219
|
+
return '?' + params.join('&');
|
|
5220
|
+
}
|
|
5221
|
+
function formatFilter(filter) {
|
|
5222
|
+
const modifier = MODIFIER_OPERATORS.includes(filter.operator) ? ':' + filter.operator : '';
|
|
5223
|
+
const prefix = PREFIX_OPERATORS.includes(filter.operator) ? filter.operator : '';
|
|
5224
|
+
return `${filter.code}${modifier}=${prefix}${encodeURIComponent(filter.value)}`;
|
|
5225
|
+
}
|
|
5226
|
+
function formatSortRules(sortRules) {
|
|
5227
|
+
if (!sortRules || sortRules.length === 0) {
|
|
5228
|
+
return '';
|
|
5229
|
+
}
|
|
5230
|
+
return '_sort=' + sortRules.map((sr) => (sr.descending ? '-' + sr.code : sr.code)).join(',');
|
|
5231
|
+
}
|
|
5232
|
+
|
|
5314
5233
|
var SearchParameterType;
|
|
5315
5234
|
(function (SearchParameterType) {
|
|
5316
5235
|
SearchParameterType["BOOLEAN"] = "BOOLEAN";
|