oro-sdk 3.2.0 → 3.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1 +1 @@
1
- {"version":3,"file":"oro-sdk.cjs.production.min.js","sources":["../node_modules/regenerator-runtime/runtime.js","../src/helpers/client.ts","../src/models/error.ts","../src/helpers/workflow.ts","../src/helpers/patient-registration.ts","../src/helpers/vault-grants.ts","../src/sdk-revision/client.ts","../src/client.ts","../src/services/external/clinia.ts","../src/index.ts"],"sourcesContent":["/**\n * Copyright (c) 2014-present, Facebook, Inc.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nvar runtime = (function (exports) {\n \"use strict\";\n\n var Op = Object.prototype;\n var hasOwn = Op.hasOwnProperty;\n var undefined; // More compressible than void 0.\n var $Symbol = typeof Symbol === \"function\" ? Symbol : {};\n var iteratorSymbol = $Symbol.iterator || \"@@iterator\";\n var asyncIteratorSymbol = $Symbol.asyncIterator || \"@@asyncIterator\";\n var toStringTagSymbol = $Symbol.toStringTag || \"@@toStringTag\";\n\n function define(obj, key, value) {\n Object.defineProperty(obj, key, {\n value: value,\n enumerable: true,\n configurable: true,\n writable: true\n });\n return obj[key];\n }\n try {\n // IE 8 has a broken Object.defineProperty that only works on DOM objects.\n define({}, \"\");\n } catch (err) {\n define = function(obj, key, value) {\n return obj[key] = value;\n };\n }\n\n function wrap(innerFn, outerFn, self, tryLocsList) {\n // If outerFn provided and outerFn.prototype is a Generator, then outerFn.prototype instanceof Generator.\n var protoGenerator = outerFn && outerFn.prototype instanceof Generator ? outerFn : Generator;\n var generator = Object.create(protoGenerator.prototype);\n var context = new Context(tryLocsList || []);\n\n // The ._invoke method unifies the implementations of the .next,\n // .throw, and .return methods.\n generator._invoke = makeInvokeMethod(innerFn, self, context);\n\n return generator;\n }\n exports.wrap = wrap;\n\n // Try/catch helper to minimize deoptimizations. Returns a completion\n // record like context.tryEntries[i].completion. This interface could\n // have been (and was previously) designed to take a closure to be\n // invoked without arguments, but in all the cases we care about we\n // already have an existing method we want to call, so there's no need\n // to create a new function object. We can even get away with assuming\n // the method takes exactly one argument, since that happens to be true\n // in every case, so we don't have to touch the arguments object. The\n // only additional allocation required is the completion record, which\n // has a stable shape and so hopefully should be cheap to allocate.\n function tryCatch(fn, obj, arg) {\n try {\n return { type: \"normal\", arg: fn.call(obj, arg) };\n } catch (err) {\n return { type: \"throw\", arg: err };\n }\n }\n\n var GenStateSuspendedStart = \"suspendedStart\";\n var GenStateSuspendedYield = \"suspendedYield\";\n var GenStateExecuting = \"executing\";\n var GenStateCompleted = \"completed\";\n\n // Returning this object from the innerFn has the same effect as\n // breaking out of the dispatch switch statement.\n var ContinueSentinel = {};\n\n // Dummy constructor functions that we use as the .constructor and\n // .constructor.prototype properties for functions that return Generator\n // objects. For full spec compliance, you may wish to configure your\n // minifier not to mangle the names of these two functions.\n function Generator() {}\n function GeneratorFunction() {}\n function GeneratorFunctionPrototype() {}\n\n // This is a polyfill for %IteratorPrototype% for environments that\n // don't natively support it.\n var IteratorPrototype = {};\n define(IteratorPrototype, iteratorSymbol, function () {\n return this;\n });\n\n var getProto = Object.getPrototypeOf;\n var NativeIteratorPrototype = getProto && getProto(getProto(values([])));\n if (NativeIteratorPrototype &&\n NativeIteratorPrototype !== Op &&\n hasOwn.call(NativeIteratorPrototype, iteratorSymbol)) {\n // This environment has a native %IteratorPrototype%; use it instead\n // of the polyfill.\n IteratorPrototype = NativeIteratorPrototype;\n }\n\n var Gp = GeneratorFunctionPrototype.prototype =\n Generator.prototype = Object.create(IteratorPrototype);\n GeneratorFunction.prototype = GeneratorFunctionPrototype;\n define(Gp, \"constructor\", GeneratorFunctionPrototype);\n define(GeneratorFunctionPrototype, \"constructor\", GeneratorFunction);\n GeneratorFunction.displayName = define(\n GeneratorFunctionPrototype,\n toStringTagSymbol,\n \"GeneratorFunction\"\n );\n\n // Helper for defining the .next, .throw, and .return methods of the\n // Iterator interface in terms of a single ._invoke method.\n function defineIteratorMethods(prototype) {\n [\"next\", \"throw\", \"return\"].forEach(function(method) {\n define(prototype, method, function(arg) {\n return this._invoke(method, arg);\n });\n });\n }\n\n exports.isGeneratorFunction = function(genFun) {\n var ctor = typeof genFun === \"function\" && genFun.constructor;\n return ctor\n ? ctor === GeneratorFunction ||\n // For the native GeneratorFunction constructor, the best we can\n // do is to check its .name property.\n (ctor.displayName || ctor.name) === \"GeneratorFunction\"\n : false;\n };\n\n exports.mark = function(genFun) {\n if (Object.setPrototypeOf) {\n Object.setPrototypeOf(genFun, GeneratorFunctionPrototype);\n } else {\n genFun.__proto__ = GeneratorFunctionPrototype;\n define(genFun, toStringTagSymbol, \"GeneratorFunction\");\n }\n genFun.prototype = Object.create(Gp);\n return genFun;\n };\n\n // Within the body of any async function, `await x` is transformed to\n // `yield regeneratorRuntime.awrap(x)`, so that the runtime can test\n // `hasOwn.call(value, \"__await\")` to determine if the yielded value is\n // meant to be awaited.\n exports.awrap = function(arg) {\n return { __await: arg };\n };\n\n function AsyncIterator(generator, PromiseImpl) {\n function invoke(method, arg, resolve, reject) {\n var record = tryCatch(generator[method], generator, arg);\n if (record.type === \"throw\") {\n reject(record.arg);\n } else {\n var result = record.arg;\n var value = result.value;\n if (value &&\n typeof value === \"object\" &&\n hasOwn.call(value, \"__await\")) {\n return PromiseImpl.resolve(value.__await).then(function(value) {\n invoke(\"next\", value, resolve, reject);\n }, function(err) {\n invoke(\"throw\", err, resolve, reject);\n });\n }\n\n return PromiseImpl.resolve(value).then(function(unwrapped) {\n // When a yielded Promise is resolved, its final value becomes\n // the .value of the Promise<{value,done}> result for the\n // current iteration.\n result.value = unwrapped;\n resolve(result);\n }, function(error) {\n // If a rejected Promise was yielded, throw the rejection back\n // into the async generator function so it can be handled there.\n return invoke(\"throw\", error, resolve, reject);\n });\n }\n }\n\n var previousPromise;\n\n function enqueue(method, arg) {\n function callInvokeWithMethodAndArg() {\n return new PromiseImpl(function(resolve, reject) {\n invoke(method, arg, resolve, reject);\n });\n }\n\n return previousPromise =\n // If enqueue has been called before, then we want to wait until\n // all previous Promises have been resolved before calling invoke,\n // so that results are always delivered in the correct order. If\n // enqueue has not been called before, then it is important to\n // call invoke immediately, without waiting on a callback to fire,\n // so that the async generator function has the opportunity to do\n // any necessary setup in a predictable way. This predictability\n // is why the Promise constructor synchronously invokes its\n // executor callback, and why async functions synchronously\n // execute code before the first await. Since we implement simple\n // async functions in terms of async generators, it is especially\n // important to get this right, even though it requires care.\n previousPromise ? previousPromise.then(\n callInvokeWithMethodAndArg,\n // Avoid propagating failures to Promises returned by later\n // invocations of the iterator.\n callInvokeWithMethodAndArg\n ) : callInvokeWithMethodAndArg();\n }\n\n // Define the unified helper method that is used to implement .next,\n // .throw, and .return (see defineIteratorMethods).\n this._invoke = enqueue;\n }\n\n defineIteratorMethods(AsyncIterator.prototype);\n define(AsyncIterator.prototype, asyncIteratorSymbol, function () {\n return this;\n });\n exports.AsyncIterator = AsyncIterator;\n\n // Note that simple async functions are implemented on top of\n // AsyncIterator objects; they just return a Promise for the value of\n // the final result produced by the iterator.\n exports.async = function(innerFn, outerFn, self, tryLocsList, PromiseImpl) {\n if (PromiseImpl === void 0) PromiseImpl = Promise;\n\n var iter = new AsyncIterator(\n wrap(innerFn, outerFn, self, tryLocsList),\n PromiseImpl\n );\n\n return exports.isGeneratorFunction(outerFn)\n ? iter // If outerFn is a generator, return the full iterator.\n : iter.next().then(function(result) {\n return result.done ? result.value : iter.next();\n });\n };\n\n function makeInvokeMethod(innerFn, self, context) {\n var state = GenStateSuspendedStart;\n\n return function invoke(method, arg) {\n if (state === GenStateExecuting) {\n throw new Error(\"Generator is already running\");\n }\n\n if (state === GenStateCompleted) {\n if (method === \"throw\") {\n throw arg;\n }\n\n // Be forgiving, per 25.3.3.3.3 of the spec:\n // https://people.mozilla.org/~jorendorff/es6-draft.html#sec-generatorresume\n return doneResult();\n }\n\n context.method = method;\n context.arg = arg;\n\n while (true) {\n var delegate = context.delegate;\n if (delegate) {\n var delegateResult = maybeInvokeDelegate(delegate, context);\n if (delegateResult) {\n if (delegateResult === ContinueSentinel) continue;\n return delegateResult;\n }\n }\n\n if (context.method === \"next\") {\n // Setting context._sent for legacy support of Babel's\n // function.sent implementation.\n context.sent = context._sent = context.arg;\n\n } else if (context.method === \"throw\") {\n if (state === GenStateSuspendedStart) {\n state = GenStateCompleted;\n throw context.arg;\n }\n\n context.dispatchException(context.arg);\n\n } else if (context.method === \"return\") {\n context.abrupt(\"return\", context.arg);\n }\n\n state = GenStateExecuting;\n\n var record = tryCatch(innerFn, self, context);\n if (record.type === \"normal\") {\n // If an exception is thrown from innerFn, we leave state ===\n // GenStateExecuting and loop back for another invocation.\n state = context.done\n ? GenStateCompleted\n : GenStateSuspendedYield;\n\n if (record.arg === ContinueSentinel) {\n continue;\n }\n\n return {\n value: record.arg,\n done: context.done\n };\n\n } else if (record.type === \"throw\") {\n state = GenStateCompleted;\n // Dispatch the exception by looping back around to the\n // context.dispatchException(context.arg) call above.\n context.method = \"throw\";\n context.arg = record.arg;\n }\n }\n };\n }\n\n // Call delegate.iterator[context.method](context.arg) and handle the\n // result, either by returning a { value, done } result from the\n // delegate iterator, or by modifying context.method and context.arg,\n // setting context.delegate to null, and returning the ContinueSentinel.\n function maybeInvokeDelegate(delegate, context) {\n var method = delegate.iterator[context.method];\n if (method === undefined) {\n // A .throw or .return when the delegate iterator has no .throw\n // method always terminates the yield* loop.\n context.delegate = null;\n\n if (context.method === \"throw\") {\n // Note: [\"return\"] must be used for ES3 parsing compatibility.\n if (delegate.iterator[\"return\"]) {\n // If the delegate iterator has a return method, give it a\n // chance to clean up.\n context.method = \"return\";\n context.arg = undefined;\n maybeInvokeDelegate(delegate, context);\n\n if (context.method === \"throw\") {\n // If maybeInvokeDelegate(context) changed context.method from\n // \"return\" to \"throw\", let that override the TypeError below.\n return ContinueSentinel;\n }\n }\n\n context.method = \"throw\";\n context.arg = new TypeError(\n \"The iterator does not provide a 'throw' method\");\n }\n\n return ContinueSentinel;\n }\n\n var record = tryCatch(method, delegate.iterator, context.arg);\n\n if (record.type === \"throw\") {\n context.method = \"throw\";\n context.arg = record.arg;\n context.delegate = null;\n return ContinueSentinel;\n }\n\n var info = record.arg;\n\n if (! info) {\n context.method = \"throw\";\n context.arg = new TypeError(\"iterator result is not an object\");\n context.delegate = null;\n return ContinueSentinel;\n }\n\n if (info.done) {\n // Assign the result of the finished delegate to the temporary\n // variable specified by delegate.resultName (see delegateYield).\n context[delegate.resultName] = info.value;\n\n // Resume execution at the desired location (see delegateYield).\n context.next = delegate.nextLoc;\n\n // If context.method was \"throw\" but the delegate handled the\n // exception, let the outer generator proceed normally. If\n // context.method was \"next\", forget context.arg since it has been\n // \"consumed\" by the delegate iterator. If context.method was\n // \"return\", allow the original .return call to continue in the\n // outer generator.\n if (context.method !== \"return\") {\n context.method = \"next\";\n context.arg = undefined;\n }\n\n } else {\n // Re-yield the result returned by the delegate method.\n return info;\n }\n\n // The delegate iterator is finished, so forget it and continue with\n // the outer generator.\n context.delegate = null;\n return ContinueSentinel;\n }\n\n // Define Generator.prototype.{next,throw,return} in terms of the\n // unified ._invoke helper method.\n defineIteratorMethods(Gp);\n\n define(Gp, toStringTagSymbol, \"Generator\");\n\n // A Generator should always return itself as the iterator object when the\n // @@iterator function is called on it. Some browsers' implementations of the\n // iterator prototype chain incorrectly implement this, causing the Generator\n // object to not be returned from this call. This ensures that doesn't happen.\n // See https://github.com/facebook/regenerator/issues/274 for more details.\n define(Gp, iteratorSymbol, function() {\n return this;\n });\n\n define(Gp, \"toString\", function() {\n return \"[object Generator]\";\n });\n\n function pushTryEntry(locs) {\n var entry = { tryLoc: locs[0] };\n\n if (1 in locs) {\n entry.catchLoc = locs[1];\n }\n\n if (2 in locs) {\n entry.finallyLoc = locs[2];\n entry.afterLoc = locs[3];\n }\n\n this.tryEntries.push(entry);\n }\n\n function resetTryEntry(entry) {\n var record = entry.completion || {};\n record.type = \"normal\";\n delete record.arg;\n entry.completion = record;\n }\n\n function Context(tryLocsList) {\n // The root entry object (effectively a try statement without a catch\n // or a finally block) gives us a place to store values thrown from\n // locations where there is no enclosing try statement.\n this.tryEntries = [{ tryLoc: \"root\" }];\n tryLocsList.forEach(pushTryEntry, this);\n this.reset(true);\n }\n\n exports.keys = function(object) {\n var keys = [];\n for (var key in object) {\n keys.push(key);\n }\n keys.reverse();\n\n // Rather than returning an object with a next method, we keep\n // things simple and return the next function itself.\n return function next() {\n while (keys.length) {\n var key = keys.pop();\n if (key in object) {\n next.value = key;\n next.done = false;\n return next;\n }\n }\n\n // To avoid creating an additional object, we just hang the .value\n // and .done properties off the next function object itself. This\n // also ensures that the minifier will not anonymize the function.\n next.done = true;\n return next;\n };\n };\n\n function values(iterable) {\n if (iterable) {\n var iteratorMethod = iterable[iteratorSymbol];\n if (iteratorMethod) {\n return iteratorMethod.call(iterable);\n }\n\n if (typeof iterable.next === \"function\") {\n return iterable;\n }\n\n if (!isNaN(iterable.length)) {\n var i = -1, next = function next() {\n while (++i < iterable.length) {\n if (hasOwn.call(iterable, i)) {\n next.value = iterable[i];\n next.done = false;\n return next;\n }\n }\n\n next.value = undefined;\n next.done = true;\n\n return next;\n };\n\n return next.next = next;\n }\n }\n\n // Return an iterator with no values.\n return { next: doneResult };\n }\n exports.values = values;\n\n function doneResult() {\n return { value: undefined, done: true };\n }\n\n Context.prototype = {\n constructor: Context,\n\n reset: function(skipTempReset) {\n this.prev = 0;\n this.next = 0;\n // Resetting context._sent for legacy support of Babel's\n // function.sent implementation.\n this.sent = this._sent = undefined;\n this.done = false;\n this.delegate = null;\n\n this.method = \"next\";\n this.arg = undefined;\n\n this.tryEntries.forEach(resetTryEntry);\n\n if (!skipTempReset) {\n for (var name in this) {\n // Not sure about the optimal order of these conditions:\n if (name.charAt(0) === \"t\" &&\n hasOwn.call(this, name) &&\n !isNaN(+name.slice(1))) {\n this[name] = undefined;\n }\n }\n }\n },\n\n stop: function() {\n this.done = true;\n\n var rootEntry = this.tryEntries[0];\n var rootRecord = rootEntry.completion;\n if (rootRecord.type === \"throw\") {\n throw rootRecord.arg;\n }\n\n return this.rval;\n },\n\n dispatchException: function(exception) {\n if (this.done) {\n throw exception;\n }\n\n var context = this;\n function handle(loc, caught) {\n record.type = \"throw\";\n record.arg = exception;\n context.next = loc;\n\n if (caught) {\n // If the dispatched exception was caught by a catch block,\n // then let that catch block handle the exception normally.\n context.method = \"next\";\n context.arg = undefined;\n }\n\n return !! caught;\n }\n\n for (var i = this.tryEntries.length - 1; i >= 0; --i) {\n var entry = this.tryEntries[i];\n var record = entry.completion;\n\n if (entry.tryLoc === \"root\") {\n // Exception thrown outside of any try block that could handle\n // it, so set the completion value of the entire function to\n // throw the exception.\n return handle(\"end\");\n }\n\n if (entry.tryLoc <= this.prev) {\n var hasCatch = hasOwn.call(entry, \"catchLoc\");\n var hasFinally = hasOwn.call(entry, \"finallyLoc\");\n\n if (hasCatch && hasFinally) {\n if (this.prev < entry.catchLoc) {\n return handle(entry.catchLoc, true);\n } else if (this.prev < entry.finallyLoc) {\n return handle(entry.finallyLoc);\n }\n\n } else if (hasCatch) {\n if (this.prev < entry.catchLoc) {\n return handle(entry.catchLoc, true);\n }\n\n } else if (hasFinally) {\n if (this.prev < entry.finallyLoc) {\n return handle(entry.finallyLoc);\n }\n\n } else {\n throw new Error(\"try statement without catch or finally\");\n }\n }\n }\n },\n\n abrupt: function(type, arg) {\n for (var i = this.tryEntries.length - 1; i >= 0; --i) {\n var entry = this.tryEntries[i];\n if (entry.tryLoc <= this.prev &&\n hasOwn.call(entry, \"finallyLoc\") &&\n this.prev < entry.finallyLoc) {\n var finallyEntry = entry;\n break;\n }\n }\n\n if (finallyEntry &&\n (type === \"break\" ||\n type === \"continue\") &&\n finallyEntry.tryLoc <= arg &&\n arg <= finallyEntry.finallyLoc) {\n // Ignore the finally entry if control is not jumping to a\n // location outside the try/catch block.\n finallyEntry = null;\n }\n\n var record = finallyEntry ? finallyEntry.completion : {};\n record.type = type;\n record.arg = arg;\n\n if (finallyEntry) {\n this.method = \"next\";\n this.next = finallyEntry.finallyLoc;\n return ContinueSentinel;\n }\n\n return this.complete(record);\n },\n\n complete: function(record, afterLoc) {\n if (record.type === \"throw\") {\n throw record.arg;\n }\n\n if (record.type === \"break\" ||\n record.type === \"continue\") {\n this.next = record.arg;\n } else if (record.type === \"return\") {\n this.rval = this.arg = record.arg;\n this.method = \"return\";\n this.next = \"end\";\n } else if (record.type === \"normal\" && afterLoc) {\n this.next = afterLoc;\n }\n\n return ContinueSentinel;\n },\n\n finish: function(finallyLoc) {\n for (var i = this.tryEntries.length - 1; i >= 0; --i) {\n var entry = this.tryEntries[i];\n if (entry.finallyLoc === finallyLoc) {\n this.complete(entry.completion, entry.afterLoc);\n resetTryEntry(entry);\n return ContinueSentinel;\n }\n }\n },\n\n \"catch\": function(tryLoc) {\n for (var i = this.tryEntries.length - 1; i >= 0; --i) {\n var entry = this.tryEntries[i];\n if (entry.tryLoc === tryLoc) {\n var record = entry.completion;\n if (record.type === \"throw\") {\n var thrown = record.arg;\n resetTryEntry(entry);\n }\n return thrown;\n }\n }\n\n // The context.catch method must only be called with a location\n // argument that corresponds to a known catch block.\n throw new Error(\"illegal catch attempt\");\n },\n\n delegateYield: function(iterable, resultName, nextLoc) {\n this.delegate = {\n iterator: values(iterable),\n resultName: resultName,\n nextLoc: nextLoc\n };\n\n if (this.method === \"next\") {\n // Deliberately forget the last sent value so that we don't\n // accidentally pass it on to the delegate.\n this.arg = undefined;\n }\n\n return ContinueSentinel;\n }\n };\n\n // Regardless of whether this script is executing as a CommonJS module\n // or not, return the runtime object so that we can declare the variable\n // regeneratorRuntime in the outer scope, which allows this module to be\n // injected easily by `bin/regenerator --include-runtime script.js`.\n return exports;\n\n}(\n // If this script is executing as a CommonJS module, use module.exports\n // as the regeneratorRuntime namespace. Otherwise create a new empty\n // object. Either way, the resulting object will be used to initialize\n // the regeneratorRuntime variable at the top of this file.\n typeof module === \"object\" ? module.exports : {}\n));\n\ntry {\n regeneratorRuntime = runtime;\n} catch (accidentalStrictMode) {\n // This module should not be running in strict mode, so the above\n // assignment should always work unless something is misconfigured. Just\n // in case runtime.js accidentally runs in strict mode, in modern engines\n // we can explicitly access globalThis. In older engines we can escape\n // strict mode using a global Function call. This could conceivably fail\n // if a Content Security Policy forbids using Function, but in that case\n // the proper solution is to fix the accidental strict mode problem. If\n // you've misconfigured your bundler to force strict mode and applied a\n // CSP to forbid Function, and you're not willing to fix either of those\n // problems, please detail your unique predicament in a GitHub issue.\n if (typeof globalThis === \"object\") {\n globalThis.regeneratorRuntime = runtime;\n } else {\n Function(\"r\", \"regeneratorRuntime = r\")(runtime);\n }\n}\n","import {\n PopulatedWorkflowData,\n MetadataCategory,\n SelectedAnswersData,\n} from 'oro-sdk-apis'\nimport { PersonalInformations } from '../models/client'\n\nconst personalMetaToPrefix = {\n [MetadataCategory.Personal]: 'you',\n [MetadataCategory.ChildPersonal]: 'child',\n [MetadataCategory.OtherPersonal]: 'other',\n}\n\n/**\n * This function extract PersonalInformations from data input object coming from workflow\n * @param data extracted from WorkflowData\n * @returns PersonalInformations of a patient\n */\nexport function identificationToPersonalInformations(\n data: any,\n category:\n | MetadataCategory.Personal\n | MetadataCategory.ChildPersonal\n | MetadataCategory.OtherPersonal\n): PersonalInformations {\n const prefix = personalMetaToPrefix[category]\n\n return {\n birthday: data[`${prefix}Birthday`],\n firstname: data[`${prefix}Firstname`],\n gender: data[`${prefix}Gender`],\n name: data[`${prefix}Name`],\n phone: data[`${prefix}Phone`],\n zip: data[`${prefix}Zip`],\n hid: data[`${prefix}HID`] ?? data[`${prefix}ID`], // This is done for backward compatibility (historically youID was used)\n pharmacy: data[`${prefix}Pharmacy`],\n address: data[`${prefix}Address`],\n }\n}\n\nexport function toActualObject(data: PopulatedWorkflowData) {\n const ret: any = {}\n\n Object.entries(data.fields).forEach(([key, field]) => {\n ret[key] = field.displayedAnswer ? field.displayedAnswer : field.answer\n })\n\n return ret\n}\n\n/**\n * This function update a PopulatedWorkflowData with PersonalInformations\n * @param infos the personal informations\n * @param data the PopulatedWorkflowData\n * @returns an updated PopulatedWorkflowData\n */\nexport function updatePersonalIntoPopulatedWorkflowData(\n infos: PersonalInformations,\n data: PopulatedWorkflowData,\n category:\n | MetadataCategory.Personal\n | MetadataCategory.ChildPersonal\n | MetadataCategory.OtherPersonal\n) {\n const prefix = personalMetaToPrefix[category]\n\n const ret = JSON.parse(JSON.stringify(data)) // deep copy PopulatedWorkflowData\n\n if (infos.birthday && ret.fields[`${prefix}Birthday`])\n ret.fields[`${prefix}Birthday`].answer = infos.birthday\n if (infos.firstname && ret.fields[`${prefix}Firstname`])\n ret.fields[`${prefix}Firstname`].answer = infos.firstname\n if (infos.gender && ret.fields[`${prefix}Gender`])\n ret.fields[`${prefix}Gender`].answer = infos.gender\n if (infos.name && ret.fields[`${prefix}Name`])\n ret.fields[`${prefix}Name`].answer = infos.name\n if (infos.phone && ret.fields[`${prefix}Phone`])\n ret.fields[`${prefix}Phone`].answer = infos.phone\n if (infos.zip && ret.fields[`${prefix}Zip`])\n ret.fields[`${prefix}Zip`].answer = infos.zip\n if (infos.hid) {\n if (ret.fields[`${prefix}HID`]) {\n ret.fields[`${prefix}HID`].answer = infos.hid\n } else if (ret.fields[`${prefix}ID`]) {\n // This is done for backward compatibility (historically youID was used)\n ret.fields[`${prefix}ID`].answer = infos.hid\n } else {\n // If does not exist create it\n ret.fields[`${prefix}HID`] = { kind: 'text', answer: infos.hid }\n }\n }\n\n return ret\n}\n\n/**\n * This function extract an ISO 3166-1 alpha-2 country and subdivision code from data input object coming from workflow\n * @param answers answers from the WorkflowData\n * @returns an ISO 3166 alpha-2 code or undefined\n */\nexport function extractISOLocalityForConsult(\n answers?: SelectedAnswersData\n): string | undefined {\n if (!answers) {\n return undefined\n }\n\n const arrAnswersWithLocality = answers\n .flatMap((currentAnswerPage) => {\n const arrCountryFields = Object.keys(currentAnswerPage)\n .filter(\n (workflowFieldName) =>\n workflowFieldName.indexOf('Country') !== -1\n )\n .flat()\n const arrProvinceFields = Object.keys(currentAnswerPage)\n .filter(\n (workflowFieldName) =>\n workflowFieldName.indexOf('Province') !== -1\n )\n .flat()\n const arrConsultLocalFields = Object.keys(currentAnswerPage)\n .filter(\n (workflowFieldName) =>\n workflowFieldName.indexOf('Locality') !== -1\n )\n .flat()\n //returning the actual selected values, skipping if their IDs are more complex than a string\n return [\n ...arrCountryFields.map(\n (currentFieldName) =>\n (typeof currentAnswerPage[currentFieldName] === 'string'\n ? currentAnswerPage[currentFieldName]\n : undefined) as string\n ),\n ...arrProvinceFields.map(\n (currentFieldName) =>\n (typeof currentAnswerPage[currentFieldName] === 'string'\n ? currentAnswerPage[currentFieldName]\n : undefined) as string\n ),\n ...arrConsultLocalFields.map(\n (currentFieldName) =>\n (typeof currentAnswerPage[currentFieldName] === 'string'\n ? currentAnswerPage[currentFieldName]\n : undefined) as string\n ),\n ]\n })\n .filter((item) => item !== undefined)\n\n const arrSelectedLocality = arrAnswersWithLocality.filter(\n (currentSelectedLocality) =>\n currentSelectedLocality.startsWith('isoLocalityConsult')\n )\n if (!arrSelectedLocality || arrSelectedLocality.length === 0) {\n console.log('no locality found in ' + arrSelectedLocality)\n return undefined\n }\n //to allow enforcing of an order, we will allow the following pattern in the isoLocalityConsult field name\n // isoLocalityConsult-QC-CA and isoLocalityConsult_1-QC-CA\n // or generally: isoLocalityConsult-<isoValue> or isoLocalityConsult_<priority>-<isoValue>\n const allowedLocalityPatterns = /isoLocalityConsult(?:_(?<indexPriority>\\d*))?-(?<isoValue>[a-zA-Z0-9]{2}-[a-zA-Z0-9]{1,3})/\n const finalLocality = arrSelectedLocality.reduce<string | undefined>(\n (finalLocality, currentSelectedLocality) => {\n const extractedSelected = allowedLocalityPatterns.exec(\n currentSelectedLocality\n )\n const [, indexSelectedPriority, isoSelectedValue] =\n extractedSelected ?? []\n if (!finalLocality) {\n return isoSelectedValue\n }\n\n const extractedFinal = allowedLocalityPatterns.exec(finalLocality)\n const [, indexFinalPriority, isoFinalValue] = extractedFinal ?? []\n //we only keep the old value if there's priority used\n // and the new value is of lower priority\n if (\n !indexSelectedPriority ||\n (indexFinalPriority &&\n indexFinalPriority > indexSelectedPriority)\n ) {\n return isoFinalValue\n }\n\n return isoSelectedValue\n },\n undefined\n )\n\n console.log('Picking locality ' + finalLocality)\n return finalLocality\n}\n\nconst sessionPrivateKeyPrefix = 'sess-pkey'\nexport function sessionStorePrivateKeyName(id: string): string {\n return sessionPrivateKeyPrefix + id\n}\n","export class IncompleteAuthentication extends Error {}\nexport class MissingGrant extends Error {}\nexport class MissingLockbox extends Error {}\nexport class MissingLockboxOwner extends Error {}\nexport class AssociatedLockboxNotFound extends Error {}\nexport class WorkflowAnswersMissingError extends Error {}\n","import { getMany } from 'idb-keyval'\nimport { WorkflowAnswersMissingError } from '../models'\nimport {\n MetadataCategory,\n PopulatedWorkflowData,\n PopulatedWorkflowField,\n QuestionData,\n SelectedAnswerData,\n SelectedAnswersData,\n WorkflowData,\n WorkflowPageData,\n WorkflowUploadedImage,\n} from 'oro-sdk-apis'\n\nexport async function filterTriggeredAnsweredWithKind(\n workflowData: WorkflowData,\n kind:\n | 'text'\n | 'text-area'\n | 'text-select-group'\n | 'date'\n | 'number'\n | 'images'\n | 'images-alias'\n | 'body-parts'\n | 'pharmacy-picker'\n | 'online-pharmacy-picker'\n): Promise<SelectedAnswerData[]> {\n if (!workflowData.selectedAnswers) throw WorkflowAnswersMissingError\n // Flattens the list of answered questions\n let flattenedAnswers = flattenSelectedAnswers(workflowData.selectedAnswers)\n // Generates a list of applicable questions\n let triggeredQuestionsWithKind = Object.fromEntries(\n workflowData.pages\n .map((a) => {\n return Object.entries(a.questions).filter(\n ([_, question]) => isTriggered(question.triggers || [], flattenedAnswers) && question.kind === kind\n )\n })\n .flat()\n )\n\n const samePageAnswers = workflowData.selectedAnswers.reduce((prev, cur) => {\n return { ...prev, ...cur }\n }, {})\n\n const res = Object.keys(triggeredQuestionsWithKind).map((questionFieldName) => {\n return samePageAnswers[questionFieldName]\n })\n\n return res\n}\n\n/**\n * Filters and Populates the `selectedAnswers` from the workflow by\n * Cross-referencing the `MetaCategory` of the answer's respective question\n * Populates the fields labels and values that are of radio, dropdown and checkbox types\n *\n * @param workflowData\n * @param category\n * @returns An array of record key, value pairs\n */\nexport async function getWorkflowDataByCategory(\n workflowData: WorkflowData,\n category: MetadataCategory\n): Promise<PopulatedWorkflowData> {\n if (!workflowData.selectedAnswers) throw WorkflowAnswersMissingError\n\n // Flattens the list of answered questions\n let flattenedAnswers = flattenSelectedAnswers(workflowData.selectedAnswers)\n // Generates a list of applicable questions\n let triggeredQuestions = Object.fromEntries(\n workflowData.pages\n .map((a) => {\n return Object.entries(a.questions).filter(([_, question]) =>\n isTriggered(question.triggers || [], flattenedAnswers)\n )\n })\n .flat()\n )\n\n const fields: Record<string, PopulatedWorkflowField> = {}\n\n // Generates the answers of the specified category and adds the appropriate values if any are missing\n return Promise.all(\n workflowData.selectedAnswers\n .map((e) => Object.entries(e))\n .flat()\n .filter(([k, v]) => triggeredQuestions[k] && triggeredQuestions[k]['metaCategory'] === category)\n .map(([k, v]) => {\n return populateWorkflowField(triggeredQuestions[k], v).then((populatedValue) => {\n fields[k] = populatedValue\n })\n })\n )\n .then(() => {\n const ret: PopulatedWorkflowData = {\n workflowCreatedAt: workflowData.createdAt,\n workflowId: workflowData.id,\n locale: workflowData.locale,\n fields,\n }\n return ret\n })\n .catch((err) => {\n console.error(`Error while extracting ${category} data from workflow`, err)\n throw err\n })\n}\n\nexport async function getImagesFromIndexDb(answer: SelectedAnswerData): Promise<WorkflowUploadedImage[]> {\n return await getMany<WorkflowUploadedImage>((answer as any[]).map((v) => v.id ?? v) as string[])\n}\n\n/**\n * (If applicable) Based on the question kind, and the answer type this function will add and replace the appropriate fields to the\n * field values if they are radio, dropdown and checkbox fields\n *\n *\n * @param question\n * @param answerValue\n * @returns\n */\nasync function populateWorkflowField(\n question: QuestionData,\n answerValue: SelectedAnswerData\n): Promise<PopulatedWorkflowField> {\n let answer: any\n let displayedAnswer: string | string[] | undefined = undefined\n switch (question.kind) {\n case 'text-select-group':\n if (question.answers) {\n displayedAnswer = `${answerValue[0]} ${question.answers[answerValue[1] as string].text}`\n }\n answer = answerValue\n break\n case 'radio':\n case 'radio-card':\n case 'select':\n if (question.answers) {\n displayedAnswer = question.answers[answerValue as string].text\n }\n\n answer = answerValue\n break\n case 'multiple':\n case 'checkbox-group':\n displayedAnswer = (answerValue as string[]).map((value) => {\n if (question.answers) {\n return question.answers[value].text\n }\n\n throw new WorkflowAnswersMissingError()\n })\n\n answer = answerValue\n break\n case 'images':\n answer = await getImagesFromIndexDb(answerValue).then((images) =>\n images.map((image) => {\n const { name, imageData } = image\n\n return { name, imageData }\n })\n )\n break\n default:\n answer = answerValue\n }\n\n return Promise.resolve({\n answer,\n displayedAnswer,\n kind: question.kind,\n })\n}\n\nexport function isTriggered(triggers: string[], answers: string[]): boolean {\n for (let trigger of triggers) {\n if (!answers.includes(trigger)) {\n return false\n }\n }\n return true\n}\n\nexport function flattenSelectedAnswers(answers: SelectedAnswersData) {\n const linearAnswers: SelectedAnswerData[] = []\n\n for (const answer of answers) {\n linearAnswers.push(...Object.values(answer))\n }\n\n return linearAnswers.flat(1)\n}\n\n/**\n * This function helps you to get a valid workflow selectedAnswers structure\n * @param workflow the workflow data to use to initialize selectedAnswers\n * @param useDefault use workflow default values or not (this is used to avoid having unset values to appear in summaries)\n * @returns a valid selectedAnswers structure\n */\nexport function getInitialisedSelectedAnswers(workflow: WorkflowData, useDefault: boolean = true) {\n return workflow.pages.map((page) => {\n const ret: any = {}\n for (const [id, question] of Object.entries(page.questions)) {\n if (question.kind === 'body-parts') {\n ret[id] = useDefault ? [] : undefined\n } else {\n ret[id] = useDefault && question.defaultValue ? question.defaultValue : undefined\n }\n }\n return ret\n })\n}\n\nexport function fillWorkflowFromPopulatedWorkflow(workflow: WorkflowData, populatedWorkflow: PopulatedWorkflowData) {\n const filledWorkflow = JSON.parse(JSON.stringify(workflow))\n\n if (!filledWorkflow.selectedAnswers) {\n filledWorkflow.selectedAnswers = getInitialisedSelectedAnswers(filledWorkflow, false)\n }\n\n filledWorkflow.pages.forEach((page: WorkflowPageData, pageIdx: number) => {\n const ret: any = {}\n for (const [id] of Object.entries(page.questions)) {\n if (populatedWorkflow.fields[id]) {\n if (filledWorkflow.selectedAnswers)\n filledWorkflow.selectedAnswers[pageIdx][id] = populatedWorkflow.fields[id].answer as\n | string\n | string[]\n }\n }\n })\n\n return filledWorkflow\n}\n","import {\n Consult,\n ConsultationImageMeta,\n ConsultationMeta,\n ConsultRequest,\n DocumentType,\n IdentityResponse,\n IndexKey,\n MedicalMeta,\n MedicalStatus,\n MetadataCategory,\n PersonalMeta,\n PopulatedWorkflowData,\n Practitioner,\n PreferenceMeta,\n RawConsultationMeta,\n Term,\n Terms,\n Uuid,\n VaultIndex,\n WorkflowData,\n} from 'oro-sdk-apis'\nimport {\n filterTriggeredAnsweredWithKind,\n getImagesFromIndexDb,\n getWorkflowDataByCategory,\n identificationToPersonalInformations,\n OroClient,\n RegisterPatientOutput,\n toActualObject\n} from '..'\n\nconst MAX_RETRIES = 15\n\n/**\n * Completes a registration for a user retrying the complete flow a maximum of 15 times\n *\n * @description The order of importance when registering:\n * Creates a consultation if none exist\n * Retrieves or create's a lockbox if none exist\n * Grants the lockbox (if new) to all practitioners in the practice\n * Stores or fetches the patient data (without images)\n * Indexes the lockbox to the consult for all practitioners (done after inserting since index can be rebuilt from grants)\n * Stores the image data - done last since the majority of failure cases occur here\n * Creates the recovery payloads if they don't exist\n *\n * @param patientUuid\n * @param consultRequest\n * @param workflow\n * @param oroClient\n * @param masterKey\n * @param recoveryQA\n * @returns the successful registration\n */\nexport async function registerPatient(\n patientUuid: Uuid,\n consultRequest: ConsultRequest,\n workflow: WorkflowData,\n oroClient: OroClient,\n masterKey?: Uuid,\n recoveryQA?: {\n recoverySecurityQuestions: string[]\n recoverySecurityAnswers: string[]\n }\n): Promise<RegisterPatientOutput> {\n let consult: Consult | undefined = undefined\n let lockboxUuid: Uuid | undefined = undefined\n let practitionerAdmin: Uuid | undefined = undefined\n let retry = MAX_RETRIES\n let identity: IdentityResponse | undefined = undefined\n let errorsThrown: Error[] = []\n\n for (; retry > 0; retry--) {\n try {\n // Wait a bit each retry (we also want the first one to wait)\n await new Promise((resolve) => setTimeout(resolve, 2000))\n\n // Retrieving practitioners\n if (!practitionerAdmin)\n practitionerAdmin = (await oroClient.practiceClient.practiceGetFromUuid(consultRequest.uuidPractice))\n .uuidAdmin\n\n let practitioners: Practitioner[] = await oroClient.practiceClient\n .practiceGetPractitioners(consultRequest.uuidPractice)\n .catch((err) => {\n console.log(`Error retrieving practitioners`, err)\n return []\n })\n\n // Creating consult\n if (!consult) {\n consult = await getOrCreatePatientConsultationUuid(consultRequest, oroClient)\n }\n\n // Creating lockbox\n if (!lockboxUuid) lockboxUuid = await getOrCreatePatientLockbox(oroClient)\n\n if (!identity)\n identity = await oroClient.guardClient.identityGet(patientUuid)\n\n await oroClient.grantLockbox(practitionerAdmin, lockboxUuid).catch((err) => {\n console.error(`Error while granting lockbox to practitioner admin ${practitionerAdmin}`, err)\n // if we cannot grant to the admin, then the registration will fail\n errorsThrown.push(err)\n })\n\n // Patient Grant to practice\n let grantPromises = practitioners\n .filter((practitioner) => practitioner.uuid !== practitionerAdmin)\n .map(async (practitioner) => {\n return oroClient.grantLockbox(practitioner.uuid, lockboxUuid!).catch((err) => {\n console.error(`Error while granting lockbox to practitioner`, err)\n // Acceptable to continue as admin has already been granted, but we should still retry until the last retry remains\n if (retry <= 1) return\n errorsThrown.push(err)\n })\n })\n\n const consultIndex: VaultIndex = {\n [IndexKey.ConsultationLockbox]: [\n {\n grant: {\n lockboxUuid,\n lockboxOwnerUuid: patientUuid,\n },\n consultationId: consult.uuid,\n },\n ],\n }\n\n // the index will identify in which lockbox a consultation resides\n let consultIndexPromises = practitioners.map(async (practitioner) => {\n return oroClient.vaultIndexAdd(consultIndex, practitioner.uuid).catch((err) => {\n console.error(`[SDK: registration] Error while adding to the practitioner's index ${practitioner.uuid}`, err)\n // Acceptable to continue as the index can be rebuilt, but we should still retry until the last retry remains\n if (retry <= 1) return\n else errorsThrown.push(err)\n })\n })\n\n\n await storeImageAliases(consult.uuid, lockboxUuid, workflow, oroClient).catch((err) => {\n console.error('[SDK: registration] Some errors happened during image upload', err)\n // Acceptable to continue as images can be requested during the consultation, but we should still retry until the last retry remains\n if (retry <= 1) return\n else errorsThrown.push(err)\n })\n\n await storePatientData(consult.uuid, consultRequest.isoLanguageRequired, lockboxUuid, workflow, oroClient).catch((err) => {\n console.error('[SDK: registration] Some errors happened during patient data upload', err)\n errorsThrown.push(err)\n })\n\n if (masterKey && !identity?.recoveryMasterKey) {\n // generate and store recovery payload and updates the identity \n identity = await oroClient.updateMasterKey(patientUuid, masterKey, lockboxUuid).catch((err) => {\n console.error(`[SDK: registration] Error while updating master key`, err)\n /// it's acceptable to continue registration (return old identity)\n if (retry <= 1) return\n errorsThrown.push(err)\n return identity\n })\n } else {\n // we did not set the master key so we do not return it\n masterKey = undefined\n }\n\n if (recoveryQA && !identity?.recoverySecurityQuestions)\n // Patient security question recovery threshold is 2 answers and updates the identity \n identity = await oroClient\n .updateSecurityQuestions(\n patientUuid,\n recoveryQA.recoverySecurityQuestions,\n recoveryQA.recoverySecurityAnswers,\n 2\n )\n .catch((err) => {\n console.error(`[SDK: registration] Error while updating security questions`, err)\n /// it's acceptable to continue registration (return old identity)\n if (retry <= 1) return\n errorsThrown.push(err)\n return identity\n })\n\n await Promise.all([...grantPromises, ...consultIndexPromises])\n\n await buildConsultSearchIndex(consult.uuid, workflow, oroClient).catch((err) => {\n console.error('[SDK: registration] personal information not found or another error occured during search indexing', err)\n if(retry <= 1) return // this statement is to avoid failing the registration due to the failure in search indexing the consult, this practically implements a soft retry\n errorsThrown.push(err)\n })\n\n if (errorsThrown.length > 0)\n throw errorsThrown\n\n // Deem the consultation as ready\n await oroClient.consultClient.updateConsultByUUID(consult.uuid, {\n statusMedical: MedicalStatus.New,\n })\n\n // if we got through the complete flow, the registration succeeded\n break\n } catch (err) {\n console.error(`[SDK] Error occured during registration: ${err}, retrying... Retries remaining: ${retry}`)\n errorsThrown = []\n continue\n }\n }\n\n if (retry <= 0) {\n console.error('[SDK] registration failed: MAX_RETRIES reached')\n throw 'RegistrationFailed'\n }\n\n console.log('Successfully Registered')\n await oroClient.cleanIndex()\n return {\n masterKey,\n consultationId: consult!.uuid,\n lockboxUuid: lockboxUuid!,\n }\n}\n\n/**\n * Creates a consultation if one has not been created and fails to be retrieved by the payment intent\n * @param consult\n * @param oroClient\n * @returns the consult Uuid\n */\nasync function getOrCreatePatientConsultationUuid(consult: ConsultRequest, oroClient: OroClient): Promise<Consult> {\n let payment = await oroClient.practiceClient.practiceGetPayment(\n consult.uuidPractice,\n consult.idStripeInvoiceOrPaymentIntent\n )\n if (payment && payment.uuidConsult) {\n return oroClient.consultClient.getConsultByUUID(payment.uuidConsult).catch((err) => {\n console.error('Error while retrieving consult', err)\n throw err\n })\n } else {\n return await oroClient.consultClient.consultCreate(consult).catch((err) => {\n console.error('Error while creating consult', err)\n throw err\n })\n }\n}\n\n/**\n * Creates a new lockbox for the patient if they do not have any, otherwise, use the first (and only one)\n * @param oroClient\n * @returns the lockbox Uuid\n */\nasync function getOrCreatePatientLockbox(oroClient: OroClient): Promise<Uuid> {\n let grants = await oroClient.getGrants(undefined, true)\n if (grants.length > 0) {\n console.log('The grant has already been created, skipping lockbox create step')\n return grants[0].lockboxUuid!\n } else\n return (\n await oroClient.vaultClient.lockboxCreate().catch((err) => {\n console.error('Error while creating lockbox', err)\n throw err\n })\n ).lockboxUuid\n}\n\n/**\n * Store all patient related information into his/her lockbox\n * @param consultationId The consultation id\n * @param isoLanguage the prefered language of communication (ISO 639-3 https://en.wikipedia.org/wiki/List_of_ISO_639-2_codes)\n * @param lockboxUuid the lockbox uuid to store data in\n * @param workflow the workflow used to extract informations\n * @param oroClient an oroClient instance\n * @returns\n */\nasync function storePatientData(\n consultationId: Uuid,\n isoLanguage: string,\n lockboxUuid: Uuid,\n workflow: WorkflowData,\n oroClient: OroClient\n): Promise<(Uuid | void)[]> {\n // Create and store registration data\n return Promise.all([\n // Storing Raw data first\n oroClient.getOrInsertJsonData<RawConsultationMeta>(\n lockboxUuid,\n workflow,\n {\n category: MetadataCategory.Raw,\n contentType: 'application/json',\n consultationId,\n },\n {}\n ),\n getWorkflowDataByCategory(workflow, MetadataCategory.Consultation).then((data) =>\n oroClient.getOrInsertJsonData<ConsultationMeta>(\n lockboxUuid,\n data,\n {\n category: MetadataCategory.Consultation,\n documentType: DocumentType.PopulatedWorkflowData,\n consultationId, // TODO: deprecated. Will finally only be in privateMetadata\n },\n { consultationId }\n )\n ),\n getWorkflowDataByCategory(workflow, MetadataCategory.Medical).then((data) =>\n oroClient.getOrInsertJsonData<MedicalMeta>(\n lockboxUuid,\n data,\n {\n category: MetadataCategory.Medical,\n documentType: DocumentType.PopulatedWorkflowData,\n consultationIds: [consultationId!],\n },\n {}\n )\n ),\n extractAndStorePersonalWorkflowData(\n workflow,\n lockboxUuid,\n consultationId,\n MetadataCategory.Personal,\n oroClient\n ),\n extractAndStorePersonalWorkflowData(\n workflow,\n lockboxUuid,\n consultationId,\n MetadataCategory.ChildPersonal,\n oroClient\n ),\n extractAndStorePersonalWorkflowData(\n workflow,\n lockboxUuid,\n consultationId,\n MetadataCategory.OtherPersonal,\n oroClient\n ),\n oroClient.getOrInsertJsonData<PreferenceMeta>(\n lockboxUuid,\n { isoLanguage },\n {\n category: MetadataCategory.Preference,\n contentType: 'application/json',\n },\n {}\n ),\n ]).then((dataUuids) => dataUuids.flat())\n}\n\nasync function storeImageAliases(\n consultationId: Uuid,\n lockboxUuid: Uuid,\n workflow: WorkflowData,\n oroClient: OroClient\n): Promise<(Uuid | void)[]> {\n const images = await getImagesFromIndexDb((await filterTriggeredAnsweredWithKind(workflow, 'images-alias')).flat())\n\n const nonNullImages = images.filter((img) => !!img)\n\n if (images.length !== nonNullImages.length) {\n console.error('[SDK] Some images have not been found, they have been skipped.')\n }\n\n let promises = nonNullImages.map((image) => {\n return oroClient.getOrInsertJsonData<ConsultationImageMeta>(\n lockboxUuid,\n image,\n {\n category: MetadataCategory.Consultation,\n documentType: DocumentType.ImageAlias,\n consultationId,\n idbId: image.idbId as string,\n },\n {}\n )\n })\n return Promise.all(promises)\n}\n\n/**\n * Extracts the workflow MetadataCategory for Personal, ChildPersonal and OtherPersonal\n * then stores it in the vault\n *\n * @param workflow\n * @param lockboxUuid\n * @param category\n * @returns The data uuid\n */\nexport async function extractAndStorePersonalWorkflowData(\n workflow: WorkflowData,\n lockboxUuid: Uuid,\n consultationId: Uuid,\n category: MetadataCategory.Personal | MetadataCategory.ChildPersonal | MetadataCategory.OtherPersonal,\n oroClient: OroClient\n): Promise<Uuid | void> {\n return getWorkflowDataByCategory(workflow, category as unknown as MetadataCategory).then((data) => {\n if (Object.keys(data.fields).length === 0) return\n return oroClient.getOrInsertJsonData<PersonalMeta>(\n lockboxUuid,\n data,\n {\n category,\n documentType: DocumentType.PopulatedWorkflowData,\n consultationIds: [consultationId],\n },\n {}\n )\n })\n}\n\n/**\n * Given workflow data, it populates it with Personal, ChildPersonal, and OtherPersonal workflow data\n * @param workflow\n */\nexport async function extractPersonalInfoFromWorkflowData(workflow: WorkflowData): Promise<{\n personalInfoPopulatedWfData: PopulatedWorkflowData,\n childPersonalInfoPopulatedWfData: PopulatedWorkflowData,\n otherPersonalInfoPopulatedWfData: PopulatedWorkflowData,\n}> {\n return Promise.all([\n getWorkflowDataByCategory(workflow, MetadataCategory.Personal),\n getWorkflowDataByCategory(workflow, MetadataCategory.ChildPersonal),\n getWorkflowDataByCategory(workflow, MetadataCategory.OtherPersonal)\n ]).then(([personalInfoPopulatedWfData, childPersonalInfoPopulatedWfData, otherPersonalInfoPopulatedWfData]) => {\n return {\n personalInfoPopulatedWfData,\n childPersonalInfoPopulatedWfData,\n otherPersonalInfoPopulatedWfData,\n }\n })\n}\n\n/**\n * Creates the search index for the first and last name of the given consultation\n * @param consultUuid the uuid of the consult to be search indexed\n * @param workflow the workflow data\n * @param oroClient\n */\nexport async function buildConsultSearchIndex(consultUuid: string, workflow: WorkflowData, oroClient: OroClient) {\n let terms: Terms = []\n\n const {\n personalInfoPopulatedWfData,\n childPersonalInfoPopulatedWfData,\n otherPersonalInfoPopulatedWfData\n } = await extractPersonalInfoFromWorkflowData(workflow)\n\n const personalInfo = identificationToPersonalInformations(\n toActualObject(personalInfoPopulatedWfData),\n MetadataCategory.Personal\n )\n const childPersonalInfo = identificationToPersonalInformations(\n toActualObject(childPersonalInfoPopulatedWfData),\n MetadataCategory.ChildPersonal\n )\n const otherPersonalInfo = identificationToPersonalInformations(\n toActualObject(otherPersonalInfoPopulatedWfData),\n MetadataCategory.OtherPersonal\n )\n\n terms.push(<Term>{\n kind: 'first-name',\n value: personalInfo.firstname,\n }, <Term> {\n kind: 'last-name',\n value: personalInfo.name\n })\n\n if(childPersonalInfo.firstname && childPersonalInfo.name) {\n terms.push(<Term>{\n kind: 'first-name',\n value: childPersonalInfo.firstname,\n }, <Term> {\n kind: 'last-name',\n value: childPersonalInfo.name\n })\n }\n\n if(otherPersonalInfo.firstname && otherPersonalInfo.name) {\n terms.push(<Term>{\n kind: 'first-name',\n value: otherPersonalInfo.firstname,\n }, <Term> {\n kind: 'last-name',\n value: otherPersonalInfo.name\n })\n }\n\n await oroClient.searchClient.index(consultUuid, terms)\n}","import { CryptoRSA, uuidParse} from \"oro-toolbox\"\nimport { EncryptedIndexEntry, Grant, IndexConsultLockbox } from \"oro-sdk-apis\"\n\n/**\n * Decrypts and returns the encrypted grants\n * If something went wrong during decryption, that grant will be removed from the list\n *\n * @param encryptedGrants: an array of encrypted grants\n * @param rsaKey: the rsa key used to decrypt the encrypted grants\n * @returns an array of grants\n */\nexport function decryptGrants(encryptedGrants: Grant[], rsaKey: CryptoRSA): Grant[] {\n return encryptedGrants\n .map(grant => {\n if (grant.encryptedLockbox && !grant.lockboxUuid) {\n try {\n grant.lockboxUuid = uuidParse(\n rsaKey.base64DecryptToBytes(grant.encryptedLockbox)\n )\n } catch (e) {\n console.error('[sdk:index] The grant could not be decrypted or was not a valid UUID: ', e)\n }\n }\n return grant\n })\n .filter(grant => grant.lockboxUuid)\n}\n\n/**\n * Decrypts the encrypted consult lockboxes and returns their grants\n * If something went wrong during decryption, that grant will be removed from the list\n *\n * @param encryptedConsultLockboxes: an array of encrypted entries\n * @param rsaKey: the rsa key used to decrypt the encrypted entries\n * @returns an array of grants\n */\nexport function decryptConsultLockboxGrants(encryptedConsultLockboxes: EncryptedIndexEntry[], rsaKey: CryptoRSA): Grant[] {\n return encryptedConsultLockboxes\n .map(encryptedConsultLockboxes => {\n try {\n return [true, (rsaKey.base64DecryptToJson(\n encryptedConsultLockboxes.encryptedIndexEntry\n ) as IndexConsultLockbox).grant]\n } catch(e) {\n console.error('[sdk:index] The consult lockbox grant could not be decrypted: ', e)\n return [false, undefined] // if decryption fails, we want to ignore the grant but not fail the call\n }\n })\n .filter(grantsTuple => grantsTuple[0])\n .map(grantTuples => grantTuples[1] as Grant)\n}","import { IndexKey, Grant, IndexConsultLockbox, MetadataCategory, VaultIndex } from 'oro-sdk-apis'\nimport { OroClient, Uuid } from '..'\n\n/**\n * @name filterGrantsWithLockboxMetadata\n * @description searches for the applied filters in the vault index\n * @param oroClient\n * @param filter: the metadata filter applied to each the lockboxes\n * @param vaultIndex: the index to which the filter will be applied\n * @param forceRefresh\n * @returns the filtered grants\n */\nexport async function filterGrantsWithLockboxMetadata(\n oroClient: OroClient,\n filter?: { consultationId: Uuid },\n vaultIndex?: VaultIndex,\n forceRefresh = false\n): Promise<Grant[]> {\n if (!vaultIndex || forceRefresh) {\n vaultIndex = await buildLegacyVaultIndex(oroClient)\n }\n if (vaultIndex[IndexKey.Consultation] && filter) {\n let indexConsults = (vaultIndex[IndexKey.Consultation] ?? [])\n .filter((consultGrant: { consultationId: Uuid }) => consultGrant.consultationId === filter.consultationId)\n .map((consultGrant: { consultationId: Uuid; grant: Grant }) => consultGrant.grant as Grant)\n return indexConsults as Grant[]\n } else {\n // No grants exist and the index has already been built\n return []\n }\n}\n\n/** Finds all grants for the logged user\n * requests a list of unique consultation ids for each lockbox the user has access to\n * builds and sets the index of consultations\n * @param oroClient\n * @returns the constructed vaultIndex\n */\nexport async function buildLegacyVaultIndex(oroClient: OroClient): Promise<VaultIndex> {\n let grants = await oroClient.getGrants()\n let consultGrants: IndexConsultLockbox[] = []\n for (let grant of grants) {\n let consults = (\n await oroClient.vaultClient.lockboxMetadataGet(grant.lockboxUuid!, ['consultationId'], [], {\n category: MetadataCategory.Consultation,\n })\n )[0] as Uuid[]\n\n consultGrants = [\n ...consultGrants,\n ...consults.map((consult: any) => ({\n ...consult,\n grant: {\n lockboxOwnerUuid: grant.lockboxOwnerUuid,\n lockboxUuid: grant.lockboxUuid,\n },\n })),\n ]\n }\n\n let vaultIndex = {\n [IndexKey.Consultation]: consultGrants,\n }\n oroClient.setVaultIndex(vaultIndex)\n console.info('[sdk:index] Successfully Built Vault Index')\n return vaultIndex\n}\n","import {\n AuthTokenRequest,\n Consult,\n ConsultRequest,\n ConsultService,\n DataCreateResponse,\n DiagnosisService,\n Document,\n DocumentType,\n EncryptedIndexEntry,\n EncryptedVaultIndex,\n Grant,\n GuardService,\n IdentityCreateRequest,\n IdentityResponse,\n IndexConsultLockbox,\n IndexKey,\n LocalizedData,\n LockboxDataRequest,\n LockboxGrantRequest,\n LockboxManifest,\n ManifestEntry,\n Meta,\n Metadata,\n MetadataCategory,\n PersonalMeta,\n PopulatedWorkflowData,\n Practice,\n PracticeService,\n PreferenceMeta,\n RecoveryMeta,\n SearchService,\n SecretShard,\n TellerService,\n TokenData,\n TosAndCpAcceptanceRequest,\n Uuid,\n VaultIndex,\n VaultService,\n WorkflowData,\n WorkflowService,\n} from 'oro-sdk-apis'\nimport * as OroToolbox from 'oro-toolbox'\nimport { CryptoRSA } from 'oro-toolbox'\nimport { decryptConsultLockboxGrants, decryptGrants, registerPatient, sessionStorePrivateKeyName } from './helpers'\nimport {\n AssociatedLockboxNotFound,\n IncompleteAuthentication,\n LocalEncryptedData,\n MissingGrant,\n MissingLockbox,\n MissingLockboxOwner,\n RecoveryData,\n RegisterPatientOutput,\n UserPreference,\n} from './models'\nimport { buildLegacyVaultIndex, filterGrantsWithLockboxMetadata } from './sdk-revision'\n\nexport class OroClient {\n private rsa?: CryptoRSA\n private secrets: {\n lockboxUuid: string\n cryptor: OroToolbox.CryptoChaCha\n }[] = []\n private cachedMetadataGrants: {\n [filter: string]: Grant[]\n } = {}\n\n private cachedManifest: {\n [filter: string]: ManifestEntry[]\n } = {}\n\n private vaultIndex?: VaultIndex\n\n constructor(\n private toolbox: typeof OroToolbox,\n public tellerClient: TellerService,\n public vaultClient: VaultService,\n public guardClient: GuardService,\n public searchClient: SearchService,\n public practiceClient: PracticeService,\n public consultClient: ConsultService,\n public workflowClient: WorkflowService,\n public diagnosisClient: DiagnosisService,\n private authenticationCallback?: (err: Error) => void\n ) { }\n\n /**\n * clears the vaultIndex and cached metadata grants\n */\n public async cleanIndex() {\n this.vaultIndex = undefined\n this.cachedMetadataGrants = {}\n this.cachedManifest = {}\n }\n\n /**\n * Generates an RSA key pair and password payload (rsa private key encrypted with the password)\n * Calls Guard to sign up with the email address, password, practice, legal and token data\n *\n * @param email\n * @param password\n * @param practice\n * @param legal\n * @param tokenData\n * @returns\n */\n public async signUp(\n email: string,\n password: string,\n practice: Practice,\n tosAndCpAcceptance: TosAndCpAcceptanceRequest,\n tokenData?: TokenData,\n subscription?: boolean,\n skipEmailValidation?: boolean\n ): Promise<IdentityResponse> {\n this.rsa = new CryptoRSA()\n const privateKey = this.rsa.private()\n\n const symmetricEncryptor = this.toolbox.CryptoChaCha.fromPassphrase(password)\n const recoveryPassword = symmetricEncryptor.bytesEncryptToBase64Payload(privateKey)\n\n const hashedPassword = this.toolbox.hashStringToBase64(this.toolbox.hashStringToBase64(password))\n\n const emailConfirmed = !!skipEmailValidation\n\n const signupRequest: IdentityCreateRequest = {\n practiceUuid: practice.uuid,\n email: email.toLowerCase(),\n emailConfirmed,\n password: hashedPassword,\n publicKey: this.toolbox.encodeToBase64(this.rsa.public()),\n recoveryPassword,\n tosAndCpAcceptance,\n tokenData,\n subscription,\n }\n\n const identity = await this.guardClient.identityCreate(signupRequest)\n\n if (identity.recoveryLogin) {\n //Ensure we can recover from a page reload\n let symetricEncryptor = this.toolbox.CryptoChaCha.fromPassphrase(identity.recoveryLogin)\n sessionStorage.setItem(\n sessionStorePrivateKeyName(identity.id),\n symetricEncryptor.bytesEncryptToBase64Payload(privateKey)\n )\n }\n\n return identity\n }\n\n /**\n * Parse the given accessToken claims by calling guard whoami and update theidentity to set it's emailConfirmed flag\n * @param accessToken\n * @returns The identity related to confirmedEmail\n */\n public async confirmEmail(accessToken: string): Promise<IdentityResponse> {\n this.guardClient.setTokens({ accessToken })\n const claims = await this.guardClient.whoAmI()\n return this.guardClient.identityUpdate(claims.sub, {\n emailConfirmed: true,\n })\n }\n\n /**\n * Calls Guard to sign in with the email address, password and one time password (if MFA is enabled)\n * Then recover's the rsa private key from the recovery payload\n *\n * @param practiceUuid\n * @param email\n * @param password\n * @param otp\n * @returns the user identity\n */\n public async signIn(practiceUuid: Uuid, email: string, password: string, otp?: string): Promise<IdentityResponse> {\n const hashedPassword = this.toolbox.hashStringToBase64(this.toolbox.hashStringToBase64(password))\n const tokenRequest: AuthTokenRequest = {\n practiceUuid,\n email: email.toLowerCase(),\n password: hashedPassword,\n otp,\n }\n\n await this.guardClient.authToken(tokenRequest)\n const userUuid = (await this.guardClient.whoAmI()).sub\n\n // Updates the rsa key to the one generated on the backend\n await this.recoverPrivateKeyFromPassword(userUuid, password)\n return await this.guardClient.identityGet(userUuid)\n }\n\n /**\n * Will attempt to recover an existing login session and set back\n * the private key in scope\n */\n public async resumeSession() {\n const id = (await this.guardClient.whoAmI()).sub\n const recoveryPayload = sessionStorage.getItem(sessionStorePrivateKeyName(id))\n const recoveryKey = (await this.guardClient.identityGet(id)).recoveryLogin\n\n if (!recoveryKey || !recoveryPayload) throw IncompleteAuthentication\n\n const symmetricDecryptor = this.toolbox.CryptoChaCha.fromPassphrase(recoveryKey)\n let privateKey = symmetricDecryptor.base64PayloadDecryptToBytes(recoveryPayload)\n this.rsa = this.toolbox.CryptoRSA.fromKey(privateKey)\n }\n\n /**\n * This function let's you encrypt locally an Object\n * @param value the Object to encrypt\n * @returns a LocalEncryptedData Object\n * @throws IncompleteAuthentication if rsa is not set\n * @calls authenticationCallback if rsa is not set\n */\n public localEncryptToJsonPayload(value: any): LocalEncryptedData {\n if (!this.rsa) {\n if (this.authenticationCallback) {\n this.authenticationCallback(new IncompleteAuthentication())\n }\n\n throw new IncompleteAuthentication()\n }\n\n const chaChaKey = new this.toolbox.CryptoChaCha()\n\n const encryptedData = chaChaKey.jsonEncryptToBase64Payload(value)\n const encryptedKey = this.toolbox.encodeToBase64(this.rsa.encryptToBytes(chaChaKey.key()))\n\n return { encryptedData, encryptedKey }\n }\n\n /**\n * This function let's you decrypt a LocalEncryptedData object\n * @param value a LocalEncryptedData object\n * @returns a decrypted Object\n * @throws IncompleteAuthentication if rsa is not set\n * @calls authenticationCallback if rsa is not set\n */\n public localDecryptJsonPayload({ encryptedKey, encryptedData }: LocalEncryptedData): any {\n if (!this.rsa) {\n if (this.authenticationCallback) {\n this.authenticationCallback(new IncompleteAuthentication())\n }\n\n throw new IncompleteAuthentication()\n }\n\n const chaChaKey = this.rsa.base64DecryptToBytes(encryptedKey)\n const decryptedData = this.toolbox.CryptoChaCha.fromKey(chaChaKey).base64PayloadDecryptToJson(encryptedData)\n\n return decryptedData\n }\n\n /**\n * Effectively kills your \"session\"\n */\n public async signOut() {\n this.rsa = undefined\n this.secrets = []\n this.guardClient.setTokens({\n accessToken: undefined,\n refreshToken: undefined,\n })\n await this.guardClient.authLogout()\n }\n\n /**\n * @name registerPatient\n * @description The complete flow to register a patient\n *\n * Steps:\n * 1. Create a consult (checks if payment has been done)\n * 2. Creates a lockbox\n * 3. Grants lockbox access to all practice personnel\n * 4. Creates secure identification, medical, onboarding data\n * 5. Generates and stores the rsa key pair and recovery payloads\n *\n * @param patientUuid\n * @param consult\n * @param workflow\n * @param recoveryQA\n * @returns\n */\n public async registerPatient(\n patientUuid: Uuid,\n consult: ConsultRequest,\n workflow: WorkflowData,\n recoveryQA?: {\n recoverySecurityQuestions: string[]\n recoverySecurityAnswers: string[]\n }\n ): Promise<RegisterPatientOutput> {\n if (!this.rsa) throw IncompleteAuthentication\n return registerPatient(patientUuid, consult, workflow, this, this.toolbox.uuid(), recoveryQA)\n }\n\n /**\n * Builds the vault index for the logged user\n *\n * Steps:\n * 1. Retrieves, decrypts and sets the lockbox IndexSnapshot\n * 2. Retrieves, decrypts and adds all other index entries starting at the snapshot timestamp\n * 3. Updates the IndexSnapshot if changed\n * @deprecated\n * @returns the latest vault index\n */\n public async buildVaultIndex(forceRefresh: boolean = false) {\n if (!this.vaultIndex || forceRefresh) await buildLegacyVaultIndex(this)\n }\n\n /**\n * Setter for the vault index\n * @param index\n */\n public setVaultIndex(index: VaultIndex) {\n this.vaultIndex = index\n }\n\n /**\n * Fetches all grants, and consultations that exist in each lockbox\n * Then updates the index for the current user with the lockbox consult relationship\n */\n public async forceUpdateIndexEntries() {\n let grants = await this.getGrants()\n\n let indexConsultLockbox: IndexConsultLockbox[] = await Promise.all(\n grants.map(\n async (grant: Grant) =>\n await this.vaultClient\n .lockboxMetadataGet(\n grant.lockboxUuid!,\n ['consultationId'],\n [],\n { category: MetadataCategory.Consultation },\n grant.lockboxOwnerUuid\n )\n .then((consults) => {\n try {\n return consults[0].map((consult: any) => {\n return {\n ...consult,\n grant: {\n lockboxOwnerUuid: grant.lockboxOwnerUuid,\n lockboxUuid: grant.lockboxUuid,\n },\n }\n })\n } catch (e) {\n // No consultations in lockbox or index could not be created\n return []\n }\n })\n .catch(() => [])\n )\n ).then((consults) => consults.flat())\n this.vaultIndexAdd({\n [IndexKey.Consultation]: indexConsultLockbox,\n })\n .then(() => alert('The Index was successfully updated!'))\n .catch(() => console.error('The index failed to update!'))\n }\n\n /**\n * Generates, encrypts and adds entries to vault index for a given index owner\n *\n * @param entries\n * @param indexOwnerUuid\n */\n public async vaultIndexAdd(entries: VaultIndex, indexOwnerUuid?: Uuid) {\n if (!this.rsa) throw IncompleteAuthentication\n\n let rsaPub: Uint8Array\n if (indexOwnerUuid) {\n let base64IndexOwnerPubKey = (await this.guardClient.identityGet(indexOwnerUuid)).publicKey\n rsaPub = this.toolbox.decodeFromBase64(base64IndexOwnerPubKey)\n } else {\n rsaPub = this.rsa.public()\n }\n\n let encryptedIndex: EncryptedVaultIndex = {}\n\n for (let keyString of Object.keys(entries)) {\n let key = keyString as keyof VaultIndex\n switch (key) {\n case IndexKey.ConsultationLockbox:\n encryptedIndex[key] = (entries[key] as IndexConsultLockbox[])\n .map((e) => ({\n ...e,\n uniqueHash: e.consultationId,\n }))\n .map(\n (e: IndexConsultLockbox) =>\n ({\n uuid: e.uuid,\n timestamp: e.timestamp,\n uniqueHash: e.uniqueHash,\n encryptedIndexEntry: CryptoRSA.jsonWithPubEncryptToBase64(\n {\n consultationId: e.consultationId,\n grant: e.grant,\n },\n rsaPub\n ),\n } as EncryptedIndexEntry)\n )\n break\n //// DEPRECATED : REMOVE ME : BEGIN ///////////////////////////////////////////\n case IndexKey.Consultation:\n encryptedIndex[key] = (entries[key] as IndexConsultLockbox[])\n .map((e) => ({\n ...e,\n uniqueHash: this.toolbox.hashStringToBase64(\n JSON.stringify({\n consultationId: e.consultationId,\n grant: e.grant,\n })\n ),\n }))\n .filter(\n (e) =>\n !this.vaultIndex ||\n !this.vaultIndex[IndexKey.Consultation]?.find((v) => v.uniqueHash === e.uniqueHash)\n )\n .map(\n (e: IndexConsultLockbox) =>\n ({\n uuid: e.uuid,\n timestamp: e.timestamp,\n uniqueHash: e.uniqueHash,\n encryptedIndexEntry: CryptoRSA.jsonWithPubEncryptToBase64(\n {\n consultationId: e.consultationId,\n grant: e.grant,\n },\n rsaPub\n ),\n } as EncryptedIndexEntry)\n )\n break\n //// DEPRECATED : REMOVE ME : END ///////////////////////////////////////////\n }\n }\n await this.vaultClient.vaultIndexPut(encryptedIndex, indexOwnerUuid)\n }\n\n /**\n * adds or updates the index snapshot for the logged user\n * @param index\n */\n public async indexSnapshotAdd(index: VaultIndex) {\n if (!this.rsa) throw IncompleteAuthentication\n let rsaPub: Uint8Array = this.rsa.public()\n\n let cleanedIndex: VaultIndex = {\n [IndexKey.Consultation]: index[IndexKey.Consultation]\n ?.filter((c) => c)\n .map((c) => {\n return {\n grant: c.grant,\n consultationId: c.consultationId,\n }\n }),\n }\n\n // the data of the snapshot should not contain the `IndexEntry` data\n // (will create conflicts while updating)\n let encryptedIndexEntry = CryptoRSA.jsonWithPubEncryptToBase64(cleanedIndex, rsaPub)\n\n // The encryptedIndexEntry can have the uuid and timstamp (for updating)\n let encryptedIndex: EncryptedIndexEntry = {\n uuid: index.uuid,\n timestamp: index.timestamp,\n encryptedIndexEntry,\n }\n this.vaultClient.vaultIndexSnapshotPut(encryptedIndex)\n }\n\n /**\n * @name grantLockbox\n * @description Grants a lockbox by retrieving the shared secret of the lockbox and encrypting it with the grantees public key\n * @param granteeUuid\n * @param lockboxUuid\n * @param lockboxOwnerUuid the lockbox owner (ignored if lockbox is owned by self)\n */\n public async grantLockbox(granteeUuid: Uuid, lockboxUuid: Uuid, lockboxOwnerUuid?: Uuid) {\n if (!this.rsa) throw IncompleteAuthentication\n\n let secret = (await this.getCachedSecretCryptor(lockboxUuid, lockboxOwnerUuid)).key()\n let base64GranteePublicKey = (await this.guardClient.identityGet(granteeUuid)).publicKey\n let granteePublicKey = this.toolbox.decodeFromBase64(base64GranteePublicKey)\n\n let granteeEncryptedSecret = CryptoRSA.bytesWithPubEncryptToBase64(secret, granteePublicKey)\n let request: LockboxGrantRequest = {\n encryptedSecret: granteeEncryptedSecret,\n granteeUuid: granteeUuid,\n }\n await this.vaultClient.lockboxGrant(lockboxUuid, request, lockboxOwnerUuid)\n }\n\n /**\n * @name createMessageData\n * @description Creates a Base64 encrypted Payload to send and store in the vault from a message string\n * @param lockboxUuid\n * @param message\n * @param consultationId the consultation for which this message is sent\n * @param lockboxOwnerUuid the lockbox owner (ignored if lockbox is owned by self)\n * @param previousDataUuid if it's a revision of existing file, specify the previous data uuid\n * @returns the data uuid\n */\n public async createMessageData(\n lockboxUuid: Uuid,\n message: string,\n consultationId: string,\n lockboxOwnerUuid?: Uuid,\n previousDataUuid?: Uuid\n ): Promise<DataCreateResponse> {\n if (!this.rsa) throw IncompleteAuthentication\n\n let symmetricEncryptor = await this.getCachedSecretCryptor(lockboxUuid, lockboxOwnerUuid)\n\n let encryptedData = symmetricEncryptor.jsonEncryptToBase64Payload(message)\n let encryptedPrivateMeta = symmetricEncryptor.jsonEncryptToBase64Payload({\n author: (await this.guardClient.whoAmI()).sub,\n })\n\n let meta = {\n consultationId,\n category: MetadataCategory.Consultation,\n documentType: DocumentType.Message,\n contentType: 'text/plain',\n }\n\n let request: LockboxDataRequest = {\n data: encryptedData,\n publicMetadata: meta,\n privateMetadata: encryptedPrivateMeta,\n }\n\n return this.tellerClient.lockboxDataStore(lockboxUuid, request, lockboxOwnerUuid, previousDataUuid)\n }\n\n /**\n * @name createMessageAttachmentData\n * @description Creates a Base64 encrypted Payload to send and store in the vault from a file\n * @param lockboxUuid\n * @param data the file stored\n * @param consultationId the consultation for which this message is sent\n * @param lockboxOwnerUuid the lockbox owner (ignored if lockbox is owned by self)\n * @param previousDataUuid if it's a revision of existing file, specify the previous data uuid\n * @returns the data uuid\n */\n public async createMessageAttachmentData(\n lockboxUuid: Uuid,\n data: File,\n consultationId: string,\n lockboxOwnerUuid?: Uuid,\n previousDataUuid?: Uuid\n ): Promise<DataCreateResponse> {\n if (!this.rsa) throw IncompleteAuthentication\n\n let symmetricEncryptor = await this.getCachedSecretCryptor(lockboxUuid, lockboxOwnerUuid)\n let encryptedData = symmetricEncryptor.bytesEncryptToBase64Payload(new Uint8Array(await data.arrayBuffer()))\n let encryptedPrivateMeta = symmetricEncryptor.jsonEncryptToBase64Payload({\n author: (await this.guardClient.whoAmI()).sub,\n fileName: data.name,\n lastModified: data.lastModified,\n size: data.size,\n })\n\n let meta = {\n consultationId,\n category: MetadataCategory.Consultation,\n documentType: DocumentType.Message,\n contentType: data.type,\n }\n\n let request: LockboxDataRequest = {\n data: encryptedData,\n publicMetadata: meta,\n privateMetadata: encryptedPrivateMeta,\n }\n\n return this.tellerClient.lockboxDataStore(lockboxUuid, request, lockboxOwnerUuid, previousDataUuid)\n }\n\n /**\n * @name createAttachmentData\n * @description Creates a Base64 encrypted Payload to send and store in the vault from a file\n * @param lockboxUuid\n * @param data the file stored\n * @param consultationId the consultation for which this message is sent\n * @param category the category for the attachment data\n * @param lockboxOwnerUuid the lockbox owner (ignored if lockbox is owned by self)\n * @param previousDataUuid if it's a revision of existing file, specify the previous data uuid\n * @returns the data uuid\n */\n public async createConsultationAttachmentData(\n lockboxUuid: Uuid,\n data: File,\n consultationId: string,\n documentType: DocumentType,\n lockboxOwnerUuid?: Uuid,\n previousDataUuid?: Uuid\n ): Promise<DataCreateResponse> {\n if (!this.rsa) throw IncompleteAuthentication\n\n return this.createBytesData<Meta | any>(\n lockboxUuid,\n new Uint8Array(await data.arrayBuffer()),\n {\n consultationId,\n category: MetadataCategory.Consultation,\n documentType,\n contentType: data.type,\n },\n {\n author: (await this.guardClient.whoAmI()).sub,\n fileName: data.name,\n },\n lockboxOwnerUuid,\n previousDataUuid\n )\n }\n\n /**\n * @name createJsonData\n * @description Creates a Base64 encrypted Payload to send and store in the vault. With the data input as a JSON\n * @param lockboxUuid\n * @param data\n * @param meta\n * @param privateMeta the metadata that will be secured in the vault\n * @param lockboxOwnerUuid the lockbox owner (ignored if lockbox is owned by self)\n * @param previousDataUuid if it's a revision of existing data, specify the previous data uuid\n * @returns the data uuid\n */\n public async createJsonData<T = Meta>(\n lockboxUuid: Uuid,\n data: any,\n meta?: T,\n privateMeta?: { [val: string]: any },\n lockboxOwnerUuid?: Uuid,\n previousDataUuid?: Uuid\n ): Promise<DataCreateResponse> {\n if (!this.rsa) throw IncompleteAuthentication\n\n let symmetricEncryptor = await this.getCachedSecretCryptor(lockboxUuid, lockboxOwnerUuid)\n let encryptedData = symmetricEncryptor.jsonEncryptToBase64Payload(data)\n let encryptedPrivateMeta = symmetricEncryptor.jsonEncryptToBase64Payload(privateMeta)\n\n let request: LockboxDataRequest = {\n data: encryptedData,\n publicMetadata: meta,\n privateMetadata: encryptedPrivateMeta,\n }\n\n return this.tellerClient.lockboxDataStore(lockboxUuid, request, lockboxOwnerUuid, previousDataUuid)\n }\n\n /**\n * Get or upsert a data in lockbox\n * @param lockboxUuid the lockbox uuid\n * @param data the data to insert\n * @param publicMetadata the public Metadata\n * @param privateMetadata the private Metadata\n * @param forceReplace set true when the insertion of data requires to replace the data when it exists already\n * @returns the data uuid\n */\n public async getOrInsertJsonData<M = Metadata>(\n lockboxUuid: Uuid,\n data: any,\n publicMetadata: M,\n privateMetadata: Metadata,\n forceReplace: boolean = false\n ): Promise<Uuid> {\n let manifest = await this.vaultClient.lockboxManifestGet(lockboxUuid, publicMetadata)\n if (!forceReplace && manifest.length > 0) {\n console.log(`The data for ${JSON.stringify(publicMetadata)} already exist`)\n return manifest[0].dataUuid\n } else\n return (\n await this.createJsonData<M>(\n lockboxUuid,\n data,\n publicMetadata,\n privateMetadata,\n undefined,\n forceReplace && manifest.length > 0 ? manifest[0].dataUuid : undefined // if forceReplace and data already exist, then replace data. Otherwise insert it\n ).catch((err) => {\n console.error(`Error while upserting data ${JSON.stringify(publicMetadata)} data`, err)\n throw err\n })\n ).dataUuid\n }\n\n /**\n * @name createBytesData\n * @description Creates a Base64 encrypted Payload to send and store in the vault. With the data input as a Bytes\n * @param lockboxUuid\n * @param data\n * @param meta\n * @param privateMeta the metadata that will be secured in the vault\n * @param lockboxOwnerUuid the lockbox owner (ignored if lockbox is owned by self)\n * @param previousDataUuid if it's a revision of existing data, specify the previous data uuid\n * @returns the data uuid\n */\n public async createBytesData<T = Meta>(\n lockboxUuid: Uuid,\n data: Uint8Array,\n meta: T,\n privateMeta: { [val: string]: any },\n lockboxOwnerUuid?: Uuid,\n previousDataUuid?: Uuid\n ): Promise<DataCreateResponse> {\n if (!this.rsa) throw IncompleteAuthentication\n let symmetricEncryptor = await this.getCachedSecretCryptor(lockboxUuid, lockboxOwnerUuid)\n let encryptedData = symmetricEncryptor.bytesEncryptToBase64Payload(data)\n let encryptedPrivateMeta = symmetricEncryptor.jsonEncryptToBase64Payload(privateMeta)\n\n let request: LockboxDataRequest = {\n data: encryptedData,\n publicMetadata: meta,\n privateMetadata: encryptedPrivateMeta,\n }\n\n return this.tellerClient.lockboxDataStore(lockboxUuid, request, lockboxOwnerUuid, previousDataUuid)\n }\n\n /**\n * @name getJsonData\n * @description Fetches and decrypts the lockbox data with the cached shared secret.\n * Decrypts the data to a valid JSON object. If this is impossible, the call to the WASM binary will fail\n *\n * @type T is the generic type specifying the return type object of the function\n * @param lockboxUuid\n * @param dataUuid\n * @param lockboxOwnerUuid the lockbox owner (ignored if lockbox is owned by self)\n * @returns the data specified by the generic type <T>\n */\n public async getJsonData<T = any>(lockboxUuid: Uuid, dataUuid: Uuid, lockboxOwnerUuid?: Uuid): Promise<T> {\n if (!this.rsa) throw IncompleteAuthentication\n\n let [encryptedPayload, symmetricDecryptor] = await Promise.all([\n this.vaultClient.lockboxDataGet(lockboxUuid, dataUuid, lockboxOwnerUuid),\n this.getCachedSecretCryptor(lockboxUuid, lockboxOwnerUuid),\n ])\n\n return symmetricDecryptor.base64PayloadDecryptToJson(encryptedPayload.data)\n }\n /**\n * @description Fetches and decrypts the lockbox data with the cached shared secret.\n * @param lockboxUuid\n * @param dataUuid\n * @param lockboxOwnerUuid the lockbox owner (ignored if lockbox is owned by self)\n * @returns the bytes data\n */\n public async getBytesData(lockboxUuid: Uuid, dataUuid: Uuid, lockboxOwnerUuid?: Uuid): Promise<Uint8Array> {\n if (!this.rsa) throw IncompleteAuthentication\n\n let [encryptedPayload, symmetricDecryptor] = await Promise.all([\n this.vaultClient.lockboxDataGet(lockboxUuid, dataUuid, lockboxOwnerUuid),\n this.getCachedSecretCryptor(lockboxUuid, lockboxOwnerUuid),\n ])\n\n return symmetricDecryptor.base64PayloadDecryptToBytes(encryptedPayload.data)\n }\n\n /**\n * @name getGrants\n * @description Get all lockboxes granted to user with the applied filter\n * @note this function returns cached grants and will not update unless the page is refreshed\n * @todo some versions of lockboxes do not make use of lockbox metadata\n * in this case, all lockboxes need to be filtered one-by-one to find the correct one\n * Remove if this is no longer the case\n * @param filter: the consultationId in which the grant exists\n * @returns decrypted lockboxes granted to user\n */\n public async getGrants(filter?: { consultationId: Uuid }, forceRefresh: boolean = false): Promise<Grant[]> {\n if (!this.rsa) throw IncompleteAuthentication\n\n let filterString = JSON.stringify(filter)\n // retrieves cached grants\n // Note: if filters is set to empty, it will be stored in the `undefined` key\n if (!forceRefresh && this.cachedMetadataGrants[filterString]) return this.cachedMetadataGrants[filterString]\n\n // if there is a filter to apply, then the grant can be retrieved from the vault index, otherwise, all grants are fetched\n // Note: will work only if the filter being applied is exclusively a consult id\n const grantsByConsultLockbox = filter ? (\n await this.vaultClient.vaultIndexGet([IndexKey.ConsultationLockbox], [filter.consultationId])\n .then((res) => res[IndexKey.ConsultationLockbox])\n .catch((e) => {\n console.error(e)\n return []\n })\n ) : undefined\n const decryptedConsults = decryptConsultLockboxGrants(grantsByConsultLockbox ?? [], this.rsa)\n if (decryptedConsults.length > 0) {\n console.info('[sdk:index] Grants found in user`s constant time secure index')\n this.cachedMetadataGrants[JSON.stringify(filter)] = decryptedConsults\n return this.cachedMetadataGrants[filterString]\n }\n\n let encryptedGrants\n // if there are no grants with the applied filter from index, attempt for naive filter with backwards compatibility\n if (filter) {\n encryptedGrants = await filterGrantsWithLockboxMetadata(this, filter, this.vaultIndex, forceRefresh)\n } else {\n encryptedGrants = (await this.vaultClient.grantsGet()).grants\n }\n\n const decryptedGrants = await decryptGrants(encryptedGrants, this.rsa)\n // sets the cached grant\n this.cachedMetadataGrants[filterString] = decryptedGrants\n return decryptedGrants\n }\n\n /**\n * @name getCachedSecretCryptor\n * @description Retrieves the cached lockbox secret or fetches the secret from vault, then creates the symmetric cryptor and stores it in memory\n * @param lockboxUuid\n * @param lockboxOwnerUuid the lockbox owner (ignored if lockbox is owned by self)\n * @returns\n */\n async getCachedSecretCryptor(lockboxUuid: string, lockboxOwnerUuid?: string): Promise<OroToolbox.CryptoChaCha> {\n if (!this.rsa) throw IncompleteAuthentication\n\n let index = this.secrets.findIndex((secret) => secret.lockboxUuid === lockboxUuid)\n if (index === -1) {\n let encryptedSecret = (await this.vaultClient.lockboxSecretGet(lockboxUuid, lockboxOwnerUuid)).sharedSecret\n\n let secret = this.rsa.base64DecryptToBytes(encryptedSecret)\n let cryptor = this.toolbox.CryptoChaCha.fromKey(secret)\n this.secrets.push({ lockboxUuid, cryptor })\n return cryptor\n } else {\n return this.secrets[index].cryptor\n }\n }\n\n /**\n * Retrieves the patient personal information associated to the `consultationId`\n * The `consultationId` only helps to retrieve the patient lockboxes\n * Note: it is possible to have several personal informations data\n * @param consultationId The consultation Id\n * @param category The personal MetadataCategory to fetch\n * @param forceRefresh force data refresh (default to false)\n * @returns the personal data\n */\n public async getPersonalInformationsFromConsultId(\n consultationId: Uuid,\n category: MetadataCategory.Personal | MetadataCategory.ChildPersonal | MetadataCategory.OtherPersonal,\n forceRefresh = false\n ): Promise<LocalizedData<PopulatedWorkflowData>[]> {\n return this.getMetaCategoryFromConsultId(consultationId, category, forceRefresh)\n }\n\n /**\n * Retrieves the patient medical data associated to the `consultationId`\n * The `consultationId` only helps to retrieve the patient lockboxes\n * Note: it is possible to have several medical data\n * @param consultationId The consultation Id\n * @param forceRefresh force data refresh (default to false)\n * @returns the medical data\n */\n public async getMedicalDataFromConsultId(\n consultationId: Uuid,\n forceRefresh = false\n ): Promise<LocalizedData<PopulatedWorkflowData>[]> {\n return this.getMetaCategoryFromConsultId(consultationId, MetadataCategory.Medical, forceRefresh)\n }\n\n private async getMetaCategoryFromConsultId(\n consultationId: Uuid,\n category: MetadataCategory,\n forceRefresh = false\n ): Promise<LocalizedData<PopulatedWorkflowData>[]> {\n let grants = await this.getGrants({ consultationId })\n let workflowData: LocalizedData<PopulatedWorkflowData>[] = []\n for (let grant of grants) {\n let manifest = await this.getLockboxManifest(\n grant.lockboxUuid!,\n {\n category,\n documentType: DocumentType.PopulatedWorkflowData,\n consultationIds: [consultationId],\n },\n true,\n grant.lockboxOwnerUuid,\n forceRefresh\n )\n\n // TODO: find another solution for backwards compatibility (those without the metadata consultationIds)\n if (manifest.length === 0) {\n manifest = (\n await this.getLockboxManifest(\n grant.lockboxUuid!,\n {\n category,\n documentType: DocumentType.PopulatedWorkflowData,\n // backward compatiblility with TonTest\n },\n true,\n grant.lockboxOwnerUuid,\n forceRefresh\n )\n ).filter((entry) => !entry.metadata.consultationIds) // Keep only entries without associated consultationIds\n }\n let data = await Promise.all(\n manifest.map(async (entry) => {\n return {\n lockboxOwnerUuid: grant.lockboxOwnerUuid,\n lockboxUuid: grant.lockboxUuid!,\n dataUuid: entry.dataUuid,\n data: await this.getJsonData<PopulatedWorkflowData>(grant.lockboxUuid!, entry.dataUuid),\n }\n })\n )\n workflowData = { ...workflowData, ...data }\n }\n return workflowData\n }\n\n /**\n * @description retrieves the personal information stored in the first owned lockbox\n * @param userId The user Id\n * @returns the personal data\n */\n public async getPersonalInformations(userId: Uuid): Promise<LocalizedData<PopulatedWorkflowData>> {\n const grant = (await this.getGrants()).find((lockbox) => lockbox.lockboxOwnerUuid === userId)\n\n if (!grant) {\n throw MissingGrant\n }\n\n const { lockboxUuid, lockboxOwnerUuid } = grant\n\n if (!lockboxUuid) throw MissingLockbox\n\n if (!lockboxOwnerUuid) throw MissingLockboxOwner\n\n const identificationDataUuid = (\n await this.getLockboxManifest(\n lockboxUuid,\n {\n category: MetadataCategory.Personal,\n documentType: DocumentType.PopulatedWorkflowData,\n },\n false,\n userId\n )\n )[0].dataUuid\n\n return {\n lockboxOwnerUuid,\n lockboxUuid,\n dataUuid: identificationDataUuid,\n data: await this.getJsonData<PopulatedWorkflowData>(lockboxUuid, identificationDataUuid),\n }\n }\n\n /**\n * Retrieves the grant associated to a consultationId\n * @note returns the first grant only\n * @param consultationId The consultationId\n * @returns the grant\n */\n public async getGrantFromConsultId(consultationId: Uuid): Promise<Grant | undefined> {\n let grants = await this.getGrants({ consultationId })\n\n if (grants.length === 0) {\n throw AssociatedLockboxNotFound\n }\n\n return grants[0]\n }\n\n /**\n * retrieves the identity associated to the `consultationId`\n * @param consultationId The consultation Id\n * @returns the identity\n */\n public async getIdentityFromConsultId(consultationId: Uuid): Promise<IdentityResponse | undefined> {\n const grant = await this.getGrantFromConsultId(consultationId)\n\n if (grant && grant.lockboxOwnerUuid) {\n return await this.guardClient.identityGet(grant.lockboxOwnerUuid)\n } else {\n return undefined\n }\n }\n\n /**\n * retrieves the lockbox manifest for a given lockbox and add's its private metadata\n * @note the lockbox manifest will retrieved the cached manifest first unless force refresh is enabled\n * @param lockboxUuid\n * @param filter\n * @param expandPrivateMetadata\n * @param lockboxOwnerUuid\n * @param forceRefresh\n * @returns the lockbox manifest\n */\n public async getLockboxManifest(\n lockboxUuid: Uuid,\n filter: Metadata,\n expandPrivateMetadata: boolean,\n lockboxOwnerUuid?: Uuid,\n forceRefresh: boolean = false\n ): Promise<LockboxManifest> {\n let manifestKey = JSON.stringify({\n lockboxUuid,\n filter,\n expandPrivateMetadata,\n lockboxOwnerUuid,\n })\n if (!forceRefresh && this.cachedManifest[manifestKey]) return this.cachedManifest[manifestKey]\n\n return this.vaultClient.lockboxManifestGet(lockboxUuid, filter, lockboxOwnerUuid).then((manifest) => {\n return Promise.all(\n manifest.map(async (entry) => {\n if (expandPrivateMetadata && entry.metadata.privateMetadata) {\n let privateMeta = await this.getJsonData<Metadata>(\n lockboxUuid!,\n entry.metadata.privateMetadata,\n lockboxOwnerUuid\n )\n entry.metadata = {\n ...entry.metadata,\n ...privateMeta,\n }\n }\n return entry\n })\n ).then((manifest) => (this.cachedManifest[manifestKey] = manifest))\n })\n }\n\n /**\n * @description Create or update the personal information and store it in the first owned lockbox\n * @param identity The identity to use\n * @param data The personal data to store\n * @param dataUuid (optional) The dataUuid to update\n * @returns\n */\n public async createPersonalInformations(\n identity: IdentityResponse,\n data: PopulatedWorkflowData,\n dataUuid?: string\n ): Promise<DataCreateResponse> {\n const lockboxUuid = (await this.getGrants()).find(\n (lockbox) => lockbox.lockboxOwnerUuid === identity.id\n )?.lockboxUuid\n\n if (lockboxUuid) {\n return this.createJsonData<PersonalMeta>(\n lockboxUuid,\n data,\n {\n category: MetadataCategory.Personal,\n documentType: DocumentType.PopulatedWorkflowData,\n },\n {},\n undefined,\n dataUuid\n )\n } else {\n throw MissingLockbox\n }\n }\n\n /**\n * Create or update user Preference\n * @param identity\n * @param preference\n * @param dataUuid\n * @returns\n */\n public async createUserPreference(\n identity: IdentityResponse,\n preference: UserPreference,\n dataUuid?: string\n ): Promise<DataCreateResponse> {\n const lockboxUuid = (await this.getGrants()).find(\n (lockbox) => lockbox.lockboxOwnerUuid === identity.id\n )?.lockboxUuid\n\n if (lockboxUuid) {\n return this.createJsonData<PreferenceMeta>(\n lockboxUuid,\n preference,\n {\n category: MetadataCategory.Preference,\n contentType: 'application/json',\n },\n {},\n undefined,\n dataUuid\n )\n } else {\n throw MissingLockbox\n }\n }\n\n /**\n * retrieves the user preference from a grant\n * @param grant The grant\n * @returns the user preference\n */\n public async getDataFromGrant<T = any>(grant: Grant, filter: Metadata): Promise<LocalizedData<T>> {\n const { lockboxUuid, lockboxOwnerUuid } = grant\n\n if (!lockboxUuid) throw MissingLockbox\n if (!lockboxOwnerUuid) throw MissingLockboxOwner\n const identificationDataUuid = (\n await this.getLockboxManifest(\n lockboxUuid,\n\n filter,\n false,\n grant.lockboxOwnerUuid,\n true\n )\n )[0].dataUuid\n\n return {\n lockboxOwnerUuid,\n lockboxUuid,\n dataUuid: identificationDataUuid,\n data: await this.getJsonData<T>(lockboxUuid, identificationDataUuid),\n }\n }\n\n /**\n * retrieves the user preference from a consultation id\n * @param consultationId The related consultationId\n * @returns the user preference\n */\n public async getUserPreferenceFromConsultId(consultationId: string): Promise<LocalizedData<UserPreference>> {\n const grant = await this.getGrantFromConsultId(consultationId)\n\n if (!grant) throw MissingGrant\n\n return this.getDataFromGrant<UserPreference>(grant, {\n category: MetadataCategory.Preference,\n contentType: 'application/json',\n })\n }\n\n /**\n * retrieves the user preference stored in the first owned lockbox from identity\n * @param identity The identity to use\n * @returns the user preference\n */\n public async getUserPreference(identity: IdentityResponse): Promise<LocalizedData<UserPreference>> {\n const grant = (await this.getGrants()).find((lockbox) => lockbox.lockboxOwnerUuid === identity.id)\n\n if (!grant) throw MissingGrant\n\n return this.getDataFromGrant<UserPreference>(grant, {\n category: MetadataCategory.Preference,\n contentType: 'application/json',\n })\n }\n\n /**\n * retrieves the user preference from a consultation id\n * @param consultationId The related consultationId\n * @returns the user preference\n */\n public async getRecoveryDataFromConsultId(consultationId: string): Promise<LocalizedData<RecoveryData>> {\n const grant = await this.getGrantFromConsultId(consultationId)\n\n if (!grant) throw MissingGrant\n\n return this.getDataFromGrant<RecoveryData>(grant, {\n category: MetadataCategory.Recovery,\n contentType: 'application/json',\n })\n }\n\n /**\n * retrieves the user preference stored in the first owned lockbox from identity\n * @param identity The identity to use\n * @returns the user preference\n */\n public async getRecoveryData(identity: IdentityResponse): Promise<LocalizedData<RecoveryData>> {\n const grant = (await this.getGrants()).find((lockbox) => lockbox.lockboxOwnerUuid === identity.id)\n\n if (!grant) throw MissingGrant\n\n return this.getDataFromGrant(grant, {\n category: MetadataCategory.Recovery,\n contentType: 'application/json',\n })\n }\n\n /**\n * @name getAssignedConsultations\n * @description finds all assigned or owned consultations for the logged user\n * Steps:\n * - Retrieves all granted lockboxes given to the logged user\n * - for each lockbox, find all consultation ids\n * - for each consultation id, retrieve the consult information\n * @param practiceUuid the uuid of the practice to look consult into\n * @returns the list of consults\n */\n public async getAssignedConsultations(practiceUuid: Uuid, forceRefresh: boolean = false): Promise<Consult[]> {\n return Promise.all(\n (await this.getGrants(undefined, forceRefresh)).map((grant) =>\n this.getLockboxManifest(\n grant.lockboxUuid!,\n {\n category: MetadataCategory.Consultation,\n documentType: DocumentType.PopulatedWorkflowData,\n },\n true,\n undefined,\n forceRefresh\n ).then((manifest) =>\n Promise.all(\n manifest.map(\n async (entry) =>\n await this.consultClient.getConsultByUUID(entry.metadata.consultationId, practiceUuid)\n )\n ).then((promise) => promise.flat())\n )\n )\n ).then((consults) => consults.flat())\n }\n\n /**\n * Gets the past consultations of the patient as well as his relatives if any\n * @param consultationId any consultation uuid from which we will fetch all the other consultations of the same patient as the owner of this consultation id\n * @param practiceUuid\n */\n public async getPastConsultationsFromConsultId(\n consultationId: string,\n practiceUuid: string\n ): Promise<Consult[] | undefined> {\n const grant = await this.getGrantFromConsultId(consultationId)\n if (!grant) return undefined\n\n let consultationsInLockbox: string[] = (\n await this.vaultClient.lockboxMetadataGet(\n grant.lockboxUuid!,\n ['consultationId'],\n ['consultationId'],\n {\n category: MetadataCategory.Consultation,\n documentType: DocumentType.PopulatedWorkflowData,\n },\n grant.lockboxOwnerUuid\n )\n )\n .flat()\n .map((metadata: { consultationId: string }) => metadata.consultationId)\n\n if (consultationsInLockbox.length == 0) return []\n\n return await Promise.all(\n consultationsInLockbox.map(async (consultId: string) => {\n return await this.consultClient.getConsultByUUID(consultId, practiceUuid)\n })\n )\n }\n\n /**\n * @name getPatientConsultationData\n * @description retrieves the consultation data\n * @param consultationId\n * @returns\n */\n public async getPatientConsultationData(\n consultationId: Uuid,\n forceRefresh: boolean = false\n ): Promise<PopulatedWorkflowData[]> {\n //TODO: make use of getPatientDocumentsList instead of doing it manually here\n return Promise.all(\n (await this.getGrants({ consultationId }, forceRefresh))\n .map((grant) =>\n this.getLockboxManifest(\n grant.lockboxUuid!,\n {\n category: MetadataCategory.Consultation,\n documentType: DocumentType.PopulatedWorkflowData,\n consultationId, //since we want to update the cached manifest (if another consult data exists)\n },\n true,\n grant.lockboxOwnerUuid,\n forceRefresh\n ).then((manifest) =>\n Promise.all(\n manifest.map((e) =>\n this.getJsonData<PopulatedWorkflowData>(\n grant.lockboxUuid!,\n e.dataUuid,\n grant.lockboxOwnerUuid\n )\n )\n )\n )\n )\n .flat()\n ).then((data) => data.flat())\n }\n\n /**\n * This function returns the patient prescriptions\n * @param consultationId\n * @returns\n */\n public async getPatientPrescriptionsList(consultationId: Uuid): Promise<Document[]> {\n return this.getPatientDocumentsList(\n {\n category: MetadataCategory.Consultation,\n documentType: DocumentType.Prescription,\n },\n true,\n consultationId\n )\n }\n\n /**\n * This function returns the patient results\n * @param consultationId\n * @returns\n */\n public async getPatientResultsList(consultationId: Uuid): Promise<Document[]> {\n return this.getPatientDocumentsList(\n {\n category: MetadataCategory.Consultation,\n documentType: DocumentType.Result,\n },\n true,\n consultationId\n )\n }\n\n /**\n * returns the patient treatment plan options\n * @param consultationId\n * @returns Document[] corresponding to the patient treatment plan options\n */\n public async getPatientTreatmentPlans(consultationId: Uuid): Promise<Document[]> {\n return this.getPatientDocumentsList(\n {\n category: MetadataCategory.Consultation,\n documentType: DocumentType.TreatmentPlan,\n },\n true,\n consultationId\n )\n }\n\n /**\n * returns a specific patient treatment plan option\n * @param consultationId\n * @param treatmentPlanId\n * @returns\n */\n public async getPatientTreatmentPlanByUuid(consultationId: Uuid, treatmentPlanId: Uuid): Promise<Document[]> {\n return this.getPatientDocumentsList(\n {\n category: MetadataCategory.Consultation,\n documentType: DocumentType.TreatmentPlan,\n treatmentPlanId,\n },\n true,\n consultationId\n )\n }\n\n /**\n * @name getPatientDocumentsList\n * @description applies the provided filter to the vault to only find those documents\n * @param filters the applied filters (e.g. type of documents)\n * @param expandPrivateMetadata whether or not, the private metadata needs to be retrieved\n * (more computationally expensive)\n * @param consultationId\n * @returns the filtered document list\n */\n public async getPatientDocumentsList(\n filters: Object,\n expandPrivateMetadata: boolean,\n consultationId: Uuid\n ): Promise<Document[]> {\n return Promise.all(\n (await this.getGrants({ consultationId }))\n .map((grant) =>\n this.getLockboxManifest(\n grant.lockboxUuid!,\n { ...filters, consultationId },\n expandPrivateMetadata,\n grant.lockboxOwnerUuid,\n true\n ).then((manifest) =>\n Promise.all(\n manifest.map(async (entry): Promise<Document> => {\n return {\n lockboxOwnerUuid: grant.lockboxOwnerUuid,\n lockboxUuid: grant.lockboxUuid!,\n ...entry,\n }\n })\n )\n )\n )\n .flat()\n ).then((data) => data.flat())\n }\n\n /****************************************************************************************************************\n * RECOVERY *\n ****************************************************************************************************************/\n\n /**\n * @name recoverPrivateKeyFromSecurityQuestions\n * @description Recovers and sets the rsa private key from the answered security questions\n * @param id\n * @param recoverySecurityQuestions\n * @param recoverySecurityAnswers\n * @param threshold the number of answers needed to recover the key\n */\n public async recoverPrivateKeyFromSecurityQuestions(\n id: Uuid,\n recoverySecurityQuestions: string[],\n recoverySecurityAnswers: string[],\n threshold: number\n ) {\n let shards: SecretShard[] = (await this.guardClient.identityGet(id)).recoverySecurityQuestions!\n let answeredShards = shards\n .filter((shard: any) => {\n // filters all answered security questions\n let indexOfQuestion = recoverySecurityQuestions.indexOf(shard.securityQuestion)\n if (indexOfQuestion === -1) return false\n return recoverySecurityAnswers[indexOfQuestion] && recoverySecurityAnswers[indexOfQuestion] != ''\n })\n .map((item: any) => {\n // appends the security answer to the answered shards\n let index = recoverySecurityQuestions.indexOf(item.securityQuestion)\n item.securityAnswer = recoverySecurityAnswers[index]\n return item\n })\n try {\n // reconstructs the key from the answered security answers\n let privateKey = this.toolbox.reconstructSecret(answeredShards, threshold)\n this.rsa = this.toolbox.CryptoRSA.fromKey(privateKey)\n } catch (e) {\n console.error(e)\n }\n }\n\n /**\n * @name recoverPrivateKeyFromPassword\n * @description Recovers and sets the rsa private key from the password\n * @param id\n * @param password\n */\n public async recoverPrivateKeyFromPassword(id: Uuid, password: string) {\n let identity = await this.guardClient.identityGet(id)\n\n let recoveryPayload = identity.recoveryPassword\n let symmetricDecryptor = this.toolbox.CryptoChaCha.fromPassphrase(password)\n let privateKey = symmetricDecryptor.base64PayloadDecryptToBytes(recoveryPayload)\n\n if (identity.recoveryLogin) {\n //Ensure we can recover from a page reload\n let symetricEncryptor = this.toolbox.CryptoChaCha.fromPassphrase(identity.recoveryLogin)\n sessionStorage.setItem(\n sessionStorePrivateKeyName(id),\n symetricEncryptor.bytesEncryptToBase64Payload(privateKey)\n )\n }\n\n this.rsa = this.toolbox.CryptoRSA.fromKey(privateKey)\n }\n\n /**\n * @name recoverPrivateKeyFromMasterKey\n * @description Recovers and sets the rsa private key from the master key\n * @param id\n * @param masterKey\n */\n public async recoverPrivateKeyFromMasterKey(id: Uuid, masterKey: string) {\n let recoveryPayload = (await this.guardClient.identityGet(id)).recoveryMasterKey!\n let symmetricDecryptor = this.toolbox.CryptoChaCha.fromPassphrase(masterKey)\n let privateKey = symmetricDecryptor.base64PayloadDecryptToBytes(recoveryPayload)\n this.rsa = this.toolbox.CryptoRSA.fromKey(privateKey)\n }\n\n /**\n * @description Generates and updates the security questions and answers payload using new recovery questions and answers\n * Important: Since the security questions generate a payload for the private key, they will never be stored on the device as they must remain secret!!!\n * @param id\n * @param recoverySecurityQuestions\n * @param recoverySecurityAnswers\n * @param threshold the number of answers needed to rebuild the secret\n */\n public async updateSecurityQuestions(\n id: Uuid,\n recoverySecurityQuestions: string[],\n recoverySecurityAnswers: string[],\n threshold: number\n ) {\n if (!this.rsa) throw IncompleteAuthentication\n let securityQuestionPayload = this.toolbox.breakSecretIntoShards(\n recoverySecurityQuestions,\n recoverySecurityAnswers,\n this.rsa.private(),\n threshold\n )\n let updateRequest = {\n recoverySecurityQuestions: securityQuestionPayload,\n }\n\n return await this.guardClient.identityUpdate(id, updateRequest)\n }\n\n /**\n * @description Generates and stores the payload encrypted payload and updates the password itself (double hash)\n * @important\n * the recovery payload uses a singly hashed password and the password stored is doubly hashed so\n * the stored password cannot derive the decryption key in the payload\n * @note\n * the old password must be provided when not performing an account recovery\n * @param id\n * @param newPassword\n * @param oldPassword\n */\n public async updatePassword(id: Uuid, newPassword: string, oldPassword?: string) {\n if (!this.rsa) throw IncompleteAuthentication\n\n let symmetricEncryptor = this.toolbox.CryptoChaCha.fromPassphrase(newPassword)\n let passwordPayload = symmetricEncryptor.bytesEncryptToBase64Payload(this.rsa.private())\n if (oldPassword) {\n oldPassword = this.toolbox.hashStringToBase64(this.toolbox.hashStringToBase64(oldPassword))\n }\n\n newPassword = this.toolbox.hashStringToBase64(this.toolbox.hashStringToBase64(newPassword))\n\n let updateRequest = {\n password: {\n oldPassword,\n newPassword,\n },\n recoveryPassword: passwordPayload,\n }\n\n return await this.guardClient.identityUpdate(id, updateRequest)\n }\n\n /**\n * @description Generates and stores the master key encrypted payload\n * Important\n * Since the master key is used to generate a payload for the private key, it will never be stored on the device as it must remain secret!\n * @param id\n * @param masterKey\n * @param lockboxUuid\n */\n async updateMasterKey(id: Uuid, masterKey: string, lockboxUuid: Uuid) {\n if (!this.rsa) throw IncompleteAuthentication\n\n let symmetricEncryptor = this.toolbox.CryptoChaCha.fromPassphrase(masterKey)\n let masterKeyPayload = symmetricEncryptor.bytesEncryptToBase64Payload(this.rsa.private())\n let updateRequest = { recoveryMasterKey: masterKeyPayload }\n const updatedIdentity = await this.guardClient.identityUpdate(id, updateRequest)\n\n await this.getOrInsertJsonData<RecoveryMeta>(\n lockboxUuid,\n { masterKey },\n {\n category: MetadataCategory.Recovery,\n contentType: 'application/json',\n },\n {},\n true\n )\n\n return updatedIdentity\n }\n}\n","import { AxiosService, CliniaResponse, FacetFilter, PlaceData } from \"oro-sdk-apis\"\n\nexport class CliniaService {\n private api: AxiosService\n\n constructor(private url: string, apiKey: string, private locale?: string) {\n this.api = new AxiosService({ headers: { 'X-Clinia-API-Key': apiKey } })\n }\n\n public placeSearch(searchOptions: {\n locale?: string\n query?: string\n facetFilters?: FacetFilter[]\n location?: string\n aroundLatLng?: string\n page?: number\n }) {\n const { locale, ...data } = searchOptions\n\n return this.api.post<CliniaResponse<PlaceData>>(\n `${this.url}/search/v1/indexes/health_facility/query`,\n data,\n {\n params: { locale: locale ?? this.locale },\n }\n )\n }\n\n public placeMatch(\n searchOptions: {\n locale?: string\n name?: string\n address?: string\n postalCode?: string\n place?: string\n region?: string\n country?: string\n },\n type?: string\n ) {\n const { locale, ...data } = searchOptions\n\n let request = this.api.post<PlaceData[]>(\n `${this.url}/search/v1/matches`,\n data,\n {\n params: { locale: locale ?? this.locale },\n }\n )\n\n if (type) {\n request = request.then((places) =>\n places.filter((place) => place.type === type)\n )\n }\n\n return request\n }\n}\n","import initApis from 'oro-sdk-apis'\nimport { OroClient } from './client'\nimport * as OroToolboxNamespace from 'oro-toolbox'\n\nexport type OroToolbox = typeof OroToolboxNamespace\n\nexport let wasmPath = 'node_modules/oro-toolbox'\n\n/**\n * This function helps you to initialize and OroClient instance\n * @param toolbox the OroToolbox object\n * @param tellerBaseURL the teller service base URL \n * @param vaultBaseURL the vault service base URL \n * @param guardBaseURL the guard service base URL \n * @param searchbaseURL the search service base URL\n * @param practiceBaseURL the practice service base URL \n * @param consultBaseURL the consult service base URL \n * @param workflowBaseURL the workflow service base URL \n * @param diagnosisBaseURL the diagnosis service base URL \n * @param authenticationCallback (optional) authenticationCallback the authentification callback \n * @returns an instance of OroClient\n */\nconst init = (\n toolbox: OroToolbox,\n tellerBaseURL: string,\n vaultBaseURL: string,\n guardBaseURL: string,\n searchBaseURL: string,\n practiceBaseURL: string,\n consultBaseURL: string,\n workflowBaseURL: string,\n diagnosisBaseURL: string,\n authenticationCallback?: (err: Error) => void\n) => {\n const {\n tellerService,\n practiceService,\n consultService,\n vaultService,\n guardService,\n searchService,\n workflowService,\n diagnosisService,\n } = initApis(\n {\n tellerBaseURL,\n vaultBaseURL,\n guardBaseURL,\n searchBaseURL,\n practiceBaseURL,\n consultBaseURL,\n workflowBaseURL,\n diagnosisBaseURL,\n },\n authenticationCallback\n )\n\n const client = new OroClient(\n toolbox,\n tellerService!,\n vaultService!,\n guardService!,\n searchService!,\n practiceService!,\n consultService!,\n workflowService!,\n diagnosisService!,\n authenticationCallback\n )\n\n return client\n}\n\nexport { OroClient } from './client'\nexport * from 'oro-sdk-apis'\nexport * from './models'\nexport * from './helpers'\nexport * from './services'\nexport { OroToolboxNamespace }\nexport default init\n"],"names":["runtime","exports","Op","Object","prototype","hasOwn","hasOwnProperty","$Symbol","Symbol","iteratorSymbol","iterator","asyncIteratorSymbol","asyncIterator","toStringTagSymbol","toStringTag","define","obj","key","value","defineProperty","enumerable","configurable","writable","err","wrap","innerFn","outerFn","self","tryLocsList","generator","create","Generator","context","Context","_invoke","state","method","arg","Error","undefined","done","delegate","delegateResult","maybeInvokeDelegate","ContinueSentinel","sent","_sent","dispatchException","abrupt","record","tryCatch","type","makeInvokeMethod","fn","call","GeneratorFunction","GeneratorFunctionPrototype","IteratorPrototype","this","getProto","getPrototypeOf","NativeIteratorPrototype","values","Gp","defineIteratorMethods","forEach","AsyncIterator","PromiseImpl","previousPromise","callInvokeWithMethodAndArg","resolve","reject","invoke","result","__await","then","unwrapped","error","TypeError","info","resultName","next","nextLoc","pushTryEntry","locs","entry","tryLoc","catchLoc","finallyLoc","afterLoc","tryEntries","push","resetTryEntry","completion","reset","iterable","iteratorMethod","isNaN","length","i","doneResult","displayName","isGeneratorFunction","genFun","ctor","constructor","name","mark","setPrototypeOf","__proto__","awrap","async","Promise","iter","keys","object","reverse","pop","skipTempReset","prev","charAt","slice","stop","rootRecord","rval","exception","handle","loc","caught","hasCatch","hasFinally","finallyEntry","complete","finish","catch","thrown","delegateYield","module","regeneratorRuntime","accidentalStrictMode","globalThis","Function","personalMetaToPrefix","MetadataCategory","Personal","ChildPersonal","OtherPersonal","identificationToPersonalInformations","data","category","prefix","birthday","firstname","gender","phone","zip","hid","pharmacy","address","toActualObject","ret","entries","fields","field","displayedAnswer","answer","sessionStorePrivateKeyName","id","IncompleteAuthentication","MissingGrant","MissingLockbox","MissingLockboxOwner","AssociatedLockboxNotFound","WorkflowAnswersMissingError","filterTriggeredAnsweredWithKind","workflowData","kind","selectedAnswers","flattenedAnswers","flattenSelectedAnswers","triggeredQuestionsWithKind","fromEntries","pages","map","a","questions","filter","question","isTriggered","triggers","flat","samePageAnswers","reduce","cur","res","questionFieldName","getWorkflowDataByCategory","triggeredQuestions","all","e","k","populateWorkflowField","populatedValue","workflowCreatedAt","createdAt","workflowId","locale","console","getImagesFromIndexDb","getMany","v","answerValue","answers","text","images","image","imageData","includes","linearAnswers","getInitialisedSelectedAnswers","workflow","useDefault","page","defaultValue","registerPatient","patientUuid","consultRequest","oroClient","masterKey","recoveryQA","consult","lockboxUuid","practitionerAdmin","retry","identity","errorsThrown","setTimeout","practiceClient","practiceGetFromUuid","uuidPractice","uuidAdmin","practiceGetPractitioners","log","practitioners","getOrCreatePatientConsultationUuid","getOrCreatePatientLockbox","guardClient","identityGet","grantLockbox","grantPromises","practitioner","uuid","IndexKey","ConsultationLockbox","grant","lockboxOwnerUuid","consultationId","consultIndex","consultIndexPromises","vaultIndexAdd","storeImageAliases","storePatientData","isoLanguageRequired","_identity","recoveryMasterKey","updateMasterKey","_identity2","recoverySecurityQuestions","updateSecurityQuestions","recoverySecurityAnswers","buildConsultSearchIndex","consultClient","updateConsultByUUID","statusMedical","MedicalStatus","New","cleanIndex","practiceGetPayment","idStripeInvoiceOrPaymentIntent","payment","uuidConsult","getConsultByUUID","consultCreate","getGrants","grants","vaultClient","lockboxCreate","isoLanguage","getOrInsertJsonData","Raw","contentType","Consultation","documentType","DocumentType","PopulatedWorkflowData","Medical","consultationIds","extractAndStorePersonalWorkflowData","Preference","dataUuids","nonNullImages","img","promises","ImageAlias","idbId","extractPersonalInfoFromWorkflowData","personalInfoPopulatedWfData","childPersonalInfoPopulatedWfData","otherPersonalInfoPopulatedWfData","consultUuid","terms","personalInfo","childPersonalInfo","otherPersonalInfo","searchClient","index","decryptGrants","encryptedGrants","rsaKey","encryptedLockbox","uuidParse","base64DecryptToBytes","decryptConsultLockboxGrants","encryptedConsultLockboxes","base64DecryptToJson","encryptedIndexEntry","grantsTuple","grantTuples","filterGrantsWithLockboxMetadata","vaultIndex","forceRefresh","buildLegacyVaultIndex","indexConsults","consultGrant","consultGrants","lockboxMetadataGet","setVaultIndex","OroClient","toolbox","tellerClient","workflowClient","diagnosisClient","authenticationCallback","cachedMetadataGrants","cachedManifest","signUp","email","password","practice","tosAndCpAcceptance","tokenData","subscription","skipEmailValidation","rsa","CryptoRSA","privateKey","symmetricEncryptor","CryptoChaCha","fromPassphrase","recoveryPassword","bytesEncryptToBase64Payload","hashedPassword","hashStringToBase64","emailConfirmed","signupRequest","practiceUuid","toLowerCase","publicKey","encodeToBase64","identityCreate","recoveryLogin","symetricEncryptor","sessionStorage","setItem","confirmEmail","accessToken","setTokens","whoAmI","identityUpdate","sub","signIn","otp","tokenRequest","authToken","userUuid","recoverPrivateKeyFromPassword","resumeSession","recoveryPayload","getItem","recoveryKey","symmetricDecryptor","base64PayloadDecryptToBytes","fromKey","localEncryptToJsonPayload","chaChaKey","encryptedData","jsonEncryptToBase64Payload","encryptedKey","encryptToBytes","localDecryptJsonPayload","base64PayloadDecryptToJson","signOut","secrets","refreshToken","authLogout","buildVaultIndex","forceUpdateIndexEntries","_this","consults","alert","indexOwnerUuid","rsaPub","decodeFromBase64","encryptedIndex","uniqueHash","timestamp","jsonWithPubEncryptToBase64","_this2","JSON","stringify","_this2$vaultIndex$Ind","find","vaultIndexPut","indexSnapshotAdd","_index$IndexKey$Consu","c","vaultIndexSnapshotPut","granteeUuid","getCachedSecretCryptor","secret","granteePublicKey","granteeEncryptedSecret","bytesWithPubEncryptToBase64","request","encryptedSecret","lockboxGrant","createMessageData","message","previousDataUuid","author","encryptedPrivateMeta","lockboxDataStore","publicMetadata","Message","privateMetadata","createMessageAttachmentData","Uint8Array","arrayBuffer","lastModified","size","fileName","createConsultationAttachmentData","createBytesData","createJsonData","meta","privateMeta","forceReplace","lockboxManifestGet","manifest","dataUuid","getJsonData","lockboxDataGet","getBytesData","filterString","vaultIndexGet","decryptedConsults","grantsByConsultLockbox","grantsGet","decryptedGrants","findIndex","lockboxSecretGet","sharedSecret","cryptor","getPersonalInformationsFromConsultId","getMetaCategoryFromConsultId","getMedicalDataFromConsultId","_this3","getLockboxManifest","metadata","getPersonalInformations","userId","lockbox","identificationDataUuid","getGrantFromConsultId","getIdentityFromConsultId","expandPrivateMetadata","manifestKey","_this4","createPersonalInformations","_yield$this$getGrants","createUserPreference","preference","_yield$this$getGrants2","getDataFromGrant","getUserPreferenceFromConsultId","getUserPreference","getRecoveryDataFromConsultId","Recovery","getRecoveryData","getAssignedConsultations","_this5","promise","getPastConsultationsFromConsultId","consultationsInLockbox","consultId","_this6","getPatientConsultationData","_this7","getPatientPrescriptionsList","getPatientDocumentsList","Prescription","getPatientResultsList","Result","getPatientTreatmentPlans","TreatmentPlan","getPatientTreatmentPlanByUuid","treatmentPlanId","filters","_this8","recoverPrivateKeyFromSecurityQuestions","threshold","answeredShards","shard","indexOfQuestion","indexOf","securityQuestion","item","securityAnswer","reconstructSecret","recoverPrivateKeyFromMasterKey","securityQuestionPayload","breakSecretIntoShards","updateRequest","updatePassword","newPassword","oldPassword","passwordPayload","masterKeyPayload","updatedIdentity","CliniaService","url","apiKey","api","AxiosService","headers","placeSearch","searchOptions","post","params","placeMatch","places","place","tellerBaseURL","vaultBaseURL","guardBaseURL","searchBaseURL","practiceBaseURL","consultBaseURL","workflowBaseURL","diagnosisBaseURL","initApis","tellerService","vaultService","guardService","searchService","practiceService","consultService","workflowService","diagnosisService","arrSelectedLocality","flatMap","currentAnswerPage","arrCountryFields","workflowFieldName","arrProvinceFields","arrConsultLocalFields","currentFieldName","currentSelectedLocality","startsWith","allowedLocalityPatterns","finalLocality","extractedSelected","exec","indexSelectedPriority","isoSelectedValue","extractedFinal","indexFinalPriority","populatedWorkflow","filledWorkflow","parse","pageIdx","infos"],"mappings":"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"}
1
+ {"version":3,"file":"oro-sdk.cjs.production.min.js","sources":["../node_modules/regenerator-runtime/runtime.js","../src/helpers/client.ts","../src/models/error.ts","../src/helpers/workflow.ts","../src/helpers/patient-registration.ts","../src/helpers/vault-grants.ts","../src/sdk-revision/client.ts","../src/client.ts","../src/services/external/clinia.ts","../src/index.ts"],"sourcesContent":["/**\n * Copyright (c) 2014-present, Facebook, Inc.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nvar runtime = (function (exports) {\n \"use strict\";\n\n var Op = Object.prototype;\n var hasOwn = Op.hasOwnProperty;\n var undefined; // More compressible than void 0.\n var $Symbol = typeof Symbol === \"function\" ? Symbol : {};\n var iteratorSymbol = $Symbol.iterator || \"@@iterator\";\n var asyncIteratorSymbol = $Symbol.asyncIterator || \"@@asyncIterator\";\n var toStringTagSymbol = $Symbol.toStringTag || \"@@toStringTag\";\n\n function define(obj, key, value) {\n Object.defineProperty(obj, key, {\n value: value,\n enumerable: true,\n configurable: true,\n writable: true\n });\n return obj[key];\n }\n try {\n // IE 8 has a broken Object.defineProperty that only works on DOM objects.\n define({}, \"\");\n } catch (err) {\n define = function(obj, key, value) {\n return obj[key] = value;\n };\n }\n\n function wrap(innerFn, outerFn, self, tryLocsList) {\n // If outerFn provided and outerFn.prototype is a Generator, then outerFn.prototype instanceof Generator.\n var protoGenerator = outerFn && outerFn.prototype instanceof Generator ? outerFn : Generator;\n var generator = Object.create(protoGenerator.prototype);\n var context = new Context(tryLocsList || []);\n\n // The ._invoke method unifies the implementations of the .next,\n // .throw, and .return methods.\n generator._invoke = makeInvokeMethod(innerFn, self, context);\n\n return generator;\n }\n exports.wrap = wrap;\n\n // Try/catch helper to minimize deoptimizations. Returns a completion\n // record like context.tryEntries[i].completion. This interface could\n // have been (and was previously) designed to take a closure to be\n // invoked without arguments, but in all the cases we care about we\n // already have an existing method we want to call, so there's no need\n // to create a new function object. We can even get away with assuming\n // the method takes exactly one argument, since that happens to be true\n // in every case, so we don't have to touch the arguments object. The\n // only additional allocation required is the completion record, which\n // has a stable shape and so hopefully should be cheap to allocate.\n function tryCatch(fn, obj, arg) {\n try {\n return { type: \"normal\", arg: fn.call(obj, arg) };\n } catch (err) {\n return { type: \"throw\", arg: err };\n }\n }\n\n var GenStateSuspendedStart = \"suspendedStart\";\n var GenStateSuspendedYield = \"suspendedYield\";\n var GenStateExecuting = \"executing\";\n var GenStateCompleted = \"completed\";\n\n // Returning this object from the innerFn has the same effect as\n // breaking out of the dispatch switch statement.\n var ContinueSentinel = {};\n\n // Dummy constructor functions that we use as the .constructor and\n // .constructor.prototype properties for functions that return Generator\n // objects. For full spec compliance, you may wish to configure your\n // minifier not to mangle the names of these two functions.\n function Generator() {}\n function GeneratorFunction() {}\n function GeneratorFunctionPrototype() {}\n\n // This is a polyfill for %IteratorPrototype% for environments that\n // don't natively support it.\n var IteratorPrototype = {};\n define(IteratorPrototype, iteratorSymbol, function () {\n return this;\n });\n\n var getProto = Object.getPrototypeOf;\n var NativeIteratorPrototype = getProto && getProto(getProto(values([])));\n if (NativeIteratorPrototype &&\n NativeIteratorPrototype !== Op &&\n hasOwn.call(NativeIteratorPrototype, iteratorSymbol)) {\n // This environment has a native %IteratorPrototype%; use it instead\n // of the polyfill.\n IteratorPrototype = NativeIteratorPrototype;\n }\n\n var Gp = GeneratorFunctionPrototype.prototype =\n Generator.prototype = Object.create(IteratorPrototype);\n GeneratorFunction.prototype = GeneratorFunctionPrototype;\n define(Gp, \"constructor\", GeneratorFunctionPrototype);\n define(GeneratorFunctionPrototype, \"constructor\", GeneratorFunction);\n GeneratorFunction.displayName = define(\n GeneratorFunctionPrototype,\n toStringTagSymbol,\n \"GeneratorFunction\"\n );\n\n // Helper for defining the .next, .throw, and .return methods of the\n // Iterator interface in terms of a single ._invoke method.\n function defineIteratorMethods(prototype) {\n [\"next\", \"throw\", \"return\"].forEach(function(method) {\n define(prototype, method, function(arg) {\n return this._invoke(method, arg);\n });\n });\n }\n\n exports.isGeneratorFunction = function(genFun) {\n var ctor = typeof genFun === \"function\" && genFun.constructor;\n return ctor\n ? ctor === GeneratorFunction ||\n // For the native GeneratorFunction constructor, the best we can\n // do is to check its .name property.\n (ctor.displayName || ctor.name) === \"GeneratorFunction\"\n : false;\n };\n\n exports.mark = function(genFun) {\n if (Object.setPrototypeOf) {\n Object.setPrototypeOf(genFun, GeneratorFunctionPrototype);\n } else {\n genFun.__proto__ = GeneratorFunctionPrototype;\n define(genFun, toStringTagSymbol, \"GeneratorFunction\");\n }\n genFun.prototype = Object.create(Gp);\n return genFun;\n };\n\n // Within the body of any async function, `await x` is transformed to\n // `yield regeneratorRuntime.awrap(x)`, so that the runtime can test\n // `hasOwn.call(value, \"__await\")` to determine if the yielded value is\n // meant to be awaited.\n exports.awrap = function(arg) {\n return { __await: arg };\n };\n\n function AsyncIterator(generator, PromiseImpl) {\n function invoke(method, arg, resolve, reject) {\n var record = tryCatch(generator[method], generator, arg);\n if (record.type === \"throw\") {\n reject(record.arg);\n } else {\n var result = record.arg;\n var value = result.value;\n if (value &&\n typeof value === \"object\" &&\n hasOwn.call(value, \"__await\")) {\n return PromiseImpl.resolve(value.__await).then(function(value) {\n invoke(\"next\", value, resolve, reject);\n }, function(err) {\n invoke(\"throw\", err, resolve, reject);\n });\n }\n\n return PromiseImpl.resolve(value).then(function(unwrapped) {\n // When a yielded Promise is resolved, its final value becomes\n // the .value of the Promise<{value,done}> result for the\n // current iteration.\n result.value = unwrapped;\n resolve(result);\n }, function(error) {\n // If a rejected Promise was yielded, throw the rejection back\n // into the async generator function so it can be handled there.\n return invoke(\"throw\", error, resolve, reject);\n });\n }\n }\n\n var previousPromise;\n\n function enqueue(method, arg) {\n function callInvokeWithMethodAndArg() {\n return new PromiseImpl(function(resolve, reject) {\n invoke(method, arg, resolve, reject);\n });\n }\n\n return previousPromise =\n // If enqueue has been called before, then we want to wait until\n // all previous Promises have been resolved before calling invoke,\n // so that results are always delivered in the correct order. If\n // enqueue has not been called before, then it is important to\n // call invoke immediately, without waiting on a callback to fire,\n // so that the async generator function has the opportunity to do\n // any necessary setup in a predictable way. This predictability\n // is why the Promise constructor synchronously invokes its\n // executor callback, and why async functions synchronously\n // execute code before the first await. Since we implement simple\n // async functions in terms of async generators, it is especially\n // important to get this right, even though it requires care.\n previousPromise ? previousPromise.then(\n callInvokeWithMethodAndArg,\n // Avoid propagating failures to Promises returned by later\n // invocations of the iterator.\n callInvokeWithMethodAndArg\n ) : callInvokeWithMethodAndArg();\n }\n\n // Define the unified helper method that is used to implement .next,\n // .throw, and .return (see defineIteratorMethods).\n this._invoke = enqueue;\n }\n\n defineIteratorMethods(AsyncIterator.prototype);\n define(AsyncIterator.prototype, asyncIteratorSymbol, function () {\n return this;\n });\n exports.AsyncIterator = AsyncIterator;\n\n // Note that simple async functions are implemented on top of\n // AsyncIterator objects; they just return a Promise for the value of\n // the final result produced by the iterator.\n exports.async = function(innerFn, outerFn, self, tryLocsList, PromiseImpl) {\n if (PromiseImpl === void 0) PromiseImpl = Promise;\n\n var iter = new AsyncIterator(\n wrap(innerFn, outerFn, self, tryLocsList),\n PromiseImpl\n );\n\n return exports.isGeneratorFunction(outerFn)\n ? iter // If outerFn is a generator, return the full iterator.\n : iter.next().then(function(result) {\n return result.done ? result.value : iter.next();\n });\n };\n\n function makeInvokeMethod(innerFn, self, context) {\n var state = GenStateSuspendedStart;\n\n return function invoke(method, arg) {\n if (state === GenStateExecuting) {\n throw new Error(\"Generator is already running\");\n }\n\n if (state === GenStateCompleted) {\n if (method === \"throw\") {\n throw arg;\n }\n\n // Be forgiving, per 25.3.3.3.3 of the spec:\n // https://people.mozilla.org/~jorendorff/es6-draft.html#sec-generatorresume\n return doneResult();\n }\n\n context.method = method;\n context.arg = arg;\n\n while (true) {\n var delegate = context.delegate;\n if (delegate) {\n var delegateResult = maybeInvokeDelegate(delegate, context);\n if (delegateResult) {\n if (delegateResult === ContinueSentinel) continue;\n return delegateResult;\n }\n }\n\n if (context.method === \"next\") {\n // Setting context._sent for legacy support of Babel's\n // function.sent implementation.\n context.sent = context._sent = context.arg;\n\n } else if (context.method === \"throw\") {\n if (state === GenStateSuspendedStart) {\n state = GenStateCompleted;\n throw context.arg;\n }\n\n context.dispatchException(context.arg);\n\n } else if (context.method === \"return\") {\n context.abrupt(\"return\", context.arg);\n }\n\n state = GenStateExecuting;\n\n var record = tryCatch(innerFn, self, context);\n if (record.type === \"normal\") {\n // If an exception is thrown from innerFn, we leave state ===\n // GenStateExecuting and loop back for another invocation.\n state = context.done\n ? GenStateCompleted\n : GenStateSuspendedYield;\n\n if (record.arg === ContinueSentinel) {\n continue;\n }\n\n return {\n value: record.arg,\n done: context.done\n };\n\n } else if (record.type === \"throw\") {\n state = GenStateCompleted;\n // Dispatch the exception by looping back around to the\n // context.dispatchException(context.arg) call above.\n context.method = \"throw\";\n context.arg = record.arg;\n }\n }\n };\n }\n\n // Call delegate.iterator[context.method](context.arg) and handle the\n // result, either by returning a { value, done } result from the\n // delegate iterator, or by modifying context.method and context.arg,\n // setting context.delegate to null, and returning the ContinueSentinel.\n function maybeInvokeDelegate(delegate, context) {\n var method = delegate.iterator[context.method];\n if (method === undefined) {\n // A .throw or .return when the delegate iterator has no .throw\n // method always terminates the yield* loop.\n context.delegate = null;\n\n if (context.method === \"throw\") {\n // Note: [\"return\"] must be used for ES3 parsing compatibility.\n if (delegate.iterator[\"return\"]) {\n // If the delegate iterator has a return method, give it a\n // chance to clean up.\n context.method = \"return\";\n context.arg = undefined;\n maybeInvokeDelegate(delegate, context);\n\n if (context.method === \"throw\") {\n // If maybeInvokeDelegate(context) changed context.method from\n // \"return\" to \"throw\", let that override the TypeError below.\n return ContinueSentinel;\n }\n }\n\n context.method = \"throw\";\n context.arg = new TypeError(\n \"The iterator does not provide a 'throw' method\");\n }\n\n return ContinueSentinel;\n }\n\n var record = tryCatch(method, delegate.iterator, context.arg);\n\n if (record.type === \"throw\") {\n context.method = \"throw\";\n context.arg = record.arg;\n context.delegate = null;\n return ContinueSentinel;\n }\n\n var info = record.arg;\n\n if (! info) {\n context.method = \"throw\";\n context.arg = new TypeError(\"iterator result is not an object\");\n context.delegate = null;\n return ContinueSentinel;\n }\n\n if (info.done) {\n // Assign the result of the finished delegate to the temporary\n // variable specified by delegate.resultName (see delegateYield).\n context[delegate.resultName] = info.value;\n\n // Resume execution at the desired location (see delegateYield).\n context.next = delegate.nextLoc;\n\n // If context.method was \"throw\" but the delegate handled the\n // exception, let the outer generator proceed normally. If\n // context.method was \"next\", forget context.arg since it has been\n // \"consumed\" by the delegate iterator. If context.method was\n // \"return\", allow the original .return call to continue in the\n // outer generator.\n if (context.method !== \"return\") {\n context.method = \"next\";\n context.arg = undefined;\n }\n\n } else {\n // Re-yield the result returned by the delegate method.\n return info;\n }\n\n // The delegate iterator is finished, so forget it and continue with\n // the outer generator.\n context.delegate = null;\n return ContinueSentinel;\n }\n\n // Define Generator.prototype.{next,throw,return} in terms of the\n // unified ._invoke helper method.\n defineIteratorMethods(Gp);\n\n define(Gp, toStringTagSymbol, \"Generator\");\n\n // A Generator should always return itself as the iterator object when the\n // @@iterator function is called on it. Some browsers' implementations of the\n // iterator prototype chain incorrectly implement this, causing the Generator\n // object to not be returned from this call. This ensures that doesn't happen.\n // See https://github.com/facebook/regenerator/issues/274 for more details.\n define(Gp, iteratorSymbol, function() {\n return this;\n });\n\n define(Gp, \"toString\", function() {\n return \"[object Generator]\";\n });\n\n function pushTryEntry(locs) {\n var entry = { tryLoc: locs[0] };\n\n if (1 in locs) {\n entry.catchLoc = locs[1];\n }\n\n if (2 in locs) {\n entry.finallyLoc = locs[2];\n entry.afterLoc = locs[3];\n }\n\n this.tryEntries.push(entry);\n }\n\n function resetTryEntry(entry) {\n var record = entry.completion || {};\n record.type = \"normal\";\n delete record.arg;\n entry.completion = record;\n }\n\n function Context(tryLocsList) {\n // The root entry object (effectively a try statement without a catch\n // or a finally block) gives us a place to store values thrown from\n // locations where there is no enclosing try statement.\n this.tryEntries = [{ tryLoc: \"root\" }];\n tryLocsList.forEach(pushTryEntry, this);\n this.reset(true);\n }\n\n exports.keys = function(object) {\n var keys = [];\n for (var key in object) {\n keys.push(key);\n }\n keys.reverse();\n\n // Rather than returning an object with a next method, we keep\n // things simple and return the next function itself.\n return function next() {\n while (keys.length) {\n var key = keys.pop();\n if (key in object) {\n next.value = key;\n next.done = false;\n return next;\n }\n }\n\n // To avoid creating an additional object, we just hang the .value\n // and .done properties off the next function object itself. This\n // also ensures that the minifier will not anonymize the function.\n next.done = true;\n return next;\n };\n };\n\n function values(iterable) {\n if (iterable) {\n var iteratorMethod = iterable[iteratorSymbol];\n if (iteratorMethod) {\n return iteratorMethod.call(iterable);\n }\n\n if (typeof iterable.next === \"function\") {\n return iterable;\n }\n\n if (!isNaN(iterable.length)) {\n var i = -1, next = function next() {\n while (++i < iterable.length) {\n if (hasOwn.call(iterable, i)) {\n next.value = iterable[i];\n next.done = false;\n return next;\n }\n }\n\n next.value = undefined;\n next.done = true;\n\n return next;\n };\n\n return next.next = next;\n }\n }\n\n // Return an iterator with no values.\n return { next: doneResult };\n }\n exports.values = values;\n\n function doneResult() {\n return { value: undefined, done: true };\n }\n\n Context.prototype = {\n constructor: Context,\n\n reset: function(skipTempReset) {\n this.prev = 0;\n this.next = 0;\n // Resetting context._sent for legacy support of Babel's\n // function.sent implementation.\n this.sent = this._sent = undefined;\n this.done = false;\n this.delegate = null;\n\n this.method = \"next\";\n this.arg = undefined;\n\n this.tryEntries.forEach(resetTryEntry);\n\n if (!skipTempReset) {\n for (var name in this) {\n // Not sure about the optimal order of these conditions:\n if (name.charAt(0) === \"t\" &&\n hasOwn.call(this, name) &&\n !isNaN(+name.slice(1))) {\n this[name] = undefined;\n }\n }\n }\n },\n\n stop: function() {\n this.done = true;\n\n var rootEntry = this.tryEntries[0];\n var rootRecord = rootEntry.completion;\n if (rootRecord.type === \"throw\") {\n throw rootRecord.arg;\n }\n\n return this.rval;\n },\n\n dispatchException: function(exception) {\n if (this.done) {\n throw exception;\n }\n\n var context = this;\n function handle(loc, caught) {\n record.type = \"throw\";\n record.arg = exception;\n context.next = loc;\n\n if (caught) {\n // If the dispatched exception was caught by a catch block,\n // then let that catch block handle the exception normally.\n context.method = \"next\";\n context.arg = undefined;\n }\n\n return !! caught;\n }\n\n for (var i = this.tryEntries.length - 1; i >= 0; --i) {\n var entry = this.tryEntries[i];\n var record = entry.completion;\n\n if (entry.tryLoc === \"root\") {\n // Exception thrown outside of any try block that could handle\n // it, so set the completion value of the entire function to\n // throw the exception.\n return handle(\"end\");\n }\n\n if (entry.tryLoc <= this.prev) {\n var hasCatch = hasOwn.call(entry, \"catchLoc\");\n var hasFinally = hasOwn.call(entry, \"finallyLoc\");\n\n if (hasCatch && hasFinally) {\n if (this.prev < entry.catchLoc) {\n return handle(entry.catchLoc, true);\n } else if (this.prev < entry.finallyLoc) {\n return handle(entry.finallyLoc);\n }\n\n } else if (hasCatch) {\n if (this.prev < entry.catchLoc) {\n return handle(entry.catchLoc, true);\n }\n\n } else if (hasFinally) {\n if (this.prev < entry.finallyLoc) {\n return handle(entry.finallyLoc);\n }\n\n } else {\n throw new Error(\"try statement without catch or finally\");\n }\n }\n }\n },\n\n abrupt: function(type, arg) {\n for (var i = this.tryEntries.length - 1; i >= 0; --i) {\n var entry = this.tryEntries[i];\n if (entry.tryLoc <= this.prev &&\n hasOwn.call(entry, \"finallyLoc\") &&\n this.prev < entry.finallyLoc) {\n var finallyEntry = entry;\n break;\n }\n }\n\n if (finallyEntry &&\n (type === \"break\" ||\n type === \"continue\") &&\n finallyEntry.tryLoc <= arg &&\n arg <= finallyEntry.finallyLoc) {\n // Ignore the finally entry if control is not jumping to a\n // location outside the try/catch block.\n finallyEntry = null;\n }\n\n var record = finallyEntry ? finallyEntry.completion : {};\n record.type = type;\n record.arg = arg;\n\n if (finallyEntry) {\n this.method = \"next\";\n this.next = finallyEntry.finallyLoc;\n return ContinueSentinel;\n }\n\n return this.complete(record);\n },\n\n complete: function(record, afterLoc) {\n if (record.type === \"throw\") {\n throw record.arg;\n }\n\n if (record.type === \"break\" ||\n record.type === \"continue\") {\n this.next = record.arg;\n } else if (record.type === \"return\") {\n this.rval = this.arg = record.arg;\n this.method = \"return\";\n this.next = \"end\";\n } else if (record.type === \"normal\" && afterLoc) {\n this.next = afterLoc;\n }\n\n return ContinueSentinel;\n },\n\n finish: function(finallyLoc) {\n for (var i = this.tryEntries.length - 1; i >= 0; --i) {\n var entry = this.tryEntries[i];\n if (entry.finallyLoc === finallyLoc) {\n this.complete(entry.completion, entry.afterLoc);\n resetTryEntry(entry);\n return ContinueSentinel;\n }\n }\n },\n\n \"catch\": function(tryLoc) {\n for (var i = this.tryEntries.length - 1; i >= 0; --i) {\n var entry = this.tryEntries[i];\n if (entry.tryLoc === tryLoc) {\n var record = entry.completion;\n if (record.type === \"throw\") {\n var thrown = record.arg;\n resetTryEntry(entry);\n }\n return thrown;\n }\n }\n\n // The context.catch method must only be called with a location\n // argument that corresponds to a known catch block.\n throw new Error(\"illegal catch attempt\");\n },\n\n delegateYield: function(iterable, resultName, nextLoc) {\n this.delegate = {\n iterator: values(iterable),\n resultName: resultName,\n nextLoc: nextLoc\n };\n\n if (this.method === \"next\") {\n // Deliberately forget the last sent value so that we don't\n // accidentally pass it on to the delegate.\n this.arg = undefined;\n }\n\n return ContinueSentinel;\n }\n };\n\n // Regardless of whether this script is executing as a CommonJS module\n // or not, return the runtime object so that we can declare the variable\n // regeneratorRuntime in the outer scope, which allows this module to be\n // injected easily by `bin/regenerator --include-runtime script.js`.\n return exports;\n\n}(\n // If this script is executing as a CommonJS module, use module.exports\n // as the regeneratorRuntime namespace. Otherwise create a new empty\n // object. Either way, the resulting object will be used to initialize\n // the regeneratorRuntime variable at the top of this file.\n typeof module === \"object\" ? module.exports : {}\n));\n\ntry {\n regeneratorRuntime = runtime;\n} catch (accidentalStrictMode) {\n // This module should not be running in strict mode, so the above\n // assignment should always work unless something is misconfigured. Just\n // in case runtime.js accidentally runs in strict mode, in modern engines\n // we can explicitly access globalThis. In older engines we can escape\n // strict mode using a global Function call. This could conceivably fail\n // if a Content Security Policy forbids using Function, but in that case\n // the proper solution is to fix the accidental strict mode problem. If\n // you've misconfigured your bundler to force strict mode and applied a\n // CSP to forbid Function, and you're not willing to fix either of those\n // problems, please detail your unique predicament in a GitHub issue.\n if (typeof globalThis === \"object\") {\n globalThis.regeneratorRuntime = runtime;\n } else {\n Function(\"r\", \"regeneratorRuntime = r\")(runtime);\n }\n}\n","import {\n PopulatedWorkflowData,\n MetadataCategory,\n SelectedAnswersData,\n} from 'oro-sdk-apis'\nimport { PersonalInformations } from '../models/client'\n\nconst personalMetaToPrefix = {\n [MetadataCategory.Personal]: 'you',\n [MetadataCategory.ChildPersonal]: 'child',\n [MetadataCategory.OtherPersonal]: 'other',\n}\n\n/**\n * This function extract PersonalInformations from data input object coming from workflow\n * @param data extracted from WorkflowData\n * @returns PersonalInformations of a patient\n */\nexport function identificationToPersonalInformations(\n data: any,\n category:\n | MetadataCategory.Personal\n | MetadataCategory.ChildPersonal\n | MetadataCategory.OtherPersonal\n): PersonalInformations {\n const prefix = personalMetaToPrefix[category]\n\n return {\n birthday: data[`${prefix}Birthday`],\n firstname: data[`${prefix}Firstname`],\n gender: data[`${prefix}Gender`],\n name: data[`${prefix}Name`],\n phone: data[`${prefix}Phone`],\n zip: data[`${prefix}Zip`],\n hid: data[`${prefix}HID`] ?? data[`${prefix}ID`], // This is done for backward compatibility (historically youID was used)\n pharmacy: data[`${prefix}Pharmacy`],\n address: data[`${prefix}Address`],\n }\n}\n\nexport function toActualObject(data: PopulatedWorkflowData) {\n const ret: any = {}\n\n Object.entries(data.fields).forEach(([key, field]) => {\n ret[key] = field.displayedAnswer ? field.displayedAnswer : field.answer\n })\n\n return ret\n}\n\n/**\n * This function update a PopulatedWorkflowData with PersonalInformations\n * @param infos the personal informations\n * @param data the PopulatedWorkflowData\n * @returns an updated PopulatedWorkflowData\n */\nexport function updatePersonalIntoPopulatedWorkflowData(\n infos: PersonalInformations,\n data: PopulatedWorkflowData,\n category:\n | MetadataCategory.Personal\n | MetadataCategory.ChildPersonal\n | MetadataCategory.OtherPersonal\n) {\n const prefix = personalMetaToPrefix[category]\n\n const ret = JSON.parse(JSON.stringify(data)) // deep copy PopulatedWorkflowData\n\n if (infos.birthday && ret.fields[`${prefix}Birthday`])\n ret.fields[`${prefix}Birthday`].answer = infos.birthday\n if (infos.firstname && ret.fields[`${prefix}Firstname`])\n ret.fields[`${prefix}Firstname`].answer = infos.firstname\n if (infos.gender && ret.fields[`${prefix}Gender`])\n ret.fields[`${prefix}Gender`].answer = infos.gender\n if (infos.name && ret.fields[`${prefix}Name`])\n ret.fields[`${prefix}Name`].answer = infos.name\n if (infos.phone && ret.fields[`${prefix}Phone`])\n ret.fields[`${prefix}Phone`].answer = infos.phone\n if (infos.zip && ret.fields[`${prefix}Zip`])\n ret.fields[`${prefix}Zip`].answer = infos.zip\n if (infos.hid) {\n if (ret.fields[`${prefix}HID`]) {\n ret.fields[`${prefix}HID`].answer = infos.hid\n } else if (ret.fields[`${prefix}ID`]) {\n // This is done for backward compatibility (historically youID was used)\n ret.fields[`${prefix}ID`].answer = infos.hid\n } else {\n // If does not exist create it\n ret.fields[`${prefix}HID`] = { kind: 'text', answer: infos.hid }\n }\n }\n\n return ret\n}\n\n/**\n * This function extract an ISO 3166-1 alpha-2 country and subdivision code from data input object coming from workflow\n * @param answers answers from the WorkflowData\n * @returns an ISO 3166 alpha-2 code or undefined\n */\nexport function extractISOLocalityForConsult(\n answers?: SelectedAnswersData\n): string | undefined {\n if (!answers) {\n return undefined\n }\n\n const arrAnswersWithLocality = answers\n .flatMap((currentAnswerPage) => {\n const arrCountryFields = Object.keys(currentAnswerPage)\n .filter(\n (workflowFieldName) =>\n workflowFieldName.indexOf('Country') !== -1\n )\n .flat()\n const arrProvinceFields = Object.keys(currentAnswerPage)\n .filter(\n (workflowFieldName) =>\n workflowFieldName.indexOf('Province') !== -1\n )\n .flat()\n const arrConsultLocalFields = Object.keys(currentAnswerPage)\n .filter(\n (workflowFieldName) =>\n workflowFieldName.indexOf('Locality') !== -1\n )\n .flat()\n //returning the actual selected values, skipping if their IDs are more complex than a string\n return [\n ...arrCountryFields.map(\n (currentFieldName) =>\n (typeof currentAnswerPage[currentFieldName] === 'string'\n ? currentAnswerPage[currentFieldName]\n : undefined) as string\n ),\n ...arrProvinceFields.map(\n (currentFieldName) =>\n (typeof currentAnswerPage[currentFieldName] === 'string'\n ? currentAnswerPage[currentFieldName]\n : undefined) as string\n ),\n ...arrConsultLocalFields.map(\n (currentFieldName) =>\n (typeof currentAnswerPage[currentFieldName] === 'string'\n ? currentAnswerPage[currentFieldName]\n : undefined) as string\n ),\n ]\n })\n .filter((item) => item !== undefined)\n\n const arrSelectedLocality = arrAnswersWithLocality.filter(\n (currentSelectedLocality) =>\n currentSelectedLocality.startsWith('isoLocalityConsult')\n )\n if (!arrSelectedLocality || arrSelectedLocality.length === 0) {\n console.log('no locality found in ' + arrSelectedLocality)\n return undefined\n }\n //to allow enforcing of an order, we will allow the following pattern in the isoLocalityConsult field name\n // isoLocalityConsult-QC-CA and isoLocalityConsult_1-QC-CA\n // or generally: isoLocalityConsult-<isoValue> or isoLocalityConsult_<priority>-<isoValue>\n const allowedLocalityPatterns = /isoLocalityConsult(?:_(?<indexPriority>\\d*))?-(?<isoValue>[a-zA-Z0-9]{2}-[a-zA-Z0-9]{1,3})/\n const finalLocality = arrSelectedLocality.reduce<string | undefined>(\n (finalLocality, currentSelectedLocality) => {\n const extractedSelected = allowedLocalityPatterns.exec(\n currentSelectedLocality\n )\n const [, indexSelectedPriority, isoSelectedValue] =\n extractedSelected ?? []\n if (!finalLocality) {\n return isoSelectedValue\n }\n\n const extractedFinal = allowedLocalityPatterns.exec(finalLocality)\n const [, indexFinalPriority, isoFinalValue] = extractedFinal ?? []\n //we only keep the old value if there's priority used\n // and the new value is of lower priority\n if (\n !indexSelectedPriority ||\n (indexFinalPriority &&\n indexFinalPriority > indexSelectedPriority)\n ) {\n return isoFinalValue\n }\n\n return isoSelectedValue\n },\n undefined\n )\n\n console.log('Picking locality ' + finalLocality)\n return finalLocality\n}\n\nconst sessionPrivateKeyPrefix = 'sess-pkey'\nexport function sessionStorePrivateKeyName(id: string): string {\n return sessionPrivateKeyPrefix + id\n}\n","export class IncompleteAuthentication extends Error {}\nexport class MissingGrant extends Error {}\nexport class MissingLockbox extends Error {}\nexport class MissingLockboxOwner extends Error {}\nexport class AssociatedLockboxNotFound extends Error {}\nexport class WorkflowAnswersMissingError extends Error {}\n","import { getMany } from 'idb-keyval'\nimport { WorkflowAnswersMissingError } from '../models'\nimport {\n MetadataCategory,\n PopulatedWorkflowData,\n PopulatedWorkflowField,\n QuestionData,\n SelectedAnswerData,\n SelectedAnswersData,\n WorkflowData,\n WorkflowPageData,\n WorkflowUploadedImage,\n} from 'oro-sdk-apis'\n\nexport async function filterTriggeredAnsweredWithKind(\n workflowData: WorkflowData,\n kind:\n | 'text'\n | 'text-area'\n | 'text-select-group'\n | 'date'\n | 'number'\n | 'images'\n | 'images-alias'\n | 'body-parts'\n | 'pharmacy-picker'\n | 'online-pharmacy-picker'\n): Promise<SelectedAnswerData[]> {\n if (!workflowData.selectedAnswers) throw WorkflowAnswersMissingError\n // Flattens the list of answered questions\n let flattenedAnswers = flattenSelectedAnswers(workflowData.selectedAnswers)\n // Generates a list of applicable questions\n let triggeredQuestionsWithKind = Object.fromEntries(\n workflowData.pages\n .map((a) => {\n return Object.entries(a.questions).filter(\n ([_, question]) => isTriggered(question.triggers || [], flattenedAnswers) && question.kind === kind\n )\n })\n .flat()\n )\n\n const samePageAnswers = workflowData.selectedAnswers.reduce((prev, cur) => {\n return { ...prev, ...cur }\n }, {})\n\n const res = Object.keys(triggeredQuestionsWithKind).map((questionFieldName) => {\n return samePageAnswers[questionFieldName]\n })\n\n return res\n}\n\n/**\n * Filters and Populates the `selectedAnswers` from the workflow by\n * Cross-referencing the `MetaCategory` of the answer's respective question\n * Populates the fields labels and values that are of radio, dropdown and checkbox types\n *\n * @param workflowData\n * @param category\n * @returns An array of record key, value pairs\n */\nexport async function getWorkflowDataByCategory(\n workflowData: WorkflowData,\n category: MetadataCategory\n): Promise<PopulatedWorkflowData> {\n if (!workflowData.selectedAnswers) throw WorkflowAnswersMissingError\n\n // Flattens the list of answered questions\n let flattenedAnswers = flattenSelectedAnswers(workflowData.selectedAnswers)\n // Generates a list of applicable questions\n let triggeredQuestions = Object.fromEntries(\n workflowData.pages\n .map((a) => {\n return Object.entries(a.questions).filter(([_, question]) =>\n isTriggered(question.triggers || [], flattenedAnswers)\n )\n })\n .flat()\n )\n\n const fields: Record<string, PopulatedWorkflowField> = {}\n\n // Generates the answers of the specified category and adds the appropriate values if any are missing\n return Promise.all(\n workflowData.selectedAnswers\n .map((e) => Object.entries(e))\n .flat()\n .filter(([k, v]) => triggeredQuestions[k] && triggeredQuestions[k]['metaCategory'] === category)\n .map(([k, v]) => {\n return populateWorkflowField(triggeredQuestions[k], v).then((populatedValue) => {\n fields[k] = populatedValue\n })\n })\n )\n .then(() => {\n const ret: PopulatedWorkflowData = {\n workflowCreatedAt: workflowData.createdAt,\n workflowId: workflowData.id,\n locale: workflowData.locale,\n fields,\n }\n return ret\n })\n .catch((err) => {\n console.error(`Error while extracting ${category} data from workflow`, err)\n throw err\n })\n}\n\nexport async function getImagesFromIndexDb(answer: SelectedAnswerData): Promise<WorkflowUploadedImage[]> {\n return await getMany<WorkflowUploadedImage>((answer as any[]).map((v) => v.id ?? v) as string[])\n}\n\n/**\n * (If applicable) Based on the question kind, and the answer type this function will add and replace the appropriate fields to the\n * field values if they are radio, dropdown and checkbox fields\n *\n *\n * @param question\n * @param answerValue\n * @returns\n */\nasync function populateWorkflowField(\n question: QuestionData,\n answerValue: SelectedAnswerData\n): Promise<PopulatedWorkflowField> {\n let answer: any\n let displayedAnswer: string | string[] | undefined = undefined\n switch (question.kind) {\n case 'text-select-group':\n if (question.answers) {\n displayedAnswer = `${answerValue[0]} ${question.answers[answerValue[1] as string].text}`\n }\n answer = answerValue\n break\n case 'radio':\n case 'radio-card':\n case 'select':\n if (question.answers) {\n displayedAnswer = question.answers[answerValue as string].text\n }\n\n answer = answerValue\n break\n case 'multiple':\n case 'checkbox-group':\n displayedAnswer = (answerValue as string[]).map((value) => {\n if (question.answers) {\n return question.answers[value].text\n }\n\n throw new WorkflowAnswersMissingError()\n })\n\n answer = answerValue\n break\n case 'images':\n answer = await getImagesFromIndexDb(answerValue).then((images) =>\n images.map((image) => {\n const { name, imageData } = image\n\n return { name, imageData }\n })\n )\n break\n default:\n answer = answerValue\n }\n\n return Promise.resolve({\n answer,\n displayedAnswer,\n kind: question.kind,\n })\n}\n\nexport function isTriggered(triggers: string[], answers: string[]): boolean {\n for (let trigger of triggers) {\n if (!answers.includes(trigger)) {\n return false\n }\n }\n return true\n}\n\nexport function flattenSelectedAnswers(answers: SelectedAnswersData) {\n const linearAnswers: SelectedAnswerData[] = []\n\n for (const answer of answers) {\n linearAnswers.push(...Object.values(answer))\n }\n\n return linearAnswers.flat(1)\n}\n\n/**\n * This function helps you to get a valid workflow selectedAnswers structure\n * @param workflow the workflow data to use to initialize selectedAnswers\n * @param useDefault use workflow default values or not (this is used to avoid having unset values to appear in summaries)\n * @returns a valid selectedAnswers structure\n */\nexport function getInitialisedSelectedAnswers(workflow: WorkflowData, useDefault: boolean = true) {\n return workflow.pages.map((page) => {\n const ret: any = {}\n for (const [id, question] of Object.entries(page.questions)) {\n if (question.kind === 'body-parts') {\n ret[id] = useDefault ? [] : undefined\n } else {\n ret[id] = useDefault && question.defaultValue ? question.defaultValue : undefined\n }\n }\n return ret\n })\n}\n\nexport function fillWorkflowFromPopulatedWorkflow(workflow: WorkflowData, populatedWorkflow: PopulatedWorkflowData) {\n const filledWorkflow = JSON.parse(JSON.stringify(workflow))\n\n if (!filledWorkflow.selectedAnswers) {\n filledWorkflow.selectedAnswers = getInitialisedSelectedAnswers(filledWorkflow, false)\n }\n\n filledWorkflow.pages.forEach((page: WorkflowPageData, pageIdx: number) => {\n const ret: any = {}\n for (const [id] of Object.entries(page.questions)) {\n if (populatedWorkflow.fields[id]) {\n if (filledWorkflow.selectedAnswers)\n filledWorkflow.selectedAnswers[pageIdx][id] = populatedWorkflow.fields[id].answer as\n | string\n | string[]\n }\n }\n })\n\n return filledWorkflow\n}\n","import {\n Consult,\n ConsultationImageMeta,\n ConsultationMeta,\n ConsultRequest,\n DocumentType,\n IdentityResponse,\n IndexKey,\n MedicalMeta,\n MedicalStatus,\n MetadataCategory,\n PersonalMeta,\n PopulatedWorkflowData,\n Practitioner,\n PreferenceMeta,\n RawConsultationMeta,\n Term,\n Terms,\n Uuid,\n VaultIndex,\n WorkflowData,\n} from 'oro-sdk-apis'\nimport {\n filterTriggeredAnsweredWithKind,\n getImagesFromIndexDb,\n getWorkflowDataByCategory,\n identificationToPersonalInformations,\n OroClient,\n RegisterPatientOutput,\n toActualObject\n} from '..'\n\nconst MAX_RETRIES = 15\n\n/**\n * Completes a registration for a user retrying the complete flow a maximum of 15 times\n *\n * @description The order of importance when registering:\n * Creates a consultation if none exist\n * Retrieves or create's a lockbox if none exist\n * Grants the lockbox (if new) to all practitioners in the practice\n * Stores or fetches the patient data (without images)\n * Indexes the lockbox to the consult for all practitioners (done after inserting since index can be rebuilt from grants)\n * Stores the image data - done last since the majority of failure cases occur here\n * Creates the recovery payloads if they don't exist\n *\n * @param patientUuid\n * @param consultRequest\n * @param workflow\n * @param oroClient\n * @param masterKey\n * @param recoveryQA\n * @returns the successful registration\n */\nexport async function registerPatient(\n patientUuid: Uuid,\n consultRequest: ConsultRequest,\n workflow: WorkflowData,\n oroClient: OroClient,\n masterKey?: Uuid,\n recoveryQA?: {\n recoverySecurityQuestions: string[]\n recoverySecurityAnswers: string[]\n }\n): Promise<RegisterPatientOutput> {\n let consult: Consult | undefined = undefined\n let lockboxUuid: Uuid | undefined = undefined\n let practitionerAdmin: Uuid | undefined = undefined\n let retry = MAX_RETRIES\n let identity: IdentityResponse | undefined = undefined\n let errorsThrown: Error[] = []\n\n for (; retry > 0; retry--) {\n try {\n // Wait a bit each retry (we also want the first one to wait)\n await new Promise((resolve) => setTimeout(resolve, 2000))\n\n // Retrieving practitioners\n if (!practitionerAdmin)\n practitionerAdmin = (await oroClient.practiceClient.practiceGetFromUuid(consultRequest.uuidPractice))\n .uuidAdmin\n\n let practitioners: Practitioner[] = await oroClient.practiceClient\n .practiceGetPractitioners(consultRequest.uuidPractice)\n .catch((err) => {\n console.log(`Error retrieving practitioners`, err)\n return []\n })\n\n // Creating consult\n if (!consult) {\n consult = await getOrCreatePatientConsultationUuid(consultRequest, oroClient)\n }\n\n // Creating lockbox\n if (!lockboxUuid) lockboxUuid = await getOrCreatePatientLockbox(oroClient)\n\n if (!identity)\n identity = await oroClient.guardClient.identityGet(patientUuid)\n\n await oroClient.grantLockbox(practitionerAdmin, lockboxUuid).catch((err) => {\n console.error(`Error while granting lockbox to practitioner admin ${practitionerAdmin}`, err)\n // if we cannot grant to the admin, then the registration will fail\n errorsThrown.push(err)\n })\n\n // Patient Grant to practice\n let grantPromises = practitioners\n .filter((practitioner) => practitioner.uuid !== practitionerAdmin)\n .map(async (practitioner) => {\n return oroClient.grantLockbox(practitioner.uuid, lockboxUuid!).catch((err) => {\n console.error(`Error while granting lockbox to practitioner`, err)\n // Acceptable to continue as admin has already been granted, but we should still retry until the last retry remains\n if (retry <= 1) return\n errorsThrown.push(err)\n })\n })\n\n const consultIndex: VaultIndex = {\n [IndexKey.ConsultationLockbox]: [\n {\n grant: {\n lockboxUuid,\n lockboxOwnerUuid: patientUuid,\n },\n consultationId: consult.uuid,\n },\n ],\n }\n\n // the index will identify in which lockbox a consultation resides\n let consultIndexPromises = practitioners.map(async (practitioner) => {\n return oroClient.vaultIndexAdd(consultIndex, practitioner.uuid).catch((err) => {\n console.error(`[SDK: registration] Error while adding to the practitioner's index ${practitioner.uuid}`, err)\n // Acceptable to continue as the index can be rebuilt, but we should still retry until the last retry remains\n if (retry <= 1) return\n else errorsThrown.push(err)\n })\n })\n\n\n await storeImageAliases(consult.uuid, lockboxUuid, workflow, oroClient).catch((err) => {\n console.error('[SDK: registration] Some errors happened during image upload', err)\n // Acceptable to continue as images can be requested during the consultation, but we should still retry until the last retry remains\n if (retry <= 1) return\n else errorsThrown.push(err)\n })\n\n await storePatientData(consult.uuid, consultRequest.isoLanguageRequired, lockboxUuid, workflow, oroClient).catch((err) => {\n console.error('[SDK: registration] Some errors happened during patient data upload', err)\n errorsThrown.push(err)\n })\n\n if (masterKey && !identity?.recoveryMasterKey) {\n // generate and store recovery payload and updates the identity \n identity = await oroClient.updateMasterKey(patientUuid, masterKey, lockboxUuid).catch((err) => {\n console.error(`[SDK: registration] Error while updating master key`, err)\n /// it's acceptable to continue registration (return old identity)\n if (retry <= 1) return\n errorsThrown.push(err)\n return identity\n })\n } else {\n // we did not set the master key so we do not return it\n masterKey = undefined\n }\n\n if (recoveryQA && !identity?.recoverySecurityQuestions)\n // Patient security question recovery threshold is 2 answers and updates the identity \n identity = await oroClient\n .updateSecurityQuestions(\n patientUuid,\n recoveryQA.recoverySecurityQuestions,\n recoveryQA.recoverySecurityAnswers,\n 2\n )\n .catch((err) => {\n console.error(`[SDK: registration] Error while updating security questions`, err)\n /// it's acceptable to continue registration (return old identity)\n if (retry <= 1) return\n errorsThrown.push(err)\n return identity\n })\n\n await Promise.all([...grantPromises, ...consultIndexPromises])\n\n await buildConsultSearchIndex(consult, workflow, oroClient).catch((err) => {\n console.error('[SDK: registration] personal information not found or another error occured during search indexing', err)\n if(retry <= 1) return // this statement is to avoid failing the registration due to the failure in search indexing the consult, this practically implements a soft retry\n errorsThrown.push(err)\n })\n\n if (errorsThrown.length > 0)\n throw errorsThrown\n\n // Deem the consultation as ready\n await oroClient.consultClient.updateConsultByUUID(consult.uuid, {\n statusMedical: MedicalStatus.New,\n })\n\n // if we got through the complete flow, the registration succeeded\n break\n } catch (err) {\n console.error(`[SDK] Error occured during registration: ${err}, retrying... Retries remaining: ${retry}`)\n errorsThrown = []\n continue\n }\n }\n\n if (retry <= 0) {\n console.error('[SDK] registration failed: MAX_RETRIES reached')\n throw 'RegistrationFailed'\n }\n\n console.log('Successfully Registered')\n await oroClient.cleanIndex()\n return {\n masterKey,\n consultationId: consult!.uuid,\n lockboxUuid: lockboxUuid!,\n }\n}\n\n/**\n * Creates a consultation if one has not been created and fails to be retrieved by the payment intent\n * @param consult\n * @param oroClient\n * @returns the consult Uuid\n */\nasync function getOrCreatePatientConsultationUuid(consult: ConsultRequest, oroClient: OroClient): Promise<Consult> {\n let payment = await oroClient.practiceClient.practiceGetPayment(\n consult.uuidPractice,\n consult.idStripeInvoiceOrPaymentIntent\n )\n if (payment && payment.uuidConsult) {\n return oroClient.consultClient.getConsultByUUID(payment.uuidConsult).catch((err) => {\n console.error('Error while retrieving consult', err)\n throw err\n })\n } else {\n return await oroClient.consultClient.consultCreate(consult).catch((err) => {\n console.error('Error while creating consult', err)\n throw err\n })\n }\n}\n\n/**\n * Creates a new lockbox for the patient if they do not have any, otherwise, use the first (and only one)\n * @param oroClient\n * @returns the lockbox Uuid\n */\nasync function getOrCreatePatientLockbox(oroClient: OroClient): Promise<Uuid> {\n let grants = await oroClient.getGrants(undefined, true)\n if (grants.length > 0) {\n console.log('The grant has already been created, skipping lockbox create step')\n return grants[0].lockboxUuid!\n } else\n return (\n await oroClient.vaultClient.lockboxCreate().catch((err) => {\n console.error('Error while creating lockbox', err)\n throw err\n })\n ).lockboxUuid\n}\n\n/**\n * Store all patient related information into his/her lockbox\n * @param consultationId The consultation id\n * @param isoLanguage the prefered language of communication (ISO 639-3 https://en.wikipedia.org/wiki/List_of_ISO_639-2_codes)\n * @param lockboxUuid the lockbox uuid to store data in\n * @param workflow the workflow used to extract informations\n * @param oroClient an oroClient instance\n * @returns\n */\nasync function storePatientData(\n consultationId: Uuid,\n isoLanguage: string,\n lockboxUuid: Uuid,\n workflow: WorkflowData,\n oroClient: OroClient\n): Promise<(Uuid | void)[]> {\n // Create and store registration data\n return Promise.all([\n // Storing Raw data first\n oroClient.getOrInsertJsonData<RawConsultationMeta>(\n lockboxUuid,\n workflow,\n {\n category: MetadataCategory.Raw,\n contentType: 'application/json',\n consultationId,\n },\n {}\n ),\n getWorkflowDataByCategory(workflow, MetadataCategory.Consultation).then((data) =>\n oroClient.getOrInsertJsonData<ConsultationMeta>(\n lockboxUuid,\n data,\n {\n category: MetadataCategory.Consultation,\n documentType: DocumentType.PopulatedWorkflowData,\n consultationId, // TODO: deprecated. Will finally only be in privateMetadata\n },\n { consultationId }\n )\n ),\n getWorkflowDataByCategory(workflow, MetadataCategory.Medical).then((data) =>\n oroClient.getOrInsertJsonData<MedicalMeta>(\n lockboxUuid,\n data,\n {\n category: MetadataCategory.Medical,\n documentType: DocumentType.PopulatedWorkflowData,\n consultationIds: [consultationId!],\n },\n {}\n )\n ),\n extractAndStorePersonalWorkflowData(\n workflow,\n lockboxUuid,\n consultationId,\n MetadataCategory.Personal,\n oroClient\n ),\n extractAndStorePersonalWorkflowData(\n workflow,\n lockboxUuid,\n consultationId,\n MetadataCategory.ChildPersonal,\n oroClient\n ),\n extractAndStorePersonalWorkflowData(\n workflow,\n lockboxUuid,\n consultationId,\n MetadataCategory.OtherPersonal,\n oroClient\n ),\n oroClient.getOrInsertJsonData<PreferenceMeta>(\n lockboxUuid,\n { isoLanguage },\n {\n category: MetadataCategory.Preference,\n contentType: 'application/json',\n },\n {}\n ),\n ]).then((dataUuids) => dataUuids.flat())\n}\n\nasync function storeImageAliases(\n consultationId: Uuid,\n lockboxUuid: Uuid,\n workflow: WorkflowData,\n oroClient: OroClient\n): Promise<(Uuid | void)[]> {\n const images = await getImagesFromIndexDb((await filterTriggeredAnsweredWithKind(workflow, 'images-alias')).flat())\n\n const nonNullImages = images.filter((img) => !!img)\n\n if (images.length !== nonNullImages.length) {\n console.error('[SDK] Some images have not been found, they have been skipped.')\n }\n\n let promises = nonNullImages.map((image) => {\n return oroClient.getOrInsertJsonData<ConsultationImageMeta>(\n lockboxUuid,\n image,\n {\n category: MetadataCategory.Consultation,\n documentType: DocumentType.ImageAlias,\n consultationId,\n idbId: image.idbId as string,\n },\n {}\n )\n })\n return Promise.all(promises)\n}\n\n/**\n * Extracts the workflow MetadataCategory for Personal, ChildPersonal and OtherPersonal\n * then stores it in the vault\n *\n * @param workflow\n * @param lockboxUuid\n * @param category\n * @returns The data uuid\n */\nexport async function extractAndStorePersonalWorkflowData(\n workflow: WorkflowData,\n lockboxUuid: Uuid,\n consultationId: Uuid,\n category: MetadataCategory.Personal | MetadataCategory.ChildPersonal | MetadataCategory.OtherPersonal,\n oroClient: OroClient\n): Promise<Uuid | void> {\n return getWorkflowDataByCategory(workflow, category as unknown as MetadataCategory).then((data) => {\n if (Object.keys(data.fields).length === 0) return\n return oroClient.getOrInsertJsonData<PersonalMeta>(\n lockboxUuid,\n data,\n {\n category,\n documentType: DocumentType.PopulatedWorkflowData,\n consultationIds: [consultationId],\n },\n {}\n )\n })\n}\n\n/**\n * Given workflow data, it populates it with Personal, ChildPersonal, and OtherPersonal workflow data\n * @param workflow\n */\nexport async function extractPersonalInfoFromWorkflowData(workflow: WorkflowData): Promise<{\n personalInfoPopulatedWfData: PopulatedWorkflowData,\n childPersonalInfoPopulatedWfData: PopulatedWorkflowData,\n otherPersonalInfoPopulatedWfData: PopulatedWorkflowData,\n}> {\n return Promise.all([\n getWorkflowDataByCategory(workflow, MetadataCategory.Personal),\n getWorkflowDataByCategory(workflow, MetadataCategory.ChildPersonal),\n getWorkflowDataByCategory(workflow, MetadataCategory.OtherPersonal)\n ]).then(([personalInfoPopulatedWfData, childPersonalInfoPopulatedWfData, otherPersonalInfoPopulatedWfData]) => {\n return {\n personalInfoPopulatedWfData,\n childPersonalInfoPopulatedWfData,\n otherPersonalInfoPopulatedWfData,\n }\n })\n}\n\n/**\n * Creates the search index for the first name, last name, and the short id of the given consultation\n * @param consult the consultation to be search indexed\n * @param workflow the workflow data\n * @param oroClient\n */\nexport async function buildConsultSearchIndex(consult: Consult, workflow: WorkflowData, oroClient: OroClient) {\n let terms: Terms = [\n <Term> {\n kind: 'consult-shortid',\n value: consult.shortId\n }\n ]\n\n const {\n personalInfoPopulatedWfData,\n childPersonalInfoPopulatedWfData,\n otherPersonalInfoPopulatedWfData\n } = await extractPersonalInfoFromWorkflowData(workflow)\n\n const personalInfo = identificationToPersonalInformations(\n toActualObject(personalInfoPopulatedWfData),\n MetadataCategory.Personal\n )\n const childPersonalInfo = identificationToPersonalInformations(\n toActualObject(childPersonalInfoPopulatedWfData),\n MetadataCategory.ChildPersonal\n )\n const otherPersonalInfo = identificationToPersonalInformations(\n toActualObject(otherPersonalInfoPopulatedWfData),\n MetadataCategory.OtherPersonal\n )\n\n terms.push(<Term>{\n kind: 'first-name',\n value: personalInfo.firstname,\n }, <Term> {\n kind: 'last-name',\n value: personalInfo.name\n })\n\n if(childPersonalInfo.firstname && childPersonalInfo.name) {\n terms.push(<Term>{\n kind: 'first-name',\n value: childPersonalInfo.firstname,\n }, <Term> {\n kind: 'last-name',\n value: childPersonalInfo.name\n })\n }\n\n if(otherPersonalInfo.firstname && otherPersonalInfo.name) {\n terms.push(<Term>{\n kind: 'first-name',\n value: otherPersonalInfo.firstname,\n }, <Term> {\n kind: 'last-name',\n value: otherPersonalInfo.name\n })\n }\n\n await oroClient.searchClient.index(consult.uuid, terms)\n}","import { CryptoRSA, uuidParse} from \"oro-toolbox\"\nimport { EncryptedIndexEntry, Grant, IndexConsultLockbox } from \"oro-sdk-apis\"\n\n/**\n * Decrypts and returns the encrypted grants\n * If something went wrong during decryption, that grant will be removed from the list\n *\n * @param encryptedGrants: an array of encrypted grants\n * @param rsaKey: the rsa key used to decrypt the encrypted grants\n * @returns an array of grants\n */\nexport function decryptGrants(encryptedGrants: Grant[], rsaKey: CryptoRSA): Grant[] {\n return encryptedGrants\n .map(grant => {\n if (grant.encryptedLockbox && !grant.lockboxUuid) {\n try {\n grant.lockboxUuid = uuidParse(\n rsaKey.base64DecryptToBytes(grant.encryptedLockbox)\n )\n } catch (e) {\n console.error('[sdk:index] The grant could not be decrypted or was not a valid UUID: ', e)\n }\n }\n return grant\n })\n .filter(grant => grant.lockboxUuid)\n}\n\n/**\n * Decrypts the encrypted consult lockboxes and returns their grants\n * If something went wrong during decryption, that grant will be removed from the list\n *\n * @param encryptedConsultLockboxes: an array of encrypted entries\n * @param rsaKey: the rsa key used to decrypt the encrypted entries\n * @returns an array of grants\n */\nexport function decryptConsultLockboxGrants(encryptedConsultLockboxes: EncryptedIndexEntry[], rsaKey: CryptoRSA): Grant[] {\n return encryptedConsultLockboxes\n .map(encryptedConsultLockboxes => {\n try {\n return [true, (rsaKey.base64DecryptToJson(\n encryptedConsultLockboxes.encryptedIndexEntry\n ) as IndexConsultLockbox).grant]\n } catch(e) {\n console.error('[sdk:index] The consult lockbox grant could not be decrypted: ', e)\n return [false, undefined] // if decryption fails, we want to ignore the grant but not fail the call\n }\n })\n .filter(grantsTuple => grantsTuple[0])\n .map(grantTuples => grantTuples[1] as Grant)\n}","import { IndexKey, Grant, IndexConsultLockbox, MetadataCategory, VaultIndex } from 'oro-sdk-apis'\nimport { OroClient, Uuid } from '..'\n\n/**\n * @name filterGrantsWithLockboxMetadata\n * @description searches for the applied filters in the vault index\n * @param oroClient\n * @param filter: the metadata filter applied to each the lockboxes\n * @param vaultIndex: the index to which the filter will be applied\n * @param forceRefresh\n * @returns the filtered grants\n */\nexport async function filterGrantsWithLockboxMetadata(\n oroClient: OroClient,\n filter?: { consultationId: Uuid },\n vaultIndex?: VaultIndex,\n forceRefresh = false\n): Promise<Grant[]> {\n if (!vaultIndex || forceRefresh) {\n vaultIndex = await buildLegacyVaultIndex(oroClient)\n }\n if (vaultIndex[IndexKey.Consultation] && filter) {\n let indexConsults = (vaultIndex[IndexKey.Consultation] ?? [])\n .filter((consultGrant: { consultationId: Uuid }) => consultGrant.consultationId === filter.consultationId)\n .map((consultGrant: { consultationId: Uuid; grant: Grant }) => consultGrant.grant as Grant)\n return indexConsults as Grant[]\n } else {\n // No grants exist and the index has already been built\n return []\n }\n}\n\n/** Finds all grants for the logged user\n * requests a list of unique consultation ids for each lockbox the user has access to\n * builds and sets the index of consultations\n * @param oroClient\n * @returns the constructed vaultIndex\n */\nexport async function buildLegacyVaultIndex(oroClient: OroClient): Promise<VaultIndex> {\n let grants = await oroClient.getGrants()\n let consultGrants: IndexConsultLockbox[] = []\n for (let grant of grants) {\n let consults = (\n await oroClient.vaultClient.lockboxMetadataGet(grant.lockboxUuid!, ['consultationId'], [], {\n category: MetadataCategory.Consultation,\n })\n )[0] as Uuid[]\n\n consultGrants = [\n ...consultGrants,\n ...consults.map((consult: any) => ({\n ...consult,\n grant: {\n lockboxOwnerUuid: grant.lockboxOwnerUuid,\n lockboxUuid: grant.lockboxUuid,\n },\n })),\n ]\n }\n\n let vaultIndex = {\n [IndexKey.Consultation]: consultGrants,\n }\n oroClient.setVaultIndex(vaultIndex)\n console.info('[sdk:index] Successfully Built Vault Index')\n return vaultIndex\n}\n","import {\n AuthTokenRequest,\n Consult,\n ConsultRequest,\n ConsultService,\n DataCreateResponse,\n DiagnosisService,\n Document,\n DocumentType,\n EncryptedIndexEntry,\n EncryptedVaultIndex,\n Grant,\n GuardService,\n IdentityCreateRequest,\n IdentityResponse,\n IndexConsultLockbox,\n IndexKey,\n LocalizedData,\n LockboxDataRequest,\n LockboxGrantRequest,\n LockboxManifest,\n ManifestEntry,\n Meta,\n Metadata,\n MetadataCategory,\n PersonalMeta,\n PopulatedWorkflowData,\n Practice,\n PracticeService,\n PreferenceMeta,\n RecoveryMeta,\n SearchService,\n SecretShard,\n TellerService,\n TokenData,\n TosAndCpAcceptanceRequest,\n Uuid,\n VaultIndex,\n VaultService,\n WorkflowData,\n WorkflowService,\n} from 'oro-sdk-apis'\nimport * as OroToolbox from 'oro-toolbox'\nimport { CryptoRSA } from 'oro-toolbox'\nimport { decryptConsultLockboxGrants, decryptGrants, registerPatient, sessionStorePrivateKeyName } from './helpers'\nimport {\n AssociatedLockboxNotFound,\n IncompleteAuthentication,\n LocalEncryptedData,\n MissingGrant,\n MissingLockbox,\n MissingLockboxOwner,\n RecoveryData,\n RegisterPatientOutput,\n UserPreference,\n} from './models'\nimport { buildLegacyVaultIndex, filterGrantsWithLockboxMetadata } from './sdk-revision'\n\nexport class OroClient {\n private rsa?: CryptoRSA\n private secrets: {\n lockboxUuid: string\n cryptor: OroToolbox.CryptoChaCha\n }[] = []\n private cachedMetadataGrants: {\n [filter: string]: Grant[]\n } = {}\n\n private cachedManifest: {\n [filter: string]: ManifestEntry[]\n } = {}\n\n private vaultIndex?: VaultIndex\n\n constructor(\n private toolbox: typeof OroToolbox,\n public tellerClient: TellerService,\n public vaultClient: VaultService,\n public guardClient: GuardService,\n public searchClient: SearchService,\n public practiceClient: PracticeService,\n public consultClient: ConsultService,\n public workflowClient: WorkflowService,\n public diagnosisClient: DiagnosisService,\n private authenticationCallback?: (err: Error) => void\n ) { }\n\n /**\n * clears the vaultIndex and cached metadata grants\n */\n public async cleanIndex() {\n this.vaultIndex = undefined\n this.cachedMetadataGrants = {}\n this.cachedManifest = {}\n }\n\n /**\n * Generates an RSA key pair and password payload (rsa private key encrypted with the password)\n * Calls Guard to sign up with the email address, password, practice, legal and token data\n *\n * @param email\n * @param password\n * @param practice\n * @param legal\n * @param tokenData\n * @returns\n */\n public async signUp(\n email: string,\n password: string,\n practice: Practice,\n tosAndCpAcceptance: TosAndCpAcceptanceRequest,\n tokenData?: TokenData,\n subscription?: boolean,\n skipEmailValidation?: boolean\n ): Promise<IdentityResponse> {\n this.rsa = new CryptoRSA()\n const privateKey = this.rsa.private()\n\n const symmetricEncryptor = this.toolbox.CryptoChaCha.fromPassphrase(password)\n const recoveryPassword = symmetricEncryptor.bytesEncryptToBase64Payload(privateKey)\n\n const hashedPassword = this.toolbox.hashStringToBase64(this.toolbox.hashStringToBase64(password))\n\n const emailConfirmed = !!skipEmailValidation\n\n const signupRequest: IdentityCreateRequest = {\n practiceUuid: practice.uuid,\n email: email.toLowerCase(),\n emailConfirmed,\n password: hashedPassword,\n publicKey: this.toolbox.encodeToBase64(this.rsa.public()),\n recoveryPassword,\n tosAndCpAcceptance,\n tokenData,\n subscription,\n }\n\n const identity = await this.guardClient.identityCreate(signupRequest)\n\n if (identity.recoveryLogin) {\n //Ensure we can recover from a page reload\n let symetricEncryptor = this.toolbox.CryptoChaCha.fromPassphrase(identity.recoveryLogin)\n sessionStorage.setItem(\n sessionStorePrivateKeyName(identity.id),\n symetricEncryptor.bytesEncryptToBase64Payload(privateKey)\n )\n }\n\n return identity\n }\n\n /**\n * Parse the given accessToken claims by calling guard whoami and update theidentity to set it's emailConfirmed flag\n * @param accessToken\n * @returns The identity related to confirmedEmail\n */\n public async confirmEmail(accessToken: string): Promise<IdentityResponse> {\n this.guardClient.setTokens({ accessToken })\n const claims = await this.guardClient.whoAmI()\n return this.guardClient.identityUpdate(claims.sub, {\n emailConfirmed: true,\n })\n }\n\n /**\n * Calls Guard to sign in with the email address, password and one time password (if MFA is enabled)\n * Then recover's the rsa private key from the recovery payload\n *\n * @param practiceUuid\n * @param email\n * @param password\n * @param otp\n * @returns the user identity\n */\n public async signIn(practiceUuid: Uuid, email: string, password: string, otp?: string): Promise<IdentityResponse> {\n const hashedPassword = this.toolbox.hashStringToBase64(this.toolbox.hashStringToBase64(password))\n const tokenRequest: AuthTokenRequest = {\n practiceUuid,\n email: email.toLowerCase(),\n password: hashedPassword,\n otp,\n }\n\n await this.guardClient.authToken(tokenRequest)\n const userUuid = (await this.guardClient.whoAmI()).sub\n\n // Updates the rsa key to the one generated on the backend\n await this.recoverPrivateKeyFromPassword(userUuid, password)\n return await this.guardClient.identityGet(userUuid)\n }\n\n /**\n * Will attempt to recover an existing login session and set back\n * the private key in scope\n */\n public async resumeSession() {\n const id = (await this.guardClient.whoAmI()).sub\n const recoveryPayload = sessionStorage.getItem(sessionStorePrivateKeyName(id))\n const recoveryKey = (await this.guardClient.identityGet(id)).recoveryLogin\n\n if (!recoveryKey || !recoveryPayload) throw IncompleteAuthentication\n\n const symmetricDecryptor = this.toolbox.CryptoChaCha.fromPassphrase(recoveryKey)\n let privateKey = symmetricDecryptor.base64PayloadDecryptToBytes(recoveryPayload)\n this.rsa = this.toolbox.CryptoRSA.fromKey(privateKey)\n }\n\n /**\n * This function let's you encrypt locally an Object\n * @param value the Object to encrypt\n * @returns a LocalEncryptedData Object\n * @throws IncompleteAuthentication if rsa is not set\n * @calls authenticationCallback if rsa is not set\n */\n public localEncryptToJsonPayload(value: any): LocalEncryptedData {\n if (!this.rsa) {\n if (this.authenticationCallback) {\n this.authenticationCallback(new IncompleteAuthentication())\n }\n\n throw new IncompleteAuthentication()\n }\n\n const chaChaKey = new this.toolbox.CryptoChaCha()\n\n const encryptedData = chaChaKey.jsonEncryptToBase64Payload(value)\n const encryptedKey = this.toolbox.encodeToBase64(this.rsa.encryptToBytes(chaChaKey.key()))\n\n return { encryptedData, encryptedKey }\n }\n\n /**\n * This function let's you decrypt a LocalEncryptedData object\n * @param value a LocalEncryptedData object\n * @returns a decrypted Object\n * @throws IncompleteAuthentication if rsa is not set\n * @calls authenticationCallback if rsa is not set\n */\n public localDecryptJsonPayload({ encryptedKey, encryptedData }: LocalEncryptedData): any {\n if (!this.rsa) {\n if (this.authenticationCallback) {\n this.authenticationCallback(new IncompleteAuthentication())\n }\n\n throw new IncompleteAuthentication()\n }\n\n const chaChaKey = this.rsa.base64DecryptToBytes(encryptedKey)\n const decryptedData = this.toolbox.CryptoChaCha.fromKey(chaChaKey).base64PayloadDecryptToJson(encryptedData)\n\n return decryptedData\n }\n\n /**\n * Effectively kills your \"session\"\n */\n public async signOut() {\n this.rsa = undefined\n this.secrets = []\n this.guardClient.setTokens({\n accessToken: undefined,\n refreshToken: undefined,\n })\n await this.guardClient.authLogout()\n }\n\n /**\n * @name registerPatient\n * @description The complete flow to register a patient\n *\n * Steps:\n * 1. Create a consult (checks if payment has been done)\n * 2. Creates a lockbox\n * 3. Grants lockbox access to all practice personnel\n * 4. Creates secure identification, medical, onboarding data\n * 5. Generates and stores the rsa key pair and recovery payloads\n *\n * @param patientUuid\n * @param consult\n * @param workflow\n * @param recoveryQA\n * @returns\n */\n public async registerPatient(\n patientUuid: Uuid,\n consult: ConsultRequest,\n workflow: WorkflowData,\n recoveryQA?: {\n recoverySecurityQuestions: string[]\n recoverySecurityAnswers: string[]\n }\n ): Promise<RegisterPatientOutput> {\n if (!this.rsa) throw IncompleteAuthentication\n return registerPatient(patientUuid, consult, workflow, this, this.toolbox.uuid(), recoveryQA)\n }\n\n /**\n * Builds the vault index for the logged user\n *\n * Steps:\n * 1. Retrieves, decrypts and sets the lockbox IndexSnapshot\n * 2. Retrieves, decrypts and adds all other index entries starting at the snapshot timestamp\n * 3. Updates the IndexSnapshot if changed\n * @deprecated\n * @returns the latest vault index\n */\n public async buildVaultIndex(forceRefresh: boolean = false) {\n if (!this.vaultIndex || forceRefresh) await buildLegacyVaultIndex(this)\n }\n\n /**\n * Setter for the vault index\n * @param index\n */\n public setVaultIndex(index: VaultIndex) {\n this.vaultIndex = index\n }\n\n /**\n * Fetches all grants, and consultations that exist in each lockbox\n * Then updates the index for the current user with the lockbox consult relationship\n */\n public async forceUpdateIndexEntries() {\n let grants = await this.getGrants()\n\n let indexConsultLockbox: IndexConsultLockbox[] = await Promise.all(\n grants.map(\n async (grant: Grant) =>\n await this.vaultClient\n .lockboxMetadataGet(\n grant.lockboxUuid!,\n ['consultationId'],\n [],\n { category: MetadataCategory.Consultation },\n grant.lockboxOwnerUuid\n )\n .then((consults) => {\n try {\n return consults[0].map((consult: any) => {\n return {\n ...consult,\n grant: {\n lockboxOwnerUuid: grant.lockboxOwnerUuid,\n lockboxUuid: grant.lockboxUuid,\n },\n }\n })\n } catch (e) {\n // No consultations in lockbox or index could not be created\n return []\n }\n })\n .catch(() => [])\n )\n ).then((consults) => consults.flat())\n this.vaultIndexAdd({\n [IndexKey.Consultation]: indexConsultLockbox,\n })\n .then(() => alert('The Index was successfully updated!'))\n .catch(() => console.error('The index failed to update!'))\n }\n\n /**\n * Generates, encrypts and adds entries to vault index for a given index owner\n *\n * @param entries\n * @param indexOwnerUuid\n */\n public async vaultIndexAdd(entries: VaultIndex, indexOwnerUuid?: Uuid) {\n if (!this.rsa) throw IncompleteAuthentication\n\n let rsaPub: Uint8Array\n if (indexOwnerUuid) {\n let base64IndexOwnerPubKey = (await this.guardClient.identityGet(indexOwnerUuid)).publicKey\n rsaPub = this.toolbox.decodeFromBase64(base64IndexOwnerPubKey)\n } else {\n rsaPub = this.rsa.public()\n }\n\n let encryptedIndex: EncryptedVaultIndex = {}\n\n for (let keyString of Object.keys(entries)) {\n let key = keyString as keyof VaultIndex\n switch (key) {\n case IndexKey.ConsultationLockbox:\n encryptedIndex[key] = (entries[key] as IndexConsultLockbox[])\n .map((e) => ({\n ...e,\n uniqueHash: e.consultationId,\n }))\n .map(\n (e: IndexConsultLockbox) =>\n ({\n uuid: e.uuid,\n timestamp: e.timestamp,\n uniqueHash: e.uniqueHash,\n encryptedIndexEntry: CryptoRSA.jsonWithPubEncryptToBase64(\n {\n consultationId: e.consultationId,\n grant: e.grant,\n },\n rsaPub\n ),\n } as EncryptedIndexEntry)\n )\n break\n //// DEPRECATED : REMOVE ME : BEGIN ///////////////////////////////////////////\n case IndexKey.Consultation:\n encryptedIndex[key] = (entries[key] as IndexConsultLockbox[])\n .map((e) => ({\n ...e,\n uniqueHash: this.toolbox.hashStringToBase64(\n JSON.stringify({\n consultationId: e.consultationId,\n grant: e.grant,\n })\n ),\n }))\n .filter(\n (e) =>\n !this.vaultIndex ||\n !this.vaultIndex[IndexKey.Consultation]?.find((v) => v.uniqueHash === e.uniqueHash)\n )\n .map(\n (e: IndexConsultLockbox) =>\n ({\n uuid: e.uuid,\n timestamp: e.timestamp,\n uniqueHash: e.uniqueHash,\n encryptedIndexEntry: CryptoRSA.jsonWithPubEncryptToBase64(\n {\n consultationId: e.consultationId,\n grant: e.grant,\n },\n rsaPub\n ),\n } as EncryptedIndexEntry)\n )\n break\n //// DEPRECATED : REMOVE ME : END ///////////////////////////////////////////\n }\n }\n await this.vaultClient.vaultIndexPut(encryptedIndex, indexOwnerUuid)\n }\n\n /**\n * adds or updates the index snapshot for the logged user\n * @param index\n */\n public async indexSnapshotAdd(index: VaultIndex) {\n if (!this.rsa) throw IncompleteAuthentication\n let rsaPub: Uint8Array = this.rsa.public()\n\n let cleanedIndex: VaultIndex = {\n [IndexKey.Consultation]: index[IndexKey.Consultation]\n ?.filter((c) => c)\n .map((c) => {\n return {\n grant: c.grant,\n consultationId: c.consultationId,\n }\n }),\n }\n\n // the data of the snapshot should not contain the `IndexEntry` data\n // (will create conflicts while updating)\n let encryptedIndexEntry = CryptoRSA.jsonWithPubEncryptToBase64(cleanedIndex, rsaPub)\n\n // The encryptedIndexEntry can have the uuid and timstamp (for updating)\n let encryptedIndex: EncryptedIndexEntry = {\n uuid: index.uuid,\n timestamp: index.timestamp,\n encryptedIndexEntry,\n }\n this.vaultClient.vaultIndexSnapshotPut(encryptedIndex)\n }\n\n /**\n * @name grantLockbox\n * @description Grants a lockbox by retrieving the shared secret of the lockbox and encrypting it with the grantees public key\n * @param granteeUuid\n * @param lockboxUuid\n * @param lockboxOwnerUuid the lockbox owner (ignored if lockbox is owned by self)\n */\n public async grantLockbox(granteeUuid: Uuid, lockboxUuid: Uuid, lockboxOwnerUuid?: Uuid) {\n if (!this.rsa) throw IncompleteAuthentication\n\n let secret = (await this.getCachedSecretCryptor(lockboxUuid, lockboxOwnerUuid)).key()\n let base64GranteePublicKey = (await this.guardClient.identityGet(granteeUuid)).publicKey\n let granteePublicKey = this.toolbox.decodeFromBase64(base64GranteePublicKey)\n\n let granteeEncryptedSecret = CryptoRSA.bytesWithPubEncryptToBase64(secret, granteePublicKey)\n let request: LockboxGrantRequest = {\n encryptedSecret: granteeEncryptedSecret,\n granteeUuid: granteeUuid,\n }\n await this.vaultClient.lockboxGrant(lockboxUuid, request, lockboxOwnerUuid)\n }\n\n /**\n * @name createMessageData\n * @description Creates a Base64 encrypted Payload to send and store in the vault from a message string\n * @param lockboxUuid\n * @param message\n * @param consultationId the consultation for which this message is sent\n * @param lockboxOwnerUuid the lockbox owner (ignored if lockbox is owned by self)\n * @param previousDataUuid if it's a revision of existing file, specify the previous data uuid\n * @returns the data uuid\n */\n public async createMessageData(\n lockboxUuid: Uuid,\n message: string,\n consultationId: string,\n lockboxOwnerUuid?: Uuid,\n previousDataUuid?: Uuid\n ): Promise<DataCreateResponse> {\n if (!this.rsa) throw IncompleteAuthentication\n\n let symmetricEncryptor = await this.getCachedSecretCryptor(lockboxUuid, lockboxOwnerUuid)\n\n let encryptedData = symmetricEncryptor.jsonEncryptToBase64Payload(message)\n let encryptedPrivateMeta = symmetricEncryptor.jsonEncryptToBase64Payload({\n author: (await this.guardClient.whoAmI()).sub,\n })\n\n let meta = {\n consultationId,\n category: MetadataCategory.Consultation,\n documentType: DocumentType.Message,\n contentType: 'text/plain',\n }\n\n let request: LockboxDataRequest = {\n data: encryptedData,\n publicMetadata: meta,\n privateMetadata: encryptedPrivateMeta,\n }\n\n return this.tellerClient.lockboxDataStore(lockboxUuid, request, lockboxOwnerUuid, previousDataUuid)\n }\n\n /**\n * @name createMessageAttachmentData\n * @description Creates a Base64 encrypted Payload to send and store in the vault from a file\n * @param lockboxUuid\n * @param data the file stored\n * @param consultationId the consultation for which this message is sent\n * @param lockboxOwnerUuid the lockbox owner (ignored if lockbox is owned by self)\n * @param previousDataUuid if it's a revision of existing file, specify the previous data uuid\n * @returns the data uuid\n */\n public async createMessageAttachmentData(\n lockboxUuid: Uuid,\n data: File,\n consultationId: string,\n lockboxOwnerUuid?: Uuid,\n previousDataUuid?: Uuid\n ): Promise<DataCreateResponse> {\n if (!this.rsa) throw IncompleteAuthentication\n\n let symmetricEncryptor = await this.getCachedSecretCryptor(lockboxUuid, lockboxOwnerUuid)\n let encryptedData = symmetricEncryptor.bytesEncryptToBase64Payload(new Uint8Array(await data.arrayBuffer()))\n let encryptedPrivateMeta = symmetricEncryptor.jsonEncryptToBase64Payload({\n author: (await this.guardClient.whoAmI()).sub,\n fileName: data.name,\n lastModified: data.lastModified,\n size: data.size,\n })\n\n let meta = {\n consultationId,\n category: MetadataCategory.Consultation,\n documentType: DocumentType.Message,\n contentType: data.type,\n }\n\n let request: LockboxDataRequest = {\n data: encryptedData,\n publicMetadata: meta,\n privateMetadata: encryptedPrivateMeta,\n }\n\n return this.tellerClient.lockboxDataStore(lockboxUuid, request, lockboxOwnerUuid, previousDataUuid)\n }\n\n /**\n * @name createAttachmentData\n * @description Creates a Base64 encrypted Payload to send and store in the vault from a file\n * @param lockboxUuid\n * @param data the file stored\n * @param consultationId the consultation for which this message is sent\n * @param category the category for the attachment data\n * @param lockboxOwnerUuid the lockbox owner (ignored if lockbox is owned by self)\n * @param previousDataUuid if it's a revision of existing file, specify the previous data uuid\n * @returns the data uuid\n */\n public async createConsultationAttachmentData(\n lockboxUuid: Uuid,\n data: File,\n consultationId: string,\n documentType: DocumentType,\n lockboxOwnerUuid?: Uuid,\n previousDataUuid?: Uuid\n ): Promise<DataCreateResponse> {\n if (!this.rsa) throw IncompleteAuthentication\n\n return this.createBytesData<Meta | any>(\n lockboxUuid,\n new Uint8Array(await data.arrayBuffer()),\n {\n consultationId,\n category: MetadataCategory.Consultation,\n documentType,\n contentType: data.type,\n },\n {\n author: (await this.guardClient.whoAmI()).sub,\n fileName: data.name,\n },\n lockboxOwnerUuid,\n previousDataUuid\n )\n }\n\n /**\n * @name createJsonData\n * @description Creates a Base64 encrypted Payload to send and store in the vault. With the data input as a JSON\n * @param lockboxUuid\n * @param data\n * @param meta\n * @param privateMeta the metadata that will be secured in the vault\n * @param lockboxOwnerUuid the lockbox owner (ignored if lockbox is owned by self)\n * @param previousDataUuid if it's a revision of existing data, specify the previous data uuid\n * @returns the data uuid\n */\n public async createJsonData<T = Meta>(\n lockboxUuid: Uuid,\n data: any,\n meta?: T,\n privateMeta?: { [val: string]: any },\n lockboxOwnerUuid?: Uuid,\n previousDataUuid?: Uuid\n ): Promise<DataCreateResponse> {\n if (!this.rsa) throw IncompleteAuthentication\n\n let symmetricEncryptor = await this.getCachedSecretCryptor(lockboxUuid, lockboxOwnerUuid)\n let encryptedData = symmetricEncryptor.jsonEncryptToBase64Payload(data)\n let encryptedPrivateMeta = symmetricEncryptor.jsonEncryptToBase64Payload(privateMeta)\n\n let request: LockboxDataRequest = {\n data: encryptedData,\n publicMetadata: meta,\n privateMetadata: encryptedPrivateMeta,\n }\n\n return this.tellerClient.lockboxDataStore(lockboxUuid, request, lockboxOwnerUuid, previousDataUuid)\n }\n\n /**\n * Get or upsert a data in lockbox\n * @param lockboxUuid the lockbox uuid\n * @param data the data to insert\n * @param publicMetadata the public Metadata\n * @param privateMetadata the private Metadata\n * @param forceReplace set true when the insertion of data requires to replace the data when it exists already\n * @returns the data uuid\n */\n public async getOrInsertJsonData<M = Metadata>(\n lockboxUuid: Uuid,\n data: any,\n publicMetadata: M,\n privateMetadata: Metadata,\n forceReplace: boolean = false\n ): Promise<Uuid> {\n let manifest = await this.vaultClient.lockboxManifestGet(lockboxUuid, publicMetadata)\n if (!forceReplace && manifest.length > 0) {\n console.log(`The data for ${JSON.stringify(publicMetadata)} already exist`)\n return manifest[0].dataUuid\n } else\n return (\n await this.createJsonData<M>(\n lockboxUuid,\n data,\n publicMetadata,\n privateMetadata,\n undefined,\n forceReplace && manifest.length > 0 ? manifest[0].dataUuid : undefined // if forceReplace and data already exist, then replace data. Otherwise insert it\n ).catch((err) => {\n console.error(`Error while upserting data ${JSON.stringify(publicMetadata)} data`, err)\n throw err\n })\n ).dataUuid\n }\n\n /**\n * @name createBytesData\n * @description Creates a Base64 encrypted Payload to send and store in the vault. With the data input as a Bytes\n * @param lockboxUuid\n * @param data\n * @param meta\n * @param privateMeta the metadata that will be secured in the vault\n * @param lockboxOwnerUuid the lockbox owner (ignored if lockbox is owned by self)\n * @param previousDataUuid if it's a revision of existing data, specify the previous data uuid\n * @returns the data uuid\n */\n public async createBytesData<T = Meta>(\n lockboxUuid: Uuid,\n data: Uint8Array,\n meta: T,\n privateMeta: { [val: string]: any },\n lockboxOwnerUuid?: Uuid,\n previousDataUuid?: Uuid\n ): Promise<DataCreateResponse> {\n if (!this.rsa) throw IncompleteAuthentication\n let symmetricEncryptor = await this.getCachedSecretCryptor(lockboxUuid, lockboxOwnerUuid)\n let encryptedData = symmetricEncryptor.bytesEncryptToBase64Payload(data)\n let encryptedPrivateMeta = symmetricEncryptor.jsonEncryptToBase64Payload(privateMeta)\n\n let request: LockboxDataRequest = {\n data: encryptedData,\n publicMetadata: meta,\n privateMetadata: encryptedPrivateMeta,\n }\n\n return this.tellerClient.lockboxDataStore(lockboxUuid, request, lockboxOwnerUuid, previousDataUuid)\n }\n\n /**\n * @name getJsonData\n * @description Fetches and decrypts the lockbox data with the cached shared secret.\n * Decrypts the data to a valid JSON object. If this is impossible, the call to the WASM binary will fail\n *\n * @type T is the generic type specifying the return type object of the function\n * @param lockboxUuid\n * @param dataUuid\n * @param lockboxOwnerUuid the lockbox owner (ignored if lockbox is owned by self)\n * @returns the data specified by the generic type <T>\n */\n public async getJsonData<T = any>(lockboxUuid: Uuid, dataUuid: Uuid, lockboxOwnerUuid?: Uuid): Promise<T> {\n if (!this.rsa) throw IncompleteAuthentication\n\n let [encryptedPayload, symmetricDecryptor] = await Promise.all([\n this.vaultClient.lockboxDataGet(lockboxUuid, dataUuid, lockboxOwnerUuid),\n this.getCachedSecretCryptor(lockboxUuid, lockboxOwnerUuid),\n ])\n\n return symmetricDecryptor.base64PayloadDecryptToJson(encryptedPayload.data)\n }\n /**\n * @description Fetches and decrypts the lockbox data with the cached shared secret.\n * @param lockboxUuid\n * @param dataUuid\n * @param lockboxOwnerUuid the lockbox owner (ignored if lockbox is owned by self)\n * @returns the bytes data\n */\n public async getBytesData(lockboxUuid: Uuid, dataUuid: Uuid, lockboxOwnerUuid?: Uuid): Promise<Uint8Array> {\n if (!this.rsa) throw IncompleteAuthentication\n\n let [encryptedPayload, symmetricDecryptor] = await Promise.all([\n this.vaultClient.lockboxDataGet(lockboxUuid, dataUuid, lockboxOwnerUuid),\n this.getCachedSecretCryptor(lockboxUuid, lockboxOwnerUuid),\n ])\n\n return symmetricDecryptor.base64PayloadDecryptToBytes(encryptedPayload.data)\n }\n\n /**\n * @name getGrants\n * @description Get all lockboxes granted to user with the applied filter\n * @note this function returns cached grants and will not update unless the page is refreshed\n * @todo some versions of lockboxes do not make use of lockbox metadata\n * in this case, all lockboxes need to be filtered one-by-one to find the correct one\n * Remove if this is no longer the case\n * @param filter: the consultationId in which the grant exists\n * @returns decrypted lockboxes granted to user\n */\n public async getGrants(filter?: { consultationId: Uuid }, forceRefresh: boolean = false): Promise<Grant[]> {\n if (!this.rsa) throw IncompleteAuthentication\n\n let filterString = JSON.stringify(filter)\n // retrieves cached grants\n // Note: if filters is set to empty, it will be stored in the `undefined` key\n if (!forceRefresh && this.cachedMetadataGrants[filterString]) return this.cachedMetadataGrants[filterString]\n\n // if there is a filter to apply, then the grant can be retrieved from the vault index, otherwise, all grants are fetched\n // Note: will work only if the filter being applied is exclusively a consult id\n const grantsByConsultLockbox = filter ? (\n await this.vaultClient.vaultIndexGet([IndexKey.ConsultationLockbox], [filter.consultationId])\n .then((res) => res[IndexKey.ConsultationLockbox])\n .catch((e) => {\n console.error(e)\n return []\n })\n ) : undefined\n const decryptedConsults = decryptConsultLockboxGrants(grantsByConsultLockbox ?? [], this.rsa)\n if (decryptedConsults.length > 0) {\n console.info('[sdk:index] Grants found in user`s constant time secure index')\n this.cachedMetadataGrants[JSON.stringify(filter)] = decryptedConsults\n return this.cachedMetadataGrants[filterString]\n }\n\n let encryptedGrants\n // if there are no grants with the applied filter from index, attempt for naive filter with backwards compatibility\n if (filter) {\n encryptedGrants = await filterGrantsWithLockboxMetadata(this, filter, this.vaultIndex, forceRefresh)\n } else {\n encryptedGrants = (await this.vaultClient.grantsGet()).grants\n }\n\n const decryptedGrants = await decryptGrants(encryptedGrants, this.rsa)\n // sets the cached grant\n this.cachedMetadataGrants[filterString] = decryptedGrants\n return decryptedGrants\n }\n\n /**\n * @name getCachedSecretCryptor\n * @description Retrieves the cached lockbox secret or fetches the secret from vault, then creates the symmetric cryptor and stores it in memory\n * @param lockboxUuid\n * @param lockboxOwnerUuid the lockbox owner (ignored if lockbox is owned by self)\n * @returns\n */\n async getCachedSecretCryptor(lockboxUuid: string, lockboxOwnerUuid?: string): Promise<OroToolbox.CryptoChaCha> {\n if (!this.rsa) throw IncompleteAuthentication\n\n let index = this.secrets.findIndex((secret) => secret.lockboxUuid === lockboxUuid)\n if (index === -1) {\n let encryptedSecret = (await this.vaultClient.lockboxSecretGet(lockboxUuid, lockboxOwnerUuid)).sharedSecret\n\n let secret = this.rsa.base64DecryptToBytes(encryptedSecret)\n let cryptor = this.toolbox.CryptoChaCha.fromKey(secret)\n this.secrets.push({ lockboxUuid, cryptor })\n return cryptor\n } else {\n return this.secrets[index].cryptor\n }\n }\n\n /**\n * Retrieves the patient personal information associated to the `consultationId`\n * The `consultationId` only helps to retrieve the patient lockboxes\n * Note: it is possible to have several personal informations data\n * @param consultationId The consultation Id\n * @param category The personal MetadataCategory to fetch\n * @param forceRefresh force data refresh (default to false)\n * @returns the personal data\n */\n public async getPersonalInformationsFromConsultId(\n consultationId: Uuid,\n category: MetadataCategory.Personal | MetadataCategory.ChildPersonal | MetadataCategory.OtherPersonal,\n forceRefresh = false\n ): Promise<LocalizedData<PopulatedWorkflowData>[]> {\n return this.getMetaCategoryFromConsultId(consultationId, category, forceRefresh)\n }\n\n /**\n * Retrieves the patient medical data associated to the `consultationId`\n * The `consultationId` only helps to retrieve the patient lockboxes\n * Note: it is possible to have several medical data\n * @param consultationId The consultation Id\n * @param forceRefresh force data refresh (default to false)\n * @returns the medical data\n */\n public async getMedicalDataFromConsultId(\n consultationId: Uuid,\n forceRefresh = false\n ): Promise<LocalizedData<PopulatedWorkflowData>[]> {\n return this.getMetaCategoryFromConsultId(consultationId, MetadataCategory.Medical, forceRefresh)\n }\n\n private async getMetaCategoryFromConsultId(\n consultationId: Uuid,\n category: MetadataCategory,\n forceRefresh = false\n ): Promise<LocalizedData<PopulatedWorkflowData>[]> {\n let grants = await this.getGrants({ consultationId })\n let workflowData: LocalizedData<PopulatedWorkflowData>[] = []\n for (let grant of grants) {\n let manifest = await this.getLockboxManifest(\n grant.lockboxUuid!,\n {\n category,\n documentType: DocumentType.PopulatedWorkflowData,\n consultationIds: [consultationId],\n },\n true,\n grant.lockboxOwnerUuid,\n forceRefresh\n )\n\n // TODO: find another solution for backwards compatibility (those without the metadata consultationIds)\n if (manifest.length === 0) {\n manifest = (\n await this.getLockboxManifest(\n grant.lockboxUuid!,\n {\n category,\n documentType: DocumentType.PopulatedWorkflowData,\n // backward compatiblility with TonTest\n },\n true,\n grant.lockboxOwnerUuid,\n forceRefresh\n )\n ).filter((entry) => !entry.metadata.consultationIds) // Keep only entries without associated consultationIds\n }\n let data = await Promise.all(\n manifest.map(async (entry) => {\n return {\n lockboxOwnerUuid: grant.lockboxOwnerUuid,\n lockboxUuid: grant.lockboxUuid!,\n dataUuid: entry.dataUuid,\n data: await this.getJsonData<PopulatedWorkflowData>(grant.lockboxUuid!, entry.dataUuid),\n }\n })\n )\n workflowData = { ...workflowData, ...data }\n }\n return workflowData\n }\n\n /**\n * @description retrieves the personal information stored in the first owned lockbox\n * @param userId The user Id\n * @returns the personal data\n */\n public async getPersonalInformations(userId: Uuid): Promise<LocalizedData<PopulatedWorkflowData>> {\n const grant = (await this.getGrants()).find((lockbox) => lockbox.lockboxOwnerUuid === userId)\n\n if (!grant) {\n throw MissingGrant\n }\n\n const { lockboxUuid, lockboxOwnerUuid } = grant\n\n if (!lockboxUuid) throw MissingLockbox\n\n if (!lockboxOwnerUuid) throw MissingLockboxOwner\n\n const identificationDataUuid = (\n await this.getLockboxManifest(\n lockboxUuid,\n {\n category: MetadataCategory.Personal,\n documentType: DocumentType.PopulatedWorkflowData,\n },\n false,\n userId\n )\n )[0].dataUuid\n\n return {\n lockboxOwnerUuid,\n lockboxUuid,\n dataUuid: identificationDataUuid,\n data: await this.getJsonData<PopulatedWorkflowData>(lockboxUuid, identificationDataUuid),\n }\n }\n\n /**\n * Retrieves the grant associated to a consultationId\n * @note returns the first grant only\n * @param consultationId The consultationId\n * @returns the grant\n */\n public async getGrantFromConsultId(consultationId: Uuid): Promise<Grant | undefined> {\n let grants = await this.getGrants({ consultationId })\n\n if (grants.length === 0) {\n throw AssociatedLockboxNotFound\n }\n\n return grants[0]\n }\n\n /**\n * retrieves the identity associated to the `consultationId`\n * @param consultationId The consultation Id\n * @returns the identity\n */\n public async getIdentityFromConsultId(consultationId: Uuid): Promise<IdentityResponse | undefined> {\n const grant = await this.getGrantFromConsultId(consultationId)\n\n if (grant && grant.lockboxOwnerUuid) {\n return await this.guardClient.identityGet(grant.lockboxOwnerUuid)\n } else {\n return undefined\n }\n }\n\n /**\n * retrieves the lockbox manifest for a given lockbox and add's its private metadata\n * @note the lockbox manifest will retrieved the cached manifest first unless force refresh is enabled\n * @param lockboxUuid\n * @param filter\n * @param expandPrivateMetadata\n * @param lockboxOwnerUuid\n * @param forceRefresh\n * @returns the lockbox manifest\n */\n public async getLockboxManifest(\n lockboxUuid: Uuid,\n filter: Metadata,\n expandPrivateMetadata: boolean,\n lockboxOwnerUuid?: Uuid,\n forceRefresh: boolean = false\n ): Promise<LockboxManifest> {\n let manifestKey = JSON.stringify({\n lockboxUuid,\n filter,\n expandPrivateMetadata,\n lockboxOwnerUuid,\n })\n if (!forceRefresh && this.cachedManifest[manifestKey]) return this.cachedManifest[manifestKey]\n\n return this.vaultClient.lockboxManifestGet(lockboxUuid, filter, lockboxOwnerUuid).then((manifest) => {\n return Promise.all(\n manifest.map(async (entry) => {\n if (expandPrivateMetadata && entry.metadata.privateMetadata) {\n let privateMeta = await this.getJsonData<Metadata>(\n lockboxUuid!,\n entry.metadata.privateMetadata,\n lockboxOwnerUuid\n )\n entry.metadata = {\n ...entry.metadata,\n ...privateMeta,\n }\n }\n return entry\n })\n ).then((manifest) => (this.cachedManifest[manifestKey] = manifest))\n })\n }\n\n /**\n * @description Create or update the personal information and store it in the first owned lockbox\n * @param identity The identity to use\n * @param data The personal data to store\n * @param dataUuid (optional) The dataUuid to update\n * @returns\n */\n public async createPersonalInformations(\n identity: IdentityResponse,\n data: PopulatedWorkflowData,\n dataUuid?: string\n ): Promise<DataCreateResponse> {\n const lockboxUuid = (await this.getGrants()).find(\n (lockbox) => lockbox.lockboxOwnerUuid === identity.id\n )?.lockboxUuid\n\n if (lockboxUuid) {\n return this.createJsonData<PersonalMeta>(\n lockboxUuid,\n data,\n {\n category: MetadataCategory.Personal,\n documentType: DocumentType.PopulatedWorkflowData,\n },\n {},\n undefined,\n dataUuid\n )\n } else {\n throw MissingLockbox\n }\n }\n\n /**\n * Create or update user Preference\n * @param identity\n * @param preference\n * @param dataUuid\n * @returns\n */\n public async createUserPreference(\n identity: IdentityResponse,\n preference: UserPreference,\n dataUuid?: string\n ): Promise<DataCreateResponse> {\n const lockboxUuid = (await this.getGrants()).find(\n (lockbox) => lockbox.lockboxOwnerUuid === identity.id\n )?.lockboxUuid\n\n if (lockboxUuid) {\n return this.createJsonData<PreferenceMeta>(\n lockboxUuid,\n preference,\n {\n category: MetadataCategory.Preference,\n contentType: 'application/json',\n },\n {},\n undefined,\n dataUuid\n )\n } else {\n throw MissingLockbox\n }\n }\n\n /**\n * retrieves the user preference from a grant\n * @param grant The grant\n * @returns the user preference\n */\n public async getDataFromGrant<T = any>(grant: Grant, filter: Metadata): Promise<LocalizedData<T>> {\n const { lockboxUuid, lockboxOwnerUuid } = grant\n\n if (!lockboxUuid) throw MissingLockbox\n if (!lockboxOwnerUuid) throw MissingLockboxOwner\n const identificationDataUuid = (\n await this.getLockboxManifest(\n lockboxUuid,\n\n filter,\n false,\n grant.lockboxOwnerUuid,\n true\n )\n )[0].dataUuid\n\n return {\n lockboxOwnerUuid,\n lockboxUuid,\n dataUuid: identificationDataUuid,\n data: await this.getJsonData<T>(lockboxUuid, identificationDataUuid),\n }\n }\n\n /**\n * retrieves the user preference from a consultation id\n * @param consultationId The related consultationId\n * @returns the user preference\n */\n public async getUserPreferenceFromConsultId(consultationId: string): Promise<LocalizedData<UserPreference>> {\n const grant = await this.getGrantFromConsultId(consultationId)\n\n if (!grant) throw MissingGrant\n\n return this.getDataFromGrant<UserPreference>(grant, {\n category: MetadataCategory.Preference,\n contentType: 'application/json',\n })\n }\n\n /**\n * retrieves the user preference stored in the first owned lockbox from identity\n * @param identity The identity to use\n * @returns the user preference\n */\n public async getUserPreference(identity: IdentityResponse): Promise<LocalizedData<UserPreference>> {\n const grant = (await this.getGrants()).find((lockbox) => lockbox.lockboxOwnerUuid === identity.id)\n\n if (!grant) throw MissingGrant\n\n return this.getDataFromGrant<UserPreference>(grant, {\n category: MetadataCategory.Preference,\n contentType: 'application/json',\n })\n }\n\n /**\n * retrieves the user preference from a consultation id\n * @param consultationId The related consultationId\n * @returns the user preference\n */\n public async getRecoveryDataFromConsultId(consultationId: string): Promise<LocalizedData<RecoveryData>> {\n const grant = await this.getGrantFromConsultId(consultationId)\n\n if (!grant) throw MissingGrant\n\n return this.getDataFromGrant<RecoveryData>(grant, {\n category: MetadataCategory.Recovery,\n contentType: 'application/json',\n })\n }\n\n /**\n * retrieves the user preference stored in the first owned lockbox from identity\n * @param identity The identity to use\n * @returns the user preference\n */\n public async getRecoveryData(identity: IdentityResponse): Promise<LocalizedData<RecoveryData>> {\n const grant = (await this.getGrants()).find((lockbox) => lockbox.lockboxOwnerUuid === identity.id)\n\n if (!grant) throw MissingGrant\n\n return this.getDataFromGrant(grant, {\n category: MetadataCategory.Recovery,\n contentType: 'application/json',\n })\n }\n\n /**\n * @name getAssignedConsultations\n * @description finds all assigned or owned consultations for the logged user\n * Steps:\n * - Retrieves all granted lockboxes given to the logged user\n * - for each lockbox, find all consultation ids\n * - for each consultation id, retrieve the consult information\n * @param practiceUuid the uuid of the practice to look consult into\n * @returns the list of consults\n */\n public async getAssignedConsultations(practiceUuid: Uuid, forceRefresh: boolean = false): Promise<Consult[]> {\n return Promise.all(\n (await this.getGrants(undefined, forceRefresh)).map((grant) =>\n this.getLockboxManifest(\n grant.lockboxUuid!,\n {\n category: MetadataCategory.Consultation,\n documentType: DocumentType.PopulatedWorkflowData,\n },\n true,\n undefined,\n forceRefresh\n ).then((manifest) =>\n Promise.all(\n manifest.map(\n async (entry) =>\n await this.consultClient.getConsultByUUID(entry.metadata.consultationId, practiceUuid)\n )\n ).then((promise) => promise.flat())\n )\n )\n ).then((consults) => consults.flat())\n }\n\n /**\n * Gets the past consultations of the patient as well as his relatives if any\n * @param consultationId any consultation uuid from which we will fetch all the other consultations of the same patient as the owner of this consultation id\n * @param practiceUuid\n */\n public async getPastConsultationsFromConsultId(\n consultationId: string,\n practiceUuid: string\n ): Promise<Consult[] | undefined> {\n const grant = await this.getGrantFromConsultId(consultationId)\n if (!grant) return undefined\n\n let consultationsInLockbox: string[] = (\n await this.vaultClient.lockboxMetadataGet(\n grant.lockboxUuid!,\n ['consultationId'],\n ['consultationId'],\n {\n category: MetadataCategory.Consultation,\n documentType: DocumentType.PopulatedWorkflowData,\n },\n grant.lockboxOwnerUuid\n )\n )\n .flat()\n .map((metadata: { consultationId: string }) => metadata.consultationId)\n\n if (consultationsInLockbox.length == 0) return []\n\n return await Promise.all(\n consultationsInLockbox.map(async (consultId: string) => {\n return await this.consultClient.getConsultByUUID(consultId, practiceUuid)\n })\n )\n }\n\n /**\n * @name getPatientConsultationData\n * @description retrieves the consultation data\n * @param consultationId\n * @returns\n */\n public async getPatientConsultationData(\n consultationId: Uuid,\n forceRefresh: boolean = false\n ): Promise<PopulatedWorkflowData[]> {\n //TODO: make use of getPatientDocumentsList instead of doing it manually here\n return Promise.all(\n (await this.getGrants({ consultationId }, forceRefresh))\n .map((grant) =>\n this.getLockboxManifest(\n grant.lockboxUuid!,\n {\n category: MetadataCategory.Consultation,\n documentType: DocumentType.PopulatedWorkflowData,\n consultationId, //since we want to update the cached manifest (if another consult data exists)\n },\n true,\n grant.lockboxOwnerUuid,\n forceRefresh\n ).then((manifest) =>\n Promise.all(\n manifest.map((e) =>\n this.getJsonData<PopulatedWorkflowData>(\n grant.lockboxUuid!,\n e.dataUuid,\n grant.lockboxOwnerUuid\n )\n )\n )\n )\n )\n .flat()\n ).then((data) => data.flat())\n }\n\n /**\n * This function returns the patient prescriptions\n * @param consultationId\n * @returns\n */\n public async getPatientPrescriptionsList(consultationId: Uuid): Promise<Document[]> {\n return this.getPatientDocumentsList(\n {\n category: MetadataCategory.Consultation,\n documentType: DocumentType.Prescription,\n },\n true,\n consultationId\n )\n }\n\n /**\n * This function returns the patient results\n * @param consultationId\n * @returns\n */\n public async getPatientResultsList(consultationId: Uuid): Promise<Document[]> {\n return this.getPatientDocumentsList(\n {\n category: MetadataCategory.Consultation,\n documentType: DocumentType.Result,\n },\n true,\n consultationId\n )\n }\n\n /**\n * returns the patient treatment plan options\n * @param consultationId\n * @returns Document[] corresponding to the patient treatment plan options\n */\n public async getPatientTreatmentPlans(consultationId: Uuid): Promise<Document[]> {\n return this.getPatientDocumentsList(\n {\n category: MetadataCategory.Consultation,\n documentType: DocumentType.TreatmentPlan,\n },\n true,\n consultationId\n )\n }\n\n /**\n * returns a specific patient treatment plan option\n * @param consultationId\n * @param treatmentPlanId\n * @returns\n */\n public async getPatientTreatmentPlanByUuid(consultationId: Uuid, treatmentPlanId: Uuid): Promise<Document[]> {\n return this.getPatientDocumentsList(\n {\n category: MetadataCategory.Consultation,\n documentType: DocumentType.TreatmentPlan,\n treatmentPlanId,\n },\n true,\n consultationId\n )\n }\n\n /**\n * @name getPatientDocumentsList\n * @description applies the provided filter to the vault to only find those documents\n * @param filters the applied filters (e.g. type of documents)\n * @param expandPrivateMetadata whether or not, the private metadata needs to be retrieved\n * (more computationally expensive)\n * @param consultationId\n * @returns the filtered document list\n */\n public async getPatientDocumentsList(\n filters: Object,\n expandPrivateMetadata: boolean,\n consultationId: Uuid\n ): Promise<Document[]> {\n return Promise.all(\n (await this.getGrants({ consultationId }))\n .map((grant) =>\n this.getLockboxManifest(\n grant.lockboxUuid!,\n { ...filters, consultationId },\n expandPrivateMetadata,\n grant.lockboxOwnerUuid,\n true\n ).then((manifest) =>\n Promise.all(\n manifest.map(async (entry): Promise<Document> => {\n return {\n lockboxOwnerUuid: grant.lockboxOwnerUuid,\n lockboxUuid: grant.lockboxUuid!,\n ...entry,\n }\n })\n )\n )\n )\n .flat()\n ).then((data) => data.flat())\n }\n\n /****************************************************************************************************************\n * RECOVERY *\n ****************************************************************************************************************/\n\n /**\n * @name recoverPrivateKeyFromSecurityQuestions\n * @description Recovers and sets the rsa private key from the answered security questions\n * @param id\n * @param recoverySecurityQuestions\n * @param recoverySecurityAnswers\n * @param threshold the number of answers needed to recover the key\n */\n public async recoverPrivateKeyFromSecurityQuestions(\n id: Uuid,\n recoverySecurityQuestions: string[],\n recoverySecurityAnswers: string[],\n threshold: number\n ) {\n let shards: SecretShard[] = (await this.guardClient.identityGet(id)).recoverySecurityQuestions!\n let answeredShards = shards\n .filter((shard: any) => {\n // filters all answered security questions\n let indexOfQuestion = recoverySecurityQuestions.indexOf(shard.securityQuestion)\n if (indexOfQuestion === -1) return false\n return recoverySecurityAnswers[indexOfQuestion] && recoverySecurityAnswers[indexOfQuestion] != ''\n })\n .map((item: any) => {\n // appends the security answer to the answered shards\n let index = recoverySecurityQuestions.indexOf(item.securityQuestion)\n item.securityAnswer = recoverySecurityAnswers[index]\n return item\n })\n try {\n // reconstructs the key from the answered security answers\n let privateKey = this.toolbox.reconstructSecret(answeredShards, threshold)\n this.rsa = this.toolbox.CryptoRSA.fromKey(privateKey)\n } catch (e) {\n console.error(e)\n }\n }\n\n /**\n * @name recoverPrivateKeyFromPassword\n * @description Recovers and sets the rsa private key from the password\n * @param id\n * @param password\n */\n public async recoverPrivateKeyFromPassword(id: Uuid, password: string) {\n let identity = await this.guardClient.identityGet(id)\n\n let recoveryPayload = identity.recoveryPassword\n let symmetricDecryptor = this.toolbox.CryptoChaCha.fromPassphrase(password)\n let privateKey = symmetricDecryptor.base64PayloadDecryptToBytes(recoveryPayload)\n\n if (identity.recoveryLogin) {\n //Ensure we can recover from a page reload\n let symetricEncryptor = this.toolbox.CryptoChaCha.fromPassphrase(identity.recoveryLogin)\n sessionStorage.setItem(\n sessionStorePrivateKeyName(id),\n symetricEncryptor.bytesEncryptToBase64Payload(privateKey)\n )\n }\n\n this.rsa = this.toolbox.CryptoRSA.fromKey(privateKey)\n }\n\n /**\n * @name recoverPrivateKeyFromMasterKey\n * @description Recovers and sets the rsa private key from the master key\n * @param id\n * @param masterKey\n */\n public async recoverPrivateKeyFromMasterKey(id: Uuid, masterKey: string) {\n let recoveryPayload = (await this.guardClient.identityGet(id)).recoveryMasterKey!\n let symmetricDecryptor = this.toolbox.CryptoChaCha.fromPassphrase(masterKey)\n let privateKey = symmetricDecryptor.base64PayloadDecryptToBytes(recoveryPayload)\n this.rsa = this.toolbox.CryptoRSA.fromKey(privateKey)\n }\n\n /**\n * @description Generates and updates the security questions and answers payload using new recovery questions and answers\n * Important: Since the security questions generate a payload for the private key, they will never be stored on the device as they must remain secret!!!\n * @param id\n * @param recoverySecurityQuestions\n * @param recoverySecurityAnswers\n * @param threshold the number of answers needed to rebuild the secret\n */\n public async updateSecurityQuestions(\n id: Uuid,\n recoverySecurityQuestions: string[],\n recoverySecurityAnswers: string[],\n threshold: number\n ) {\n if (!this.rsa) throw IncompleteAuthentication\n let securityQuestionPayload = this.toolbox.breakSecretIntoShards(\n recoverySecurityQuestions,\n recoverySecurityAnswers,\n this.rsa.private(),\n threshold\n )\n let updateRequest = {\n recoverySecurityQuestions: securityQuestionPayload,\n }\n\n return await this.guardClient.identityUpdate(id, updateRequest)\n }\n\n /**\n * @description Generates and stores the payload encrypted payload and updates the password itself (double hash)\n * @important\n * the recovery payload uses a singly hashed password and the password stored is doubly hashed so\n * the stored password cannot derive the decryption key in the payload\n * @note\n * the old password must be provided when not performing an account recovery\n * @param id\n * @param newPassword\n * @param oldPassword\n */\n public async updatePassword(id: Uuid, newPassword: string, oldPassword?: string) {\n if (!this.rsa) throw IncompleteAuthentication\n\n let symmetricEncryptor = this.toolbox.CryptoChaCha.fromPassphrase(newPassword)\n let passwordPayload = symmetricEncryptor.bytesEncryptToBase64Payload(this.rsa.private())\n if (oldPassword) {\n oldPassword = this.toolbox.hashStringToBase64(this.toolbox.hashStringToBase64(oldPassword))\n }\n\n newPassword = this.toolbox.hashStringToBase64(this.toolbox.hashStringToBase64(newPassword))\n\n let updateRequest = {\n password: {\n oldPassword,\n newPassword,\n },\n recoveryPassword: passwordPayload,\n }\n\n return await this.guardClient.identityUpdate(id, updateRequest)\n }\n\n /**\n * @description Generates and stores the master key encrypted payload\n * Important\n * Since the master key is used to generate a payload for the private key, it will never be stored on the device as it must remain secret!\n * @param id\n * @param masterKey\n * @param lockboxUuid\n */\n async updateMasterKey(id: Uuid, masterKey: string, lockboxUuid: Uuid) {\n if (!this.rsa) throw IncompleteAuthentication\n\n let symmetricEncryptor = this.toolbox.CryptoChaCha.fromPassphrase(masterKey)\n let masterKeyPayload = symmetricEncryptor.bytesEncryptToBase64Payload(this.rsa.private())\n let updateRequest = { recoveryMasterKey: masterKeyPayload }\n const updatedIdentity = await this.guardClient.identityUpdate(id, updateRequest)\n\n await this.getOrInsertJsonData<RecoveryMeta>(\n lockboxUuid,\n { masterKey },\n {\n category: MetadataCategory.Recovery,\n contentType: 'application/json',\n },\n {},\n true\n )\n\n return updatedIdentity\n }\n}\n","import { AxiosService, CliniaResponse, FacetFilter, PlaceData } from \"oro-sdk-apis\"\n\nexport class CliniaService {\n private api: AxiosService\n\n constructor(private url: string, apiKey: string, private locale?: string) {\n this.api = new AxiosService({ headers: { 'X-Clinia-API-Key': apiKey } })\n }\n\n public placeSearch(searchOptions: {\n locale?: string\n query?: string\n facetFilters?: FacetFilter[]\n location?: string\n aroundLatLng?: string\n page?: number\n }) {\n const { locale, ...data } = searchOptions\n\n return this.api.post<CliniaResponse<PlaceData>>(\n `${this.url}/search/v1/indexes/health_facility/query`,\n data,\n {\n params: { locale: locale ?? this.locale },\n }\n )\n }\n\n public placeMatch(\n searchOptions: {\n locale?: string\n name?: string\n address?: string\n postalCode?: string\n place?: string\n region?: string\n country?: string\n },\n type?: string\n ) {\n const { locale, ...data } = searchOptions\n\n let request = this.api.post<PlaceData[]>(\n `${this.url}/search/v1/matches`,\n data,\n {\n params: { locale: locale ?? this.locale },\n }\n )\n\n if (type) {\n request = request.then((places) =>\n places.filter((place) => place.type === type)\n )\n }\n\n return request\n }\n}\n","import initApis from 'oro-sdk-apis'\nimport { OroClient } from './client'\nimport * as OroToolboxNamespace from 'oro-toolbox'\n\nexport type OroToolbox = typeof OroToolboxNamespace\n\nexport let wasmPath = 'node_modules/oro-toolbox'\n\n/**\n * This function helps you to initialize and OroClient instance\n * @param toolbox the OroToolbox object\n * @param tellerBaseURL the teller service base URL \n * @param vaultBaseURL the vault service base URL \n * @param guardBaseURL the guard service base URL \n * @param searchbaseURL the search service base URL\n * @param practiceBaseURL the practice service base URL \n * @param consultBaseURL the consult service base URL \n * @param workflowBaseURL the workflow service base URL \n * @param diagnosisBaseURL the diagnosis service base URL \n * @param authenticationCallback (optional) authenticationCallback the authentification callback \n * @returns an instance of OroClient\n */\nconst init = (\n toolbox: OroToolbox,\n tellerBaseURL: string,\n vaultBaseURL: string,\n guardBaseURL: string,\n searchBaseURL: string,\n practiceBaseURL: string,\n consultBaseURL: string,\n workflowBaseURL: string,\n diagnosisBaseURL: string,\n authenticationCallback?: (err: Error) => void\n) => {\n const {\n tellerService,\n practiceService,\n consultService,\n vaultService,\n guardService,\n searchService,\n workflowService,\n diagnosisService,\n } = initApis(\n {\n tellerBaseURL,\n vaultBaseURL,\n guardBaseURL,\n searchBaseURL,\n practiceBaseURL,\n consultBaseURL,\n workflowBaseURL,\n diagnosisBaseURL,\n },\n authenticationCallback\n )\n\n const client = new OroClient(\n toolbox,\n tellerService!,\n vaultService!,\n guardService!,\n searchService!,\n practiceService!,\n consultService!,\n workflowService!,\n diagnosisService!,\n authenticationCallback\n )\n\n return client\n}\n\nexport { OroClient } from './client'\nexport * from 'oro-sdk-apis'\nexport * from './models'\nexport * from './helpers'\nexport * from './services'\nexport { OroToolboxNamespace }\nexport default init\n"],"names":["runtime","exports","Op","Object","prototype","hasOwn","hasOwnProperty","$Symbol","Symbol","iteratorSymbol","iterator","asyncIteratorSymbol","asyncIterator","toStringTagSymbol","toStringTag","define","obj","key","value","defineProperty","enumerable","configurable","writable","err","wrap","innerFn","outerFn","self","tryLocsList","generator","create","Generator","context","Context","_invoke","state","method","arg","Error","undefined","done","delegate","delegateResult","maybeInvokeDelegate","ContinueSentinel","sent","_sent","dispatchException","abrupt","record","tryCatch","type","makeInvokeMethod","fn","call","GeneratorFunction","GeneratorFunctionPrototype","IteratorPrototype","this","getProto","getPrototypeOf","NativeIteratorPrototype","values","Gp","defineIteratorMethods","forEach","AsyncIterator","PromiseImpl","previousPromise","callInvokeWithMethodAndArg","resolve","reject","invoke","result","__await","then","unwrapped","error","TypeError","info","resultName","next","nextLoc","pushTryEntry","locs","entry","tryLoc","catchLoc","finallyLoc","afterLoc","tryEntries","push","resetTryEntry","completion","reset","iterable","iteratorMethod","isNaN","length","i","doneResult","displayName","isGeneratorFunction","genFun","ctor","constructor","name","mark","setPrototypeOf","__proto__","awrap","async","Promise","iter","keys","object","reverse","pop","skipTempReset","prev","charAt","slice","stop","rootRecord","rval","exception","handle","loc","caught","hasCatch","hasFinally","finallyEntry","complete","finish","catch","thrown","delegateYield","module","regeneratorRuntime","accidentalStrictMode","globalThis","Function","personalMetaToPrefix","MetadataCategory","Personal","ChildPersonal","OtherPersonal","identificationToPersonalInformations","data","category","prefix","birthday","firstname","gender","phone","zip","hid","pharmacy","address","toActualObject","ret","entries","fields","field","displayedAnswer","answer","sessionStorePrivateKeyName","id","IncompleteAuthentication","MissingGrant","MissingLockbox","MissingLockboxOwner","AssociatedLockboxNotFound","WorkflowAnswersMissingError","filterTriggeredAnsweredWithKind","workflowData","kind","selectedAnswers","flattenedAnswers","flattenSelectedAnswers","triggeredQuestionsWithKind","fromEntries","pages","map","a","questions","filter","question","isTriggered","triggers","flat","samePageAnswers","reduce","cur","res","questionFieldName","getWorkflowDataByCategory","triggeredQuestions","all","e","k","populateWorkflowField","populatedValue","workflowCreatedAt","createdAt","workflowId","locale","console","getImagesFromIndexDb","getMany","v","answerValue","answers","text","images","image","imageData","includes","linearAnswers","getInitialisedSelectedAnswers","workflow","useDefault","page","defaultValue","registerPatient","patientUuid","consultRequest","oroClient","masterKey","recoveryQA","consult","lockboxUuid","practitionerAdmin","retry","identity","errorsThrown","setTimeout","practiceClient","practiceGetFromUuid","uuidPractice","uuidAdmin","practiceGetPractitioners","log","practitioners","getOrCreatePatientConsultationUuid","getOrCreatePatientLockbox","guardClient","identityGet","grantLockbox","grantPromises","practitioner","uuid","IndexKey","ConsultationLockbox","grant","lockboxOwnerUuid","consultationId","consultIndex","consultIndexPromises","vaultIndexAdd","storeImageAliases","storePatientData","isoLanguageRequired","_identity","recoveryMasterKey","updateMasterKey","_identity2","recoverySecurityQuestions","updateSecurityQuestions","recoverySecurityAnswers","buildConsultSearchIndex","consultClient","updateConsultByUUID","statusMedical","MedicalStatus","New","cleanIndex","practiceGetPayment","idStripeInvoiceOrPaymentIntent","payment","uuidConsult","getConsultByUUID","consultCreate","getGrants","grants","vaultClient","lockboxCreate","isoLanguage","getOrInsertJsonData","Raw","contentType","Consultation","documentType","DocumentType","PopulatedWorkflowData","Medical","consultationIds","extractAndStorePersonalWorkflowData","Preference","dataUuids","nonNullImages","img","promises","ImageAlias","idbId","extractPersonalInfoFromWorkflowData","personalInfoPopulatedWfData","childPersonalInfoPopulatedWfData","otherPersonalInfoPopulatedWfData","terms","shortId","personalInfo","childPersonalInfo","otherPersonalInfo","searchClient","index","decryptGrants","encryptedGrants","rsaKey","encryptedLockbox","uuidParse","base64DecryptToBytes","decryptConsultLockboxGrants","encryptedConsultLockboxes","base64DecryptToJson","encryptedIndexEntry","grantsTuple","grantTuples","filterGrantsWithLockboxMetadata","vaultIndex","forceRefresh","buildLegacyVaultIndex","indexConsults","consultGrant","consultGrants","lockboxMetadataGet","setVaultIndex","OroClient","toolbox","tellerClient","workflowClient","diagnosisClient","authenticationCallback","cachedMetadataGrants","cachedManifest","signUp","email","password","practice","tosAndCpAcceptance","tokenData","subscription","skipEmailValidation","rsa","CryptoRSA","privateKey","symmetricEncryptor","CryptoChaCha","fromPassphrase","recoveryPassword","bytesEncryptToBase64Payload","hashedPassword","hashStringToBase64","emailConfirmed","signupRequest","practiceUuid","toLowerCase","publicKey","encodeToBase64","identityCreate","recoveryLogin","symetricEncryptor","sessionStorage","setItem","confirmEmail","accessToken","setTokens","whoAmI","identityUpdate","sub","signIn","otp","tokenRequest","authToken","userUuid","recoverPrivateKeyFromPassword","resumeSession","recoveryPayload","getItem","recoveryKey","symmetricDecryptor","base64PayloadDecryptToBytes","fromKey","localEncryptToJsonPayload","chaChaKey","encryptedData","jsonEncryptToBase64Payload","encryptedKey","encryptToBytes","localDecryptJsonPayload","base64PayloadDecryptToJson","signOut","secrets","refreshToken","authLogout","buildVaultIndex","forceUpdateIndexEntries","_this","consults","alert","indexOwnerUuid","rsaPub","decodeFromBase64","encryptedIndex","uniqueHash","timestamp","jsonWithPubEncryptToBase64","_this2","JSON","stringify","_this2$vaultIndex$Ind","find","vaultIndexPut","indexSnapshotAdd","_index$IndexKey$Consu","c","vaultIndexSnapshotPut","granteeUuid","getCachedSecretCryptor","secret","granteePublicKey","granteeEncryptedSecret","bytesWithPubEncryptToBase64","request","encryptedSecret","lockboxGrant","createMessageData","message","previousDataUuid","author","encryptedPrivateMeta","lockboxDataStore","publicMetadata","Message","privateMetadata","createMessageAttachmentData","Uint8Array","arrayBuffer","lastModified","size","fileName","createConsultationAttachmentData","createBytesData","createJsonData","meta","privateMeta","forceReplace","lockboxManifestGet","manifest","dataUuid","getJsonData","lockboxDataGet","getBytesData","filterString","vaultIndexGet","decryptedConsults","grantsByConsultLockbox","grantsGet","decryptedGrants","findIndex","lockboxSecretGet","sharedSecret","cryptor","getPersonalInformationsFromConsultId","getMetaCategoryFromConsultId","getMedicalDataFromConsultId","_this3","getLockboxManifest","metadata","getPersonalInformations","userId","lockbox","identificationDataUuid","getGrantFromConsultId","getIdentityFromConsultId","expandPrivateMetadata","manifestKey","_this4","createPersonalInformations","_yield$this$getGrants","createUserPreference","preference","_yield$this$getGrants2","getDataFromGrant","getUserPreferenceFromConsultId","getUserPreference","getRecoveryDataFromConsultId","Recovery","getRecoveryData","getAssignedConsultations","_this5","promise","getPastConsultationsFromConsultId","consultationsInLockbox","consultId","_this6","getPatientConsultationData","_this7","getPatientPrescriptionsList","getPatientDocumentsList","Prescription","getPatientResultsList","Result","getPatientTreatmentPlans","TreatmentPlan","getPatientTreatmentPlanByUuid","treatmentPlanId","filters","_this8","recoverPrivateKeyFromSecurityQuestions","threshold","answeredShards","shard","indexOfQuestion","indexOf","securityQuestion","item","securityAnswer","reconstructSecret","recoverPrivateKeyFromMasterKey","securityQuestionPayload","breakSecretIntoShards","updateRequest","updatePassword","newPassword","oldPassword","passwordPayload","masterKeyPayload","updatedIdentity","CliniaService","url","apiKey","api","AxiosService","headers","placeSearch","searchOptions","post","params","placeMatch","places","place","tellerBaseURL","vaultBaseURL","guardBaseURL","searchBaseURL","practiceBaseURL","consultBaseURL","workflowBaseURL","diagnosisBaseURL","initApis","tellerService","vaultService","guardService","searchService","practiceService","consultService","workflowService","diagnosisService","arrSelectedLocality","flatMap","currentAnswerPage","arrCountryFields","workflowFieldName","arrProvinceFields","arrConsultLocalFields","currentFieldName","currentSelectedLocality","startsWith","allowedLocalityPatterns","finalLocality","extractedSelected","exec","indexSelectedPriority","isoSelectedValue","extractedFinal","indexFinalPriority","populatedWorkflow","filledWorkflow","parse","pageIdx","infos"],"mappings":"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"}