cod-dicomweb-server 1.3.6 → 1.3.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cjs/main.js CHANGED
@@ -142,7 +142,8 @@ __webpack_require__.r(enums_namespaceObject);
142
142
  __webpack_require__.d(enums_namespaceObject, {
143
143
  DataRetrieveMode: () => (DataRetrieveMode),
144
144
  FetchType: () => (FetchType),
145
- RequestType: () => (RequestType)
145
+ RequestType: () => (RequestType),
146
+ URLType: () => (URLType)
146
147
  });
147
148
 
148
149
  // NAMESPACE OBJECT: ./src/constants/url.ts
@@ -183,6 +184,12 @@ var DataRetrieveMode = /*#__PURE__*/function (DataRetrieveMode) {
183
184
  DataRetrieveMode[DataRetrieveMode["REQUEST"] = 1] = "REQUEST";
184
185
  return DataRetrieveMode;
185
186
  }({});
187
+ var URLType = /*#__PURE__*/function (URLType) {
188
+ URLType[URLType["THUMBNAIL"] = 0] = "THUMBNAIL";
189
+ URLType[URLType["FILE"] = 1] = "FILE";
190
+ URLType[URLType["OTHERS"] = 2] = "OTHERS";
191
+ return URLType;
192
+ }({});
186
193
  // EXTERNAL MODULE: ./node_modules/dicom-parser/dist/dicomParser.min.js
187
194
  var dicomParser_min = __webpack_require__(915);
188
195
  ;// ./src/classes/customClasses.ts
