@ubercode/dcmtk 0.11.1 → 0.12.1

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/index.d.cts CHANGED
@@ -3,7 +3,7 @@ export { L as LineSource, P as ProcessLine, a as ResultValue, b as assertUnreach
3
3
  import { A as AETitle, D as DicomTag, a as DicomTagPath, P as Port, S as SOPClassUID, T as TransferSyntaxUID, b as DicomDataset } from './DicomInstance-CxLKC-oM.cjs';
4
4
  export { B as Brand, C as ChangeSet, c as DicomFilePath, d as DicomInstance, e as DicomOpenOptions, W as WalkTagEntry, f as WalkTagsOptions, g as createAETitle, h as createDicomFilePath, i as createDicomTag, j as createDicomTagPath, k as createPort, l as createSOPClassUID, m as createTransferSyntaxUID, t as tag, w as walkTags } from './DicomInstance-CxLKC-oM.cjs';
5
5
  import { z } from 'zod';
6
- export { A as AssociationAcknowledgedData, a as AssociationCompleteData, b as AssociationContext, c as AssociationReceivedData, d as AssociationSummary, e as AssociationTracker, C as CStoreRequestData, f as CannotStartListenerData, g as ConfigErrorData, D as DCMPRSCP_FATAL_EVENTS, h as DCMPRSCP_PATTERNS, i as DCMPSRCV_FATAL_EVENTS, j as DCMPSRCV_PATTERNS, k as DCMQRSCP_FATAL_EVENTS, l as DCMQRSCP_PATTERNS, m as DCMRECV_FATAL_EVENTS, n as DCMRECV_PATTERNS, o as DatabaseReadyData, p as DcmQRSCP, q as DcmQRSCPEventMap, r as DcmQRSCPOptions, s as DcmprsCP, t as DcmprsCPEventMap, u as DcmprsCPOptions, v as DcmprscpEvent, w as DcmprscpEventValue, x as Dcmpsrcv, y as DcmpsrcvEvent, z as DcmpsrcvEventMap, B as DcmpsrcvEventValue, E as DcmpsrcvOptions, F as DcmqrscpEvent, G as DcmqrscpEventValue, H as Dcmrecv, I as DcmrecvEvent, J as DcmrecvEventMap, K as DcmrecvEventValue, L as DcmrecvOptions, M as DcmtkProcess, N as DcmtkProcessConfig, O as DcmtkProcessEventMap, P as DicomReceiver, Q as DicomReceiverEventMap, R as DicomReceiverOptions, S as EventPattern, T as FileDeletedData, U as FileReceivedData, V as FilenameMode, W as FilenameModeValue, X as LineParser, Y as LineParserEventMap, Z as MultiLineConfig, _ as PoolAssociationReceivedData, $ as PoolCStoreRequestData, a0 as PoolEchoRequestData, a1 as PoolRefusingAssociationData, a2 as PoolStatus, a3 as PreferredTransferSyntax, a4 as PreferredTransferSyntaxValue, a5 as PrintAssociationAcknowledgedData, a6 as PrintAssociationReceivedData, a7 as PrintCannotStartListenerData, a8 as ProcessState, a9 as ProcessStateValue, aa as QRAssociationAcknowledgedData, ab as QRAssociationReceivedData, ac as QRCFindRequestData, ad as QRCGetRequestData, ae as QRCMoveRequestData, af as QRCStoreRequestData, ag as QRCannotStartListenerData, ah as QRListeningData, ai as ReceiverAssociationAcknowledgedData, aj as ReceiverAssociationData, ak as ReceiverAssociationReceivedData, al as ReceiverCStoreRequestData, am as ReceiverCannotStartListenerData, an as ReceiverConfigErrorData, ao as ReceiverDatabaseReadyData, ap as ReceiverEchoRequestData, aq as ReceiverErrorData, ar as ReceiverFileData, as as ReceiverFileReceivedData, at as ReceiverFileStoredData, au as ReceiverInstanceData, av as ReceiverListeningData, aw as RefusingAssociationData, ax as STORESCP_FATAL_EVENTS, ay as STORESCP_PATTERNS, az as StorageMode, aA as StorageModeValue, aB as StoreSCP, aC as StoreSCPEventMap, aD as StoreSCPOptions, aE as StoreSCPPreset, aF as StoreSCPPresetName, aG as StoredFileData, aH as StorescpEvent, aI as StorescpEventValue, aJ as StoringFileData, aK as SubdirectoryCreatedData, aL as SubdirectoryMode, aM as SubdirectoryModeValue, aN as TrackedFile, aO as WLMSCPFS_FATAL_EVENTS, aP as WLMSCPFS_PATTERNS, aQ as WlmAssociationAcknowledgedData, aR as WlmAssociationReceivedData, aS as WlmCFindRequestData, aT as WlmCannotStartListenerData, aU as WlmListeningData, aV as Wlmscpfs, aW as WlmscpfsEvent, aX as WlmscpfsEventMap, aY as WlmscpfsEventValue, aZ as WlmscpfsOptions } from './index-CVDMaxd8.cjs';
6
+ export { A as AssociationAcknowledgedData, a as AssociationCompleteData, b as AssociationContext, c as AssociationReceivedData, d as AssociationSummary, e as AssociationTracker, C as CStoreRequestData, f as CannotStartListenerData, g as ConfigErrorData, D as DCMPRSCP_FATAL_EVENTS, h as DCMPRSCP_PATTERNS, i as DCMPSRCV_FATAL_EVENTS, j as DCMPSRCV_PATTERNS, k as DCMQRSCP_FATAL_EVENTS, l as DCMQRSCP_PATTERNS, m as DCMRECV_FATAL_EVENTS, n as DCMRECV_PATTERNS, o as DatabaseReadyData, p as DcmQRSCP, q as DcmQRSCPEventMap, r as DcmQRSCPOptions, s as DcmprsCP, t as DcmprsCPEventMap, u as DcmprsCPOptions, v as DcmprscpEvent, w as DcmprscpEventValue, x as Dcmpsrcv, y as DcmpsrcvEvent, z as DcmpsrcvEventMap, B as DcmpsrcvEventValue, E as DcmpsrcvOptions, F as DcmqrscpEvent, G as DcmqrscpEventValue, H as Dcmrecv, I as DcmrecvEvent, J as DcmrecvEventMap, K as DcmrecvEventValue, L as DcmrecvOptions, M as DcmtkProcess, N as DcmtkProcessConfig, O as DcmtkProcessEventMap, P as DicomReceiver, Q as DicomReceiverEventMap, R as DicomReceiverOptions, S as EventPattern, T as FileDeletedData, U as FileReceivedData, V as FilenameMode, W as FilenameModeValue, X as LineParser, Y as LineParserEventMap, Z as MultiLineConfig, _ as PoolAssociationReceivedData, $ as PoolCStoreRequestData, a0 as PoolEchoRequestData, a1 as PoolRefusingAssociationData, a2 as PoolStatus, a3 as PreferredTransferSyntax, a4 as PreferredTransferSyntaxValue, a5 as PrintAssociationAcknowledgedData, a6 as PrintAssociationReceivedData, a7 as PrintCannotStartListenerData, a8 as ProcessState, a9 as ProcessStateValue, aa as QRAssociationAcknowledgedData, ab as QRAssociationReceivedData, ac as QRCFindRequestData, ad as QRCGetRequestData, ae as QRCMoveRequestData, af as QRCStoreRequestData, ag as QRCannotStartListenerData, ah as QRListeningData, ai as ReceiverAssociationAcknowledgedData, aj as ReceiverAssociationData, ak as ReceiverAssociationFinalizedData, al as ReceiverAssociationReceivedData, am as ReceiverCStoreRequestData, an as ReceiverCannotStartListenerData, ao as ReceiverConfigErrorData, ap as ReceiverDatabaseReadyData, aq as ReceiverEchoRequestData, ar as ReceiverErrorData, as as ReceiverFileData, at as ReceiverFileReceivedData, au as ReceiverFileStoredData, av as ReceiverInstanceData, aw as ReceiverInstanceErrorData, ax as ReceiverListeningData, ay as RefusingAssociationData, az as STORESCP_FATAL_EVENTS, aA as STORESCP_PATTERNS, aB as StorageMode, aC as StorageModeValue, aD as StoreSCP, aE as StoreSCPEventMap, aF as StoreSCPOptions, aG as StoreSCPPreset, aH as StoreSCPPresetName, aI as StoredFileData, aJ as StorescpEvent, aK as StorescpEventValue, aL as StoringFileData, aM as SubdirectoryCreatedData, aN as SubdirectoryMode, aO as SubdirectoryModeValue, aP as TrackedFile, aQ as WLMSCPFS_FATAL_EVENTS, aR as WLMSCPFS_PATTERNS, aS as WlmAssociationAcknowledgedData, aT as WlmAssociationReceivedData, aU as WlmCFindRequestData, aV as WlmCannotStartListenerData, aW as WlmListeningData, aX as Wlmscpfs, aY as WlmscpfsEvent, aZ as WlmscpfsEventMap, a_ as WlmscpfsEventValue, a$ as WlmscpfsOptions } from './index-DV8HaHEX.cjs';
7
7
  import { T as TagModification } from './dcmodify-Cf-RPHF3.cjs';
8
8
  export { b as DcmodifyOptions, c as DcmodifyResult, D as DicomJsonElement, a as DicomJsonModel, d as ToolBaseOptions, e as dcmodify, x as xmlToJson } from './dcmodify-Cf-RPHF3.cjs';
9
9
  export { DictionaryEntry, SOPClassName, SOP_CLASSES, TagSegment, VR, VRCategoryName, VRMetadata, VRValue, VR_CATEGORY, VR_CATEGORY_NAME, VR_META, getVRCategory, isBinaryVR, isNumericVR, isStringVR, lookupTag, lookupTagByKeyword, lookupTagByName, segmentsToModifyPath, segmentsToString, sopClassNameFromUID, tagPathToSegments } from './dicom.cjs';
package/dist/index.d.ts CHANGED
@@ -3,7 +3,7 @@ export { L as LineSource, P as ProcessLine, a as ResultValue, b as assertUnreach
3
3
  import { A as AETitle, D as DicomTag, a as DicomTagPath, P as Port, S as SOPClassUID, T as TransferSyntaxUID, b as DicomDataset } from './DicomInstance-BKUiir0G.js';
4
4
  export { B as Brand, C as ChangeSet, c as DicomFilePath, d as DicomInstance, e as DicomOpenOptions, W as WalkTagEntry, f as WalkTagsOptions, g as createAETitle, h as createDicomFilePath, i as createDicomTag, j as createDicomTagPath, k as createPort, l as createSOPClassUID, m as createTransferSyntaxUID, t as tag, w as walkTags } from './DicomInstance-BKUiir0G.js';
5
5
  import { z } from 'zod';
6
- export { A as AssociationAcknowledgedData, a as AssociationCompleteData, b as AssociationContext, c as AssociationReceivedData, d as AssociationSummary, e as AssociationTracker, C as CStoreRequestData, f as CannotStartListenerData, g as ConfigErrorData, D as DCMPRSCP_FATAL_EVENTS, h as DCMPRSCP_PATTERNS, i as DCMPSRCV_FATAL_EVENTS, j as DCMPSRCV_PATTERNS, k as DCMQRSCP_FATAL_EVENTS, l as DCMQRSCP_PATTERNS, m as DCMRECV_FATAL_EVENTS, n as DCMRECV_PATTERNS, o as DatabaseReadyData, p as DcmQRSCP, q as DcmQRSCPEventMap, r as DcmQRSCPOptions, s as DcmprsCP, t as DcmprsCPEventMap, u as DcmprsCPOptions, v as DcmprscpEvent, w as DcmprscpEventValue, x as Dcmpsrcv, y as DcmpsrcvEvent, z as DcmpsrcvEventMap, B as DcmpsrcvEventValue, E as DcmpsrcvOptions, F as DcmqrscpEvent, G as DcmqrscpEventValue, H as Dcmrecv, I as DcmrecvEvent, J as DcmrecvEventMap, K as DcmrecvEventValue, L as DcmrecvOptions, M as DcmtkProcess, N as DcmtkProcessConfig, O as DcmtkProcessEventMap, P as DicomReceiver, Q as DicomReceiverEventMap, R as DicomReceiverOptions, S as EventPattern, T as FileDeletedData, U as FileReceivedData, V as FilenameMode, W as FilenameModeValue, X as LineParser, Y as LineParserEventMap, Z as MultiLineConfig, _ as PoolAssociationReceivedData, $ as PoolCStoreRequestData, a0 as PoolEchoRequestData, a1 as PoolRefusingAssociationData, a2 as PoolStatus, a3 as PreferredTransferSyntax, a4 as PreferredTransferSyntaxValue, a5 as PrintAssociationAcknowledgedData, a6 as PrintAssociationReceivedData, a7 as PrintCannotStartListenerData, a8 as ProcessState, a9 as ProcessStateValue, aa as QRAssociationAcknowledgedData, ab as QRAssociationReceivedData, ac as QRCFindRequestData, ad as QRCGetRequestData, ae as QRCMoveRequestData, af as QRCStoreRequestData, ag as QRCannotStartListenerData, ah as QRListeningData, ai as ReceiverAssociationAcknowledgedData, aj as ReceiverAssociationData, ak as ReceiverAssociationReceivedData, al as ReceiverCStoreRequestData, am as ReceiverCannotStartListenerData, an as ReceiverConfigErrorData, ao as ReceiverDatabaseReadyData, ap as ReceiverEchoRequestData, aq as ReceiverErrorData, ar as ReceiverFileData, as as ReceiverFileReceivedData, at as ReceiverFileStoredData, au as ReceiverInstanceData, av as ReceiverListeningData, aw as RefusingAssociationData, ax as STORESCP_FATAL_EVENTS, ay as STORESCP_PATTERNS, az as StorageMode, aA as StorageModeValue, aB as StoreSCP, aC as StoreSCPEventMap, aD as StoreSCPOptions, aE as StoreSCPPreset, aF as StoreSCPPresetName, aG as StoredFileData, aH as StorescpEvent, aI as StorescpEventValue, aJ as StoringFileData, aK as SubdirectoryCreatedData, aL as SubdirectoryMode, aM as SubdirectoryModeValue, aN as TrackedFile, aO as WLMSCPFS_FATAL_EVENTS, aP as WLMSCPFS_PATTERNS, aQ as WlmAssociationAcknowledgedData, aR as WlmAssociationReceivedData, aS as WlmCFindRequestData, aT as WlmCannotStartListenerData, aU as WlmListeningData, aV as Wlmscpfs, aW as WlmscpfsEvent, aX as WlmscpfsEventMap, aY as WlmscpfsEventValue, aZ as WlmscpfsOptions } from './index--dDQfutR.js';
6
+ export { A as AssociationAcknowledgedData, a as AssociationCompleteData, b as AssociationContext, c as AssociationReceivedData, d as AssociationSummary, e as AssociationTracker, C as CStoreRequestData, f as CannotStartListenerData, g as ConfigErrorData, D as DCMPRSCP_FATAL_EVENTS, h as DCMPRSCP_PATTERNS, i as DCMPSRCV_FATAL_EVENTS, j as DCMPSRCV_PATTERNS, k as DCMQRSCP_FATAL_EVENTS, l as DCMQRSCP_PATTERNS, m as DCMRECV_FATAL_EVENTS, n as DCMRECV_PATTERNS, o as DatabaseReadyData, p as DcmQRSCP, q as DcmQRSCPEventMap, r as DcmQRSCPOptions, s as DcmprsCP, t as DcmprsCPEventMap, u as DcmprsCPOptions, v as DcmprscpEvent, w as DcmprscpEventValue, x as Dcmpsrcv, y as DcmpsrcvEvent, z as DcmpsrcvEventMap, B as DcmpsrcvEventValue, E as DcmpsrcvOptions, F as DcmqrscpEvent, G as DcmqrscpEventValue, H as Dcmrecv, I as DcmrecvEvent, J as DcmrecvEventMap, K as DcmrecvEventValue, L as DcmrecvOptions, M as DcmtkProcess, N as DcmtkProcessConfig, O as DcmtkProcessEventMap, P as DicomReceiver, Q as DicomReceiverEventMap, R as DicomReceiverOptions, S as EventPattern, T as FileDeletedData, U as FileReceivedData, V as FilenameMode, W as FilenameModeValue, X as LineParser, Y as LineParserEventMap, Z as MultiLineConfig, _ as PoolAssociationReceivedData, $ as PoolCStoreRequestData, a0 as PoolEchoRequestData, a1 as PoolRefusingAssociationData, a2 as PoolStatus, a3 as PreferredTransferSyntax, a4 as PreferredTransferSyntaxValue, a5 as PrintAssociationAcknowledgedData, a6 as PrintAssociationReceivedData, a7 as PrintCannotStartListenerData, a8 as ProcessState, a9 as ProcessStateValue, aa as QRAssociationAcknowledgedData, ab as QRAssociationReceivedData, ac as QRCFindRequestData, ad as QRCGetRequestData, ae as QRCMoveRequestData, af as QRCStoreRequestData, ag as QRCannotStartListenerData, ah as QRListeningData, ai as ReceiverAssociationAcknowledgedData, aj as ReceiverAssociationData, ak as ReceiverAssociationFinalizedData, al as ReceiverAssociationReceivedData, am as ReceiverCStoreRequestData, an as ReceiverCannotStartListenerData, ao as ReceiverConfigErrorData, ap as ReceiverDatabaseReadyData, aq as ReceiverEchoRequestData, ar as ReceiverErrorData, as as ReceiverFileData, at as ReceiverFileReceivedData, au as ReceiverFileStoredData, av as ReceiverInstanceData, aw as ReceiverInstanceErrorData, ax as ReceiverListeningData, ay as RefusingAssociationData, az as STORESCP_FATAL_EVENTS, aA as STORESCP_PATTERNS, aB as StorageMode, aC as StorageModeValue, aD as StoreSCP, aE as StoreSCPEventMap, aF as StoreSCPOptions, aG as StoreSCPPreset, aH as StoreSCPPresetName, aI as StoredFileData, aJ as StorescpEvent, aK as StorescpEventValue, aL as StoringFileData, aM as SubdirectoryCreatedData, aN as SubdirectoryMode, aO as SubdirectoryModeValue, aP as TrackedFile, aQ as WLMSCPFS_FATAL_EVENTS, aR as WLMSCPFS_PATTERNS, aS as WlmAssociationAcknowledgedData, aT as WlmAssociationReceivedData, aU as WlmCFindRequestData, aV as WlmCannotStartListenerData, aW as WlmListeningData, aX as Wlmscpfs, aY as WlmscpfsEvent, aZ as WlmscpfsEventMap, a_ as WlmscpfsEventValue, a$ as WlmscpfsOptions } from './index-B5FQoIqM.js';
7
7
  import { T as TagModification } from './dcmodify-CHvwChFu.js';
8
8
  export { b as DcmodifyOptions, c as DcmodifyResult, D as DicomJsonElement, a as DicomJsonModel, d as ToolBaseOptions, e as dcmodify, x as xmlToJson } from './dcmodify-CHvwChFu.js';
9
9
  export { DictionaryEntry, SOPClassName, SOP_CLASSES, TagSegment, VR, VRCategoryName, VRMetadata, VRValue, VR_CATEGORY, VR_CATEGORY_NAME, VR_META, getVRCategory, isBinaryVR, isNumericVR, isStringVR, lookupTag, lookupTagByKeyword, lookupTagByName, segmentsToModifyPath, segmentsToString, sopClassNameFromUID, tagPathToSegments } from './dicom.js';
package/dist/index.js CHANGED
@@ -31377,7 +31377,12 @@ var parser = new XMLParser({
31377
31377
  ignoreAttributes: false,
31378
31378
  attributeNamePrefix: "@_",
31379
31379
  parseTagValue: false,
31380
- isArray: (name) => ARRAY_TAG_NAMES.has(name)
31380
+ isArray: (name) => ARRAY_TAG_NAMES.has(name),
31381
+ // DICOM XML does not use XML entities. Disable entity processing to avoid
31382
+ // the default expansion limit (1000) which rejects files with >1000 tags.
31383
+ // Without this, large studies fall through to dcm2json which hangs on
31384
+ // compressed pixel data (DCMTK bug).
31385
+ processEntities: false
31381
31386
  });
31382
31387
  function xmlToJson(xml) {
31383
31388
  try {
@@ -36459,6 +36464,9 @@ var Worker = class {
36459
36464
  __publicField(this, "_state", "idle");
36460
36465
  __publicField(this, "_context");
36461
36466
  __publicField(this, "_pending", /* @__PURE__ */ new Set());
36467
+ __publicField(this, "_instancePending", /* @__PURE__ */ new Set());
36468
+ __publicField(this, "_instancesReceived", 0);
36469
+ __publicField(this, "_instanceErrors", 0);
36462
36470
  __publicField(this, "_files", []);
36463
36471
  __publicField(this, "_fileSizes", []);
36464
36472
  __publicField(this, "_outputLines", []);
@@ -36496,6 +36504,9 @@ var Worker = class {
36496
36504
  this._fileSizes.length = 0;
36497
36505
  this._outputLines.length = 0;
36498
36506
  this._pending.clear();
36507
+ this._instancePending.clear();
36508
+ this._instancesReceived = 0;
36509
+ this._instanceErrors = 0;
36499
36510
  }
36500
36511
  /** Returns the worker to idle and clears all association state. */
36501
36512
  endAssociation() {
@@ -36505,6 +36516,9 @@ var Worker = class {
36505
36516
  this._fileSizes.length = 0;
36506
36517
  this._outputLines.length = 0;
36507
36518
  this._pending.clear();
36519
+ this._instancePending.clear();
36520
+ this._instancesReceived = 0;
36521
+ this._instanceErrors = 0;
36508
36522
  this._remoteSocket = void 0;
36509
36523
  this._workerSocket = void 0;
36510
36524
  }
@@ -36515,6 +36529,35 @@ var Worker = class {
36515
36529
  this._pending.delete(promise);
36516
36530
  });
36517
36531
  }
36532
+ /** Tracks an in-flight instance parsing promise; auto-removes on completion. */
36533
+ trackInstance(promise) {
36534
+ this._instancePending.add(promise);
36535
+ void promise.finally(() => {
36536
+ this._instancePending.delete(promise);
36537
+ });
36538
+ }
36539
+ /** Records a successful instance parse. */
36540
+ recordInstanceSuccess() {
36541
+ this._instancesReceived++;
36542
+ }
36543
+ /** Records a failed instance parse. */
36544
+ recordInstanceError() {
36545
+ this._instanceErrors++;
36546
+ }
36547
+ /** Awaits all in-flight instance parsing promises. */
36548
+ async drainInstancePending() {
36549
+ if (this._instancePending.size > 0) {
36550
+ await Promise.all(this._instancePending);
36551
+ }
36552
+ }
36553
+ /** Number of successfully parsed instances in this association. */
36554
+ get instancesReceived() {
36555
+ return this._instancesReceived;
36556
+ }
36557
+ /** Number of failed instance parses in this association. */
36558
+ get instanceErrors() {
36559
+ return this._instanceErrors;
36560
+ }
36518
36561
  /** Records a successfully received file path and its size. */
36519
36562
  recordFile(filePath, size) {
36520
36563
  this._files.push(filePath);
@@ -36686,7 +36729,16 @@ var DicomReceiver = class _DicomReceiver extends EventEmitter {
36686
36729
  return this.on("INSTANCE_RECEIVED", listener);
36687
36730
  }
36688
36731
  /**
36689
- * Registers a listener for completed associations.
36732
+ * Registers a listener for DicomInstance.open failures.
36733
+ *
36734
+ * @param listener - Callback receiving instance error data
36735
+ * @returns this for chaining
36736
+ */
36737
+ onInstanceError(listener) {
36738
+ return this.on("INSTANCE_ERROR", listener);
36739
+ }
36740
+ /**
36741
+ * Registers a listener for completed associations (file moves done).
36690
36742
  *
36691
36743
  * @param listener - Callback receiving association data
36692
36744
  * @returns this for chaining
@@ -36694,6 +36746,15 @@ var DicomReceiver = class _DicomReceiver extends EventEmitter {
36694
36746
  onAssociationComplete(listener) {
36695
36747
  return this.on("ASSOCIATION_COMPLETE", listener);
36696
36748
  }
36749
+ /**
36750
+ * Registers a listener for fully finalized associations (all parsing done).
36751
+ *
36752
+ * @param listener - Callback receiving finalized data with instance counts
36753
+ * @returns this for chaining
36754
+ */
36755
+ onAssociationFinalized(listener) {
36756
+ return this.on("ASSOCIATION_FINALIZED", listener);
36757
+ }
36697
36758
  /**
36698
36759
  * Registers a listener for new associations (bubbled from workers).
36699
36760
  *
@@ -37023,28 +37084,33 @@ var DicomReceiver = class _DicomReceiver extends EventEmitter {
37023
37084
  calledAE: data.calledAE,
37024
37085
  source: data.source
37025
37086
  });
37026
- this.emitInstanceReceived(finalPath, fileSize, data, ctx);
37027
- }
37028
- /** Parses a DICOM file and emits INSTANCE_RECEIVED or error. */
37029
- emitInstanceReceived(filePath, fileSize, data, ctx) {
37030
- const errorCtx = {
37031
- filePath,
37087
+ const instanceCtx = {
37088
+ filePath: finalPath,
37089
+ fileSize,
37032
37090
  associationId: ctx.associationId,
37033
37091
  associationDir: ctx.associationDir,
37034
37092
  callingAE: data.callingAE,
37035
37093
  calledAE: data.calledAE,
37036
37094
  source: data.source
37037
37095
  };
37038
- void DicomInstance.open(filePath).then((openResult) => {
37096
+ worker.trackInstance(this.parseAndEmitInstance(worker, instanceCtx));
37097
+ }
37098
+ /** Parses a DICOM file and emits INSTANCE_RECEIVED or INSTANCE_ERROR. */
37099
+ async parseAndEmitInstance(worker, ctx) {
37100
+ try {
37101
+ const openResult = await DicomInstance.open(ctx.filePath);
37039
37102
  if (!openResult.ok) {
37040
- this.emit("error", { error: openResult.error, ...errorCtx });
37103
+ worker.recordInstanceError();
37104
+ this.emit("INSTANCE_ERROR", { error: openResult.error, thrown: false, ...ctx });
37041
37105
  return;
37042
37106
  }
37043
- this.emit("INSTANCE_RECEIVED", { ...errorCtx, fileSize, instance: openResult.value });
37044
- }).catch((thrown) => {
37107
+ worker.recordInstanceSuccess();
37108
+ this.emit("INSTANCE_RECEIVED", { ...ctx, instance: openResult.value });
37109
+ } catch (thrown) {
37045
37110
  const error = thrown instanceof Error ? thrown : new Error(String(thrown));
37046
- this.emit("error", { error, ...errorCtx });
37047
- });
37111
+ worker.recordInstanceError();
37112
+ this.emit("INSTANCE_ERROR", { error, thrown: true, ...ctx });
37113
+ }
37048
37114
  }
37049
37115
  /** Returns worker to idle pool on association complete, emits summary. */
37050
37116
  wireAssociationComplete(worker) {
@@ -37052,10 +37118,12 @@ var DicomReceiver = class _DicomReceiver extends EventEmitter {
37052
37118
  void this.finalizeAssociation(worker, data);
37053
37119
  });
37054
37120
  }
37055
- /** Awaits ALL pending file operations, emits ASSOCIATION_COMPLETE, resets worker state. */
37121
+ /** Awaits file ops, emits ASSOCIATION_COMPLETE, awaits parsing, emits ASSOCIATION_FINALIZED. */
37056
37122
  async finalizeAssociation(worker, data) {
37057
37123
  await worker.drainPendingFiles();
37058
37124
  this.emitAssociationComplete(worker, data);
37125
+ await worker.drainInstancePending();
37126
+ this.emitAssociationFinalized(worker, data);
37059
37127
  worker.endAssociation();
37060
37128
  void this.scaleDown();
37061
37129
  }
@@ -37087,6 +37155,20 @@ var DicomReceiver = class _DicomReceiver extends EventEmitter {
37087
37155
  output
37088
37156
  });
37089
37157
  }
37158
+ /** Emits ASSOCIATION_FINALIZED after all instance parsing is done. */
37159
+ emitAssociationFinalized(worker, data) {
37160
+ const ctx = worker.context;
37161
+ this.emit("ASSOCIATION_FINALIZED", {
37162
+ associationId: ctx?.associationId ?? data.associationId,
37163
+ associationDir: ctx?.associationDir ?? "",
37164
+ callingAE: data.callingAE,
37165
+ calledAE: data.calledAE,
37166
+ source: data.source,
37167
+ files: [...worker.files],
37168
+ instancesReceived: worker.instancesReceived,
37169
+ instanceErrors: worker.instanceErrors
37170
+ });
37171
+ }
37090
37172
  /** Bubbles ASSOCIATION_RECEIVED from dcmrecv worker. */
37091
37173
  wireAssociationReceived(worker) {
37092
37174
  worker.dcmrecv.onEvent("ASSOCIATION_RECEIVED", (data) => {