@openfn/language-fhir-4 0.4.0 → 0.4.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.
Files changed (3) hide show
  1. package/dist/index.cjs +76 -27
  2. package/dist/index.js +1319 -1270
  3. package/package.json +2 -1
package/dist/index.cjs CHANGED
@@ -79,6 +79,7 @@ var import_util2 = require("@openfn/language-common/util");
79
79
 
80
80
  // src/util.ts
81
81
  var import_node_path = __toESM(require("path"), 1);
82
+ var import_lodash_es = __toESM(require("lodash-es"), 1);
82
83
  var import_language_common = require("@openfn/language-common");
83
84
  var import_util = require("@openfn/language-common/util");
84
85
  function assertValidResourceId(id2) {
@@ -102,7 +103,7 @@ function addAuth(options) {
102
103
  return {};
103
104
  }
104
105
  var prepareNextState = (state, response) => {
105
- const { body, ...responseWithoutBody } = response;
106
+ const { body, validationErrors, ...responseWithoutBody } = response;
106
107
  return {
107
108
  ...(0, import_language_common.composeNextState)(state, body),
108
109
  response: responseWithoutBody
@@ -117,11 +118,11 @@ var logResponse = (response, query) => {
117
118
  }
118
119
  const message = `${method} ${urlWithQuery} - ${statusCode} in ${duration}ms`;
119
120
  if (response instanceof Error) {
120
- logger.error(message);
121
- logger.error("response body: ");
122
- logger.error(response.body || "[no body]");
121
+ console.error(message);
122
+ console.error("response body: ");
123
+ console.error(response.body || "[no body]");
123
124
  } else {
124
- logger.log(message);
125
+ console.log(message);
125
126
  }
126
127
  }
127
128
  return response;
@@ -146,63 +147,102 @@ var request = (method, path, options) => {
146
147
  };
147
148
  return (0, import_util.request)(method, fullPath, opts).then(logResponse).then().catch(async (e) => {
148
149
  if (e.headers && "content-type" in e.headers && e.headers["content-type"].match(/fhir\+json/)) {
149
- logValidationErrors(e);
150
+ logValidationErrors(e, opts.body);
150
151
  }
151
152
  throw e;
152
153
  });
153
154
  };
154
- function logValidationErrors(response, logger2 = console) {
155
+ function logValidationErrors(response, payload, logger = console) {
155
156
  const error = JSON.parse(response.body);
156
157
  if (error.issue && error.issue.length) {
157
158
  delete response.body;
158
- logger2.log();
159
- logger2.error("FHIR server reports validation issues:");
159
+ logger.log();
160
+ logger.error("FHIR server reports validation issues:");
160
161
  const errCount = error.issue.reduce(
161
162
  (count, e) => e.severity === "error" ? count + 1 : count,
162
163
  0
163
164
  );
164
165
  if (errCount) {
165
- logger2.error(` - ${errCount} Errors`);
166
+ logger.error(` - ${errCount} Errors`);
166
167
  }
167
168
  const warnCount = error.issue.reduce(
168
169
  (count, e) => e.severity === "error" ? count + 1 : count,
169
170
  0
170
171
  );
171
172
  if (warnCount) {
172
- logger2.error(` - ${warnCount} Warnings`);
173
+ logger.error(` - ${warnCount} Warnings`);
173
174
  }
174
- logger2.log();
175
+ logger.log();
175
176
  const groups = {};
176
177
  error.issue.forEach((issue) => {
177
- var _a, _b;
178
+ var _a, _b, _c;
178
179
  try {
179
- let id2 = issue.location[0];
180
- if (id2.startsWith("Bundle")) {
181
- id2 = id2.split("*").at(1);
180
+ let resourceId = "unidentified resource";
181
+ if (issue.location) {
182
+ let idx = issue.location[0].match(/Bundle.entry\[(\d+)\]/);
183
+ if (idx && idx.length >= 2) {
184
+ idx = idx[1];
185
+ const resource = (_a = import_lodash_es.default.get(payload, `entry[${idx}]`)) == null ? void 0 : _a.resource;
186
+ if (resource) {
187
+ resourceId = `${resource.resourceType}/${resource.id}`;
188
+ }
189
+ } else {
190
+ if (payload.resourceType && payload.id) {
191
+ resourceId = `${payload.resourceType}/${payload.id}`;
192
+ }
193
+ }
194
+ }
195
+ const type = `${issue.severity}s`;
196
+ groups[resourceId] ?? (groups[resourceId] = {});
197
+ let path = "*";
198
+ if (issue.location[0].match(/\.resource\./)) {
199
+ path = issue.location[0].split(/\.resource\./)[1];
200
+ } else if (issue.location.includes(`*${resourceId}*`)) {
201
+ const suffix = issue.location[0].split(/\.resource\./)[1];
202
+ if (suffix && suffix.length > 1) {
203
+ path = suffix;
204
+ }
182
205
  }
183
- groups[id2] ?? (groups[id2] = {});
184
- (_a = groups[id2])[_b = issue.severity] ?? (_a[_b] = []);
185
- groups[id2][issue.severity].push(issue.diagnostics);
206
+ (_b = groups[resourceId])[type] ?? (_b[type] = {});
207
+ (_c = groups[resourceId][type])[path] ?? (_c[path] = []);
208
+ groups[resourceId][type][path].push(issue.diagnostics);
186
209
  } catch (e) {
187
- logger2.log("error parsing issue at ", issue.location);
210
+ logger.log("error parsing issue at ", issue.location);
211
+ console.log(e);
188
212
  }
189
213
  });
190
214
  for (const resource in groups) {
191
- logger2.log(`${resource} issues:`);
192
- ["error", "warning"].forEach((type) => {
193
- logger2.log(` ${type}s:`.toUpperCase());
194
- for (const e of groups[resource][type]) {
195
- logger2.log(" -", e);
215
+ logger.log(`${resource} issues:`);
216
+ ["errors", "warnings"].forEach((type) => {
217
+ if (type in groups[resource]) {
218
+ logger.log(` ${type}:`.toUpperCase());
219
+ for (const path in groups[resource][type]) {
220
+ logger.log();
221
+ logger.log(" ", path);
222
+ for (const message of groups[resource][type][path]) {
223
+ const fn2 = type === "error" ? console.error : console.warn;
224
+ fn2(" -", message);
225
+ }
226
+ }
227
+ logger.log();
196
228
  }
197
- logger2.log();
198
229
  });
199
230
  }
200
- response.validationIssues = groups;
231
+ logger.log("Issues will be written to state.fhirValidationIssues");
232
+ response.$validationIssues = groups;
201
233
  } else {
202
234
  response.body = error;
203
235
  }
204
236
  return response;
205
237
  }
238
+ function cleanResponseObject(state, response) {
239
+ if (response.$validationIssues) {
240
+ state.fhirValidationIssues ?? (state.fhirValidationIssues = {});
241
+ Object.assign(state.fhirValidationIssues, response.$validationIssues);
242
+ delete response.$validationIssues;
243
+ }
244
+ return state;
245
+ }
206
246
  function collectRefs(value2) {
207
247
  if (!value2 || typeof value2 !== "object")
208
248
  return [];
@@ -369,6 +409,9 @@ function create(resource) {
369
409
  const response = await request("POST", $resource.resourceType, {
370
410
  configuration: state.configuration,
371
411
  body: $resource
412
+ }).catch((e) => {
413
+ cleanResponseObject(state, e);
414
+ throw e;
372
415
  });
373
416
  console.log(`Created ${response.body.id}`);
374
417
  return prepareNextState(state, response);
@@ -433,6 +476,9 @@ function uploadBundle(bundle = "bundle") {
433
476
  const response = await request("POST", "/", {
434
477
  configuration: state.configuration,
435
478
  body: data
479
+ }).catch((e) => {
480
+ cleanResponseObject(state, e);
481
+ throw e;
436
482
  });
437
483
  return prepareNextState(state, response);
438
484
  };
@@ -785,6 +831,9 @@ var composite = (object, key, value2) => {
785
831
  k.push("CodeableConcept");
786
832
  } else if (value2.reference) {
787
833
  k.push("Reference");
834
+ }
835
+ if (value2.value && typeof value2.value === "number") {
836
+ k.push("Quantity");
788
837
  } else if (value2.id && value2.meta && value2.resourceType) {
789
838
  k.push("Reference");
790
839
  value2 = reference(value2);