@@ -1160,6 +1167,12 @@ function metadataManager_typeof(o) { "@babel/helpers - typeof"; return metadataM
1160
1167
  function metadataManager_regeneratorRuntime() { "use strict"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ metadataManager_regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = "function" == typeof Symbol ? Symbol : {}, a = i.iterator || "@@iterator", c = i.asyncIterator || "@@asyncIterator", u = i.toStringTag || "@@toStringTag"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, ""); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, "_invoke", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: "normal", arg: t.call(e, r) }; } catch (t) { return { type: "throw", arg: t }; } } e.wrap = wrap; var h = "suspendedStart", l = "suspendedYield", f = "executing", s = "completed", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { ["next", "throw", "return"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if ("throw" !== c.type) { var u = c.arg, h = u.value; return h && "object" == metadataManager_typeof(h) && n.call(h, "__await") ? e.resolve(h.__await).then(function (t) { invoke("next", t, i, a); }, function (t) { invoke("throw", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke("throw", t, i, a); }); } a(c.arg); } var r; o(this, "_invoke", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw Error("Generator is already running"); if (o === s) { if ("throw" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if ("next" === n.method) n.sent = n._sent = n.arg;else if ("throw" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else "return" === n.method && n.abrupt("return", n.arg); o = f; var p = tryCatch(e, r, n); if ("normal" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } "throw" === p.type && (o = s, n.method = "throw", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, "throw" === n && e.iterator["return"] && (r.method = "return", r.arg = t, maybeInvokeDelegate(e, r), "throw" === r.method) || "return" !== n && (r.method = "throw", r.arg = new TypeError("The iterator does not provide a '" + n + "' method")), y; var i = tryCatch(o, e.iterator, r.arg); if ("throw" === i.type) return r.method = "throw", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, "return" !== r.method && (r.method = "next", r.arg = t), r.delegate = null, y) : a : (r.method = "throw", r.arg = new TypeError("iterator result is not an object"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = "normal", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: "root" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || "" === e) { var r = e[a]; if (r) return r.call(e); if ("function" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(metadataManager_typeof(e) + " is not iterable"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, "constructor", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, "constructor", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, "GeneratorFunction"), e.isGeneratorFunction = function (t) { var e = "function" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || "GeneratorFunction" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, "GeneratorFunction")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, "Generator"), define(g, a, function () { return this; }), define(g, "toString", function () { return "[object Generator]"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = "next", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) "t" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if ("throw" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = "throw", a.arg = e, r.next = n, o && (r.method = "next", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if ("root" === i.tryLoc) return handle("end"); if (i.tryLoc <= this.prev) { var c = n.call(i, "catchLoc"), u = n.call(i, "finallyLoc"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw Error("try statement without catch or finally"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, "finallyLoc") && this.prev < o.finallyLoc) { var i = o; break; } } i && ("break" === t || "continue" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = "next", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if ("throw" === t.type) throw t.arg; return "break" === t.type || "continue" === t.type ? this.next = t.arg : "return" === t.type ? (this.rval = this.arg = t.arg, this.method = "return", this.next = "end") : "normal" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, "catch": function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if ("throw" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw Error("illegal catch attempt"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, "next" === this.method && (this.arg = t), y; } }, e; }
1161
1168
  function metadataManager_asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }
1162
1169
  function metadataManager_asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { metadataManager_asyncGeneratorStep(a, r, o, _next, _throw, "next", n); } function _throw(n) { metadataManager_asyncGeneratorStep(a, r, o, _next, _throw, "throw", n); } _next(void 0); }); }; }
1170
+ function metadataManager_slicedToArray(r, e) { return metadataManager_arrayWithHoles(r) || metadataManager_iterableToArrayLimit(r, e) || metadataManager_unsupportedIterableToArray(r, e) || metadataManager_nonIterableRest(); }
1171
+ function metadataManager_nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
1172
+ function metadataManager_unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return metadataManager_arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? metadataManager_arrayLikeToArray(r, a) : void 0; } }
1173
+ function metadataManager_arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
1174
+ function metadataManager_iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
1175
+ function metadataManager_arrayWithHoles(r) { if (Array.isArray(r)) return r; }
1163
1176
  function metadataManager_classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
1164
1177
  function metadataManager_defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, metadataManager_toPropertyKey(o.key), o); } }
1165
1178
  function metadataManager_createClass(e, r, t) { return r && metadataManager_defineProperties(e.prototype, r), t && metadataManager_defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }
@@ -1175,24 +1188,28 @@ var MetadataManager = /*#__PURE__*/function () {
1175
1188
  }
1176
1189
  return metadataManager_createClass(MetadataManager, [{
1177
1190
  key: "addDeidMetadata",
1178
- value: function addDeidMetadata(jsonMetadata) {
1179
- var deid_study_uid = jsonMetadata.deid_study_uid,
1180
- deid_series_uid = jsonMetadata.deid_series_uid,
1181
- cod = jsonMetadata.cod;
1182
- if (!cod || !deid_study_uid || !deid_series_uid) {
1191
+ value: function addDeidMetadata(jsonMetadata, url) {
1192
+ var _url$match;
1193
+ var cod = jsonMetadata.cod;
1194
+ var _url$match$1$split = (_url$match = url.match(/studies\/(.*?)\/metadata/)) === null || _url$match === void 0 ? void 0 : _url$match[1].split('/'),
1195
+ _url$match$1$split2 = metadataManager_slicedToArray(_url$match$1$split, 3),
1196
+ studyUID = _url$match$1$split2[0],
1197
+ _ = _url$match$1$split2[1],
1198
+ seriesUID = _url$match$1$split2[2];
1199
+ if (!cod || !studyUID || !seriesUID) {
1183
1200
  console.warn('Missing required metadata properties: cod, deid_study_uid, or deid_series_uid');
1184
1201
  return;
1185
1202
  }
1186
- for (var deid_sop_uid in cod.instances) {
1187
- var instance = cod.instances[deid_sop_uid];
1203
+ for (var sopUID in cod.instances) {
1204
+ var instance = cod.instances[sopUID];
1188
1205
  instance.metadata.DeidStudyInstanceUID = {
1189
- Value: [deid_study_uid]
1206
+ Value: [studyUID]
1190
1207
  };
1191
1208
  instance.metadata.DeidSeriesInstanceUID = {
1192
- Value: [deid_series_uid]
1209
+ Value: [seriesUID]
1193
1210
  };
1194
1211
  instance.metadata.DeidSopInstanceUID = {
1195
- Value: [deid_sop_uid]
1212
+ Value: [sopUID]
1196
1213
  };
1197
1214
  }
1198
1215
  }
@@ -1236,7 +1253,7 @@ var MetadataManager = /*#__PURE__*/function () {
1236
1253
  }
1237
1254
  return response.json();
1238
1255
  }).then(function (data) {
1239
- _this.addDeidMetadata(data);
1256
+ _this.addDeidMetadata(data, url);
1240
1257
  return data;
1241
1258
  });
1242
1259
  _context.next = 12;
@@ -1660,6 +1677,23 @@ function _writeFile() {
1660
1677
  }));
1661
1678
  return _writeFile.apply(this, arguments);
1662
1679
  }
1680
+ function download(fileName, file) {
1681
+ try {
1682
+ var blob = new Blob([file], {
1683
+ type: 'application/x-tar'
1684
+ });
1685
+ var url = URL.createObjectURL(blob);
1686
+ var a = document.createElement('a');
1687
+ a.href = url;
1688
+ a.download = fileName;
1689
+ a.click();
1690
+ URL.revokeObjectURL(url);
1691
+ return true;
1692
+ } catch (error) {
1693
+ console.warn("Error downloading file - ".concat(fileName, ": ") + error.message);
1694
+ return false;
1695
+ }
1696
+ }
1663
1697
  function clearPartialFiles() {
1664
1698
  return _clearPartialFiles.apply(this, arguments);
1665
1699
  }
@@ -2047,11 +2081,17 @@ var CodDicomWebServer = /*#__PURE__*/function () {
2047
2081
  }
2048
2082
  return CodDicomWebServer_createClass(CodDicomWebServer, [{
2049
2083
  key: "addFileUrl",
2050
- value: function addFileUrl(seriesInstanceUID, url) {
2084
+ value: function addFileUrl(seriesInstanceUID, type, url) {
2051
2085
  if (this.seriesUidFileUrls[seriesInstanceUID]) {
2052
- this.seriesUidFileUrls[seriesInstanceUID].push(url);
2086
+ this.seriesUidFileUrls[seriesInstanceUID].add({
2087
+ type: type,
2088
+ url: url
2089
+ });
2053
2090
  } else {
2054
- this.seriesUidFileUrls[seriesInstanceUID] = [url];
2091
+ this.seriesUidFileUrls[seriesInstanceUID] = new Set([{
2092
+ type: type,
2093
+ url: url
2094
+ }]);
2055
2095
  }
2056
2096
  }
2057
2097
  }, {
@@ -2132,7 +2172,7 @@ var CodDicomWebServer = /*#__PURE__*/function () {
2132
2172
  }
2133
2173
  throw new CustomError("Thumbnail not found for ".concat(wadorsUrl));
2134
2174
  case 19:
2135
- this.addFileUrl(seriesInstanceUID, thumbnailUrl);
2175
+ this.addFileUrl(seriesInstanceUID, URLType.THUMBNAIL, thumbnailUrl);
2136
2176
  return _context.abrupt("return", this.fetchFile(thumbnailUrl, headers, {
2137
2177
  useSharedArrayBuffer: useSharedArrayBuffer
2138
2178
  }));
@@ -2147,7 +2187,7 @@ var CodDicomWebServer = /*#__PURE__*/function () {
2147
2187
  if (fetchType === FetchType.BYTES_OPTIMIZED) {
2148
2188
  urlWithBytes = "".concat(fileUrl, "?bytes=").concat(startByte, "-").concat(endByte);
2149
2189
  }
2150
- this.addFileUrl(seriesInstanceUID, fileUrl);
2190
+ this.addFileUrl(seriesInstanceUID, URLType.FILE, fileUrl);
2151
2191
  return _context.abrupt("return", this.fetchFile(urlWithBytes, headers, {
2152
2192
  offsets: {
2153
2193
  startByte: startByte,
@@ -2194,7 +2234,7 @@ var CodDicomWebServer = /*#__PURE__*/function () {
2194
2234
  var dataSet = (0,dicomParser_min.parseDicom)(new Uint8Array(result));
2195
2235
  var _seriesInstanceUID = dataSet.string('0020000e');
2196
2236
  if (_seriesInstanceUID) {
2197
- _this2.addFileUrl(_seriesInstanceUID, wadorsUrl);
2237
+ _this2.addFileUrl(_seriesInstanceUID, URLType.OTHERS, wadorsUrl);
2198
2238
  }
2199
2239
  } catch (error) {
2200
2240
  console.warn('CodDicomWebServer.ts: There is some issue parsing the file.', error);
@@ -2422,14 +2462,30 @@ var CodDicomWebServer = /*#__PURE__*/function () {
2422
2462
  }
2423
2463
  return fetchFile;
2424
2464
  }()
2465
+ }, {
2466
+ key: "downloadSeriesFile",
2467
+ value: function downloadSeriesFile(seriesInstanceUID) {
2468
+ var _Array$from$find;
2469
+ var seriesFileURL = (_Array$from$find = Array.from(this.seriesUidFileUrls[seriesInstanceUID]).find(function (_ref3) {
2470
+ var url = _ref3.url,
2471
+ type = _ref3.type;
2472
+ return type === URLType.FILE && url.endsWith('.tar');
2473
+ })) === null || _Array$from$find === void 0 ? void 0 : _Array$from$find.url;
2474
+ if (seriesFileURL) {
2475
+ var seriesArrayBuffer = this.fileManager.get(seriesFileURL);
2476
+ return download(seriesFileURL.split('/').at(-1), seriesArrayBuffer);
2477
+ }
2478
+ return false;
2479
+ }
2425
2480
  }, {
2426
2481
  key: "delete",
2427
2482
  value: function _delete(seriesInstanceUID) {
2428
2483
  var _this4 = this;
2429
2484
  var fileUrls = this.seriesUidFileUrls[seriesInstanceUID];
2430
2485
  if (fileUrls) {
2431
- fileUrls.forEach(function (fileUrl) {
2432
- _this4.fileManager.remove(fileUrl);
2486
+ fileUrls.forEach(function (_ref4) {
2487
+ var url = _ref4.url;
2488
+ _this4.fileManager.remove(url);
2433
2489
  });
2434
2490
  }
2435
2491
  delete this.seriesUidFileUrls[seriesInstanceUID];
@@ -2439,8 +2495,9 @@ var CodDicomWebServer = /*#__PURE__*/function () {
2439
2495
  value: function deleteAll() {
2440
2496
  var _this5 = this;
2441
2497
  Object.values(this.seriesUidFileUrls).forEach(function (fileUrls) {
2442
- fileUrls.forEach(function (fileUrl) {
2443
- _this5.fileManager.remove(fileUrl);
2498
+ fileUrls.forEach(function (_ref5) {
2499
+ var url = _ref5.url;
2500
+ _this5.fileManager.remove(url);
2444
2501
  });
2445
2502
  });
2446
2503
  this.seriesUidFileUrls = {};
@@ -2450,10 +2507,10 @@ var CodDicomWebServer = /*#__PURE__*/function () {
2450
2507
  value: function parseMetadata(metadata, type, sopInstanceUID) {
2451
2508
  if (type === RequestType.INSTANCE_METADATA) {
2452
2509
  var _Object$entries$find;
2453
- return (_Object$entries$find = Object.entries(metadata.cod.instances).find(function (_ref3) {
2454
- var _ref4 = CodDicomWebServer_slicedToArray(_ref3, 2),
2455
- key = _ref4[0],
2456
- instance = _ref4[1];
2510
+ return (_Object$entries$find = Object.entries(metadata.cod.instances).find(function (_ref6) {
2511
+ var _ref7 = CodDicomWebServer_slicedToArray(_ref6, 2),
2512
+ key = _ref7[0],
2513
+ instance = _ref7[1];
2457
2514
  return key === sopInstanceUID;
2458
2515
  })) === null || _Object$entries$find === void 0 ? void 0 : _Object$entries$find[1].metadata;
2459
2516
  } else {
@@ -14,9 +14,10 @@ declare class CodDicomWebServer {
14
14
  });
15
15
  setOptions: (newOptions: Partial<CodDicomWebServerOptions>) => void;
16
16
  getOptions: () => CodDicomWebServerOptions;
17
- addFileUrl(seriesInstanceUID: string, url: string): void;
17
+ addFileUrl(seriesInstanceUID: string, type: Enums.URLType, url: string): void;
18
18
  fetchCod(wadorsUrl: string, headers?: Record<string, string> | undefined, { useSharedArrayBuffer, fetchType }?: CODRequestOptions): Promise<ArrayBufferLike | InstanceMetadata | SeriesMetadata | undefined>;
19
19
  fetchFile(fileUrl: string, headers: Record<string, string>, { offsets, useSharedArrayBuffer, fetchType }?: FileRequestOptions): Promise<ArrayBufferLike | undefined>;
20
+ downloadSeriesFile(seriesInstanceUID: string): boolean;
20
21
  delete(seriesInstanceUID: string): void;
21
22
  deleteAll(): void;
22
23
  parseMetadata(metadata: JsonMetadata, type: Enums.RequestType, sopInstanceUID: string): InstanceMetadata | SeriesMetadata;
@@ -7,7 +7,7 @@ import constants, { Enums } from '../constants';
7
7
  import { getDataRetrievalManager } from '../dataRetrieval/dataRetrievalManager';
8
8
  import { CustomError } from './customClasses';
9
9
  import { CustomErrorEvent } from './customClasses';
10
- import { getDirectoryHandle } from '../fileAccessSystemUtils';
10
+ import { download, getDirectoryHandle } from '../fileAccessSystemUtils';
11
11
  class CodDicomWebServer {
12
12
  filePromises = {};
13
13
  options = {
@@ -43,12 +43,12 @@ class CodDicomWebServer {
43
43
  getOptions = () => {
44
44
  return this.options;
45
45
  };
46
- addFileUrl(seriesInstanceUID, url) {
46
+ addFileUrl(seriesInstanceUID, type, url) {
47
47
  if (this.seriesUidFileUrls[seriesInstanceUID]) {
48
- this.seriesUidFileUrls[seriesInstanceUID].push(url);
48
+ this.seriesUidFileUrls[seriesInstanceUID].add({ type, url });
49
49
  }
50
50
  else {
51
- this.seriesUidFileUrls[seriesInstanceUID] = [url];
51
+ this.seriesUidFileUrls[seriesInstanceUID] = new Set([{ type, url }]);
52
52
  }
53
53
  }
54
54
  async fetchCod(wadorsUrl, headers = {}, { useSharedArrayBuffer = false, fetchType = constants.Enums.FetchType.API_OPTIMIZED } = {}) {
@@ -79,7 +79,7 @@ class CodDicomWebServer {
79
79
  if (!thumbnailUrl) {
80
80
  throw new CustomError(`Thumbnail not found for ${wadorsUrl}`);
81
81
  }
82
- this.addFileUrl(seriesInstanceUID, thumbnailUrl);
82
+ this.addFileUrl(seriesInstanceUID, Enums.URLType.THUMBNAIL, thumbnailUrl);
83
83
  return this.fetchFile(thumbnailUrl, headers, {
84
84
  useSharedArrayBuffer
85
85
  });
@@ -91,7 +91,7 @@ class CodDicomWebServer {
91
91
  if (fetchType === Enums.FetchType.BYTES_OPTIMIZED) {
92
92
  urlWithBytes = `${fileUrl}?bytes=${startByte}-${endByte}`;
93
93
  }
94
- this.addFileUrl(seriesInstanceUID, fileUrl);
94
+ this.addFileUrl(seriesInstanceUID, Enums.URLType.FILE, fileUrl);
95
95
  return this.fetchFile(urlWithBytes, headers, {
96
96
  offsets: { startByte, endByte },
97
97
  useSharedArrayBuffer,
@@ -134,7 +134,7 @@ class CodDicomWebServer {
134
134
  const dataSet = parseDicom(new Uint8Array(result));
135
135
  const seriesInstanceUID = dataSet.string('0020000e');
136
136
  if (seriesInstanceUID) {
137
- this.addFileUrl(seriesInstanceUID, wadorsUrl);
137
+ this.addFileUrl(seriesInstanceUID, Enums.URLType.OTHERS, wadorsUrl);
138
138
  }
139
139
  }
140
140
  catch (error) {
@@ -299,19 +299,27 @@ class CodDicomWebServer {
299
299
  });
300
300
  });
301
301
  }
302
+ downloadSeriesFile(seriesInstanceUID) {
303
+ const seriesFileURL = Array.from(this.seriesUidFileUrls[seriesInstanceUID]).find(({ url, type }) => type === Enums.URLType.FILE && url.endsWith('.tar'))?.url;
304
+ if (seriesFileURL) {
305
+ const seriesArrayBuffer = this.fileManager.get(seriesFileURL);
306
+ return download(seriesFileURL.split('/').at(-1), seriesArrayBuffer);
307
+ }
308
+ return false;
309
+ }
302
310
  delete(seriesInstanceUID) {
303
311
  const fileUrls = this.seriesUidFileUrls[seriesInstanceUID];
304
312
  if (fileUrls) {
305
- fileUrls.forEach((fileUrl) => {
306
- this.fileManager.remove(fileUrl);
313
+ fileUrls.forEach(({ url }) => {
314
+ this.fileManager.remove(url);
307
315
  });
308
316
  }
309
317
  delete this.seriesUidFileUrls[seriesInstanceUID];
310
318
  }
311
319
  deleteAll() {
312
320
  Object.values(this.seriesUidFileUrls).forEach((fileUrls) => {
313
- fileUrls.forEach((fileUrl) => {
314
- this.fileManager.remove(fileUrl);
321
+ fileUrls.forEach(({ url }) => {
322
+ this.fileManager.remove(url);
315
323
  });
316
324
  });
317
325
  this.seriesUidFileUrls = {};
@@ -19,3 +19,8 @@ export declare enum DataRetrieveMode {
19
19
  WORKER = 0,
20
20
  REQUEST = 1
21
21
  }
22
+ export declare enum URLType {
23
+ THUMBNAIL = 0,
24
+ FILE = 1,
25
+ OTHERS = 2
26
+ }
@@ -22,3 +22,9 @@ export var DataRetrieveMode;
22
22
  DataRetrieveMode[DataRetrieveMode["WORKER"] = 0] = "WORKER";
23
23
  DataRetrieveMode[DataRetrieveMode["REQUEST"] = 1] = "REQUEST";
24
24
  })(DataRetrieveMode || (DataRetrieveMode = {}));
25
+ export var URLType;
26
+ (function (URLType) {
27
+ URLType[URLType["THUMBNAIL"] = 0] = "THUMBNAIL";
28
+ URLType[URLType["FILE"] = 1] = "FILE";
29
+ URLType[URLType["OTHERS"] = 2] = "OTHERS";
30
+ })(URLType || (URLType = {}));
@@ -4,6 +4,7 @@ export declare function readFile(directoryHandle: FileSystemDirectoryHandle, nam
4
4
  endByte: number;
5
5
  }): Promise<ArrayBuffer>;
6
6
  export declare function writeFile(directoryHandle: FileSystemDirectoryHandle, name: string, file: ArrayBuffer): Promise<void>;
7
+ export declare function download(fileName: string, file: ArrayBuffer): boolean;
7
8
  export declare function clearPartialFiles(): Promise<void>;
8
9
  export declare function createStreamingFileName(url: string): string;
9
10
  export declare function createPartialFileName(url: string, offsets?: {
@@ -66,6 +66,22 @@ export async function writeFile(directoryHandle, name, file) {
66
66
  console.warn(`Error writing the file ${name}: ${error.message}`);
67
67
  }
68
68
  }
69
+ export function download(fileName, file) {
70
+ try {
71
+ const blob = new Blob([file], { type: 'application/x-tar' });
72
+ const url = URL.createObjectURL(blob);
73
+ const a = document.createElement('a');
74
+ a.href = url;
75
+ a.download = fileName;
76
+ a.click();
77
+ URL.revokeObjectURL(url);
78
+ return true;
79
+ }
80
+ catch (error) {
81
+ console.warn(`Error downloading file - ${fileName}: ` + error.message);
82
+ return false;
83
+ }
84
+ }
69
85
  export async function clearPartialFiles() {
70
86
  try {
71
87
  await directoryHandle.removeEntry(FILE_SYSTEM_ROUTES.Partial, { recursive: true });
@@ -2,7 +2,7 @@ import type { JsonMetadata, MetadataUrlCreationParams } from './types';
2
2
  declare class MetadataManager {
3
3
  private metadataPromises;
4
4
  constructor();
5
- addDeidMetadata(jsonMetadata: JsonMetadata): void;
5
+ addDeidMetadata(jsonMetadata: JsonMetadata, url: string): void;
6
6
  getMetadataFromCache(url: string): Promise<JsonMetadata>;
7
7
  getMetadata(params: MetadataUrlCreationParams, headers: Record<string, string>): Promise<JsonMetadata | null>;
8
8
  }
@@ -3,17 +3,18 @@ import { createMetadataJsonUrl } from './classes/utils';
3
3
  class MetadataManager {
4
4
  metadataPromises = {};
5
5
  constructor() { }
6
- addDeidMetadata(jsonMetadata) {
7
- const { deid_study_uid, deid_series_uid, cod } = jsonMetadata;
8
- if (!cod || !deid_study_uid || !deid_series_uid) {
6
+ addDeidMetadata(jsonMetadata, url) {
7
+ const { cod } = jsonMetadata;
8
+ const [studyUID, _, seriesUID] = url.match(/studies\/(.*?)\/metadata/)?.[1].split('/');
9
+ if (!cod || !studyUID || !seriesUID) {
9
10
  console.warn('Missing required metadata properties: cod, deid_study_uid, or deid_series_uid');
10
11
  return;
11
12
  }
12
- for (const deid_sop_uid in cod.instances) {
13
- const instance = cod.instances[deid_sop_uid];
14
- instance.metadata.DeidStudyInstanceUID = { Value: [deid_study_uid] };
15
- instance.metadata.DeidSeriesInstanceUID = { Value: [deid_series_uid] };
16
- instance.metadata.DeidSopInstanceUID = { Value: [deid_sop_uid] };
13
+ for (const sopUID in cod.instances) {
14
+ const instance = cod.instances[sopUID];
15
+ instance.metadata.DeidStudyInstanceUID = { Value: [studyUID] };
16
+ instance.metadata.DeidSeriesInstanceUID = { Value: [seriesUID] };
17
+ instance.metadata.DeidSopInstanceUID = { Value: [sopUID] };
17
18
  }
18
19
  }
19
20
  getMetadataFromCache(url) {
@@ -37,7 +38,7 @@ class MetadataManager {
37
38
  return response.json();
38
39
  })
39
40
  .then((data) => {
40
- this.addDeidMetadata(data);
41
+ this.addDeidMetadata(data, url);
41
42
  return data;
42
43
  });
43
44
  return await this.metadataPromises[url];
package/dist/umd/563.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /*!
2
2
  *
3
- * cod-dicomweb-server v1.3.4
3
+ * cod-dicomweb-server v1.3.7
4
4
  * git+https://github.com/gradienthealth/cod-dicomweb-server.git
5
5
  *
6
6
  * Copyright (c) Adithyan Dinesh and project contributors.