@ubercode/dcmtk 0.11.1 → 0.12.0

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
@@ -36459,6 +36459,9 @@ var Worker = class {
36459
36459
  __publicField(this, "_state", "idle");
36460
36460
  __publicField(this, "_context");
36461
36461
  __publicField(this, "_pending", /* @__PURE__ */ new Set());
36462
+ __publicField(this, "_instancePending", /* @__PURE__ */ new Set());
36463
+ __publicField(this, "_instancesReceived", 0);
36464
+ __publicField(this, "_instanceErrors", 0);
36462
36465
  __publicField(this, "_files", []);
36463
36466
  __publicField(this, "_fileSizes", []);
36464
36467
  __publicField(this, "_outputLines", []);
@@ -36496,6 +36499,9 @@ var Worker = class {
36496
36499
  this._fileSizes.length = 0;
36497
36500
  this._outputLines.length = 0;
36498
36501
  this._pending.clear();
36502
+ this._instancePending.clear();
36503
+ this._instancesReceived = 0;
36504
+ this._instanceErrors = 0;
36499
36505
  }
36500
36506
  /** Returns the worker to idle and clears all association state. */
36501
36507
  endAssociation() {
@@ -36505,6 +36511,9 @@ var Worker = class {
36505
36511
  this._fileSizes.length = 0;
36506
36512
  this._outputLines.length = 0;
36507
36513
  this._pending.clear();
36514
+ this._instancePending.clear();
36515
+ this._instancesReceived = 0;
36516
+ this._instanceErrors = 0;
36508
36517
  this._remoteSocket = void 0;
36509
36518
  this._workerSocket = void 0;
36510
36519
  }
@@ -36515,6 +36524,35 @@ var Worker = class {
36515
36524
  this._pending.delete(promise);
36516
36525
  });
36517
36526
  }
36527
+ /** Tracks an in-flight instance parsing promise; auto-removes on completion. */
36528
+ trackInstance(promise) {
36529
+ this._instancePending.add(promise);
36530
+ void promise.finally(() => {
36531
+ this._instancePending.delete(promise);
36532
+ });
36533
+ }
36534
+ /** Records a successful instance parse. */
36535
+ recordInstanceSuccess() {
36536
+ this._instancesReceived++;
36537
+ }
36538
+ /** Records a failed instance parse. */
36539
+ recordInstanceError() {
36540
+ this._instanceErrors++;
36541
+ }
36542
+ /** Awaits all in-flight instance parsing promises. */
36543
+ async drainInstancePending() {
36544
+ if (this._instancePending.size > 0) {
36545
+ await Promise.all(this._instancePending);
36546
+ }
36547
+ }
36548
+ /** Number of successfully parsed instances in this association. */
36549
+ get instancesReceived() {
36550
+ return this._instancesReceived;
36551
+ }
36552
+ /** Number of failed instance parses in this association. */
36553
+ get instanceErrors() {
36554
+ return this._instanceErrors;
36555
+ }
36518
36556
  /** Records a successfully received file path and its size. */
36519
36557
  recordFile(filePath, size) {
36520
36558
  this._files.push(filePath);
@@ -36686,7 +36724,16 @@ var DicomReceiver = class _DicomReceiver extends EventEmitter {
36686
36724
  return this.on("INSTANCE_RECEIVED", listener);
36687
36725
  }
36688
36726
  /**
36689
- * Registers a listener for completed associations.
36727
+ * Registers a listener for DicomInstance.open failures.
36728
+ *
36729
+ * @param listener - Callback receiving instance error data
36730
+ * @returns this for chaining
36731
+ */
36732
+ onInstanceError(listener) {
36733
+ return this.on("INSTANCE_ERROR", listener);
36734
+ }
36735
+ /**
36736
+ * Registers a listener for completed associations (file moves done).
36690
36737
  *
36691
36738
  * @param listener - Callback receiving association data
36692
36739
  * @returns this for chaining
@@ -36694,6 +36741,15 @@ var DicomReceiver = class _DicomReceiver extends EventEmitter {
36694
36741
  onAssociationComplete(listener) {
36695
36742
  return this.on("ASSOCIATION_COMPLETE", listener);
36696
36743
  }
36744
+ /**
36745
+ * Registers a listener for fully finalized associations (all parsing done).
36746
+ *
36747
+ * @param listener - Callback receiving finalized data with instance counts
36748
+ * @returns this for chaining
36749
+ */
36750
+ onAssociationFinalized(listener) {
36751
+ return this.on("ASSOCIATION_FINALIZED", listener);
36752
+ }
36697
36753
  /**
36698
36754
  * Registers a listener for new associations (bubbled from workers).
36699
36755
  *
@@ -37023,28 +37079,33 @@ var DicomReceiver = class _DicomReceiver extends EventEmitter {
37023
37079
  calledAE: data.calledAE,
37024
37080
  source: data.source
37025
37081
  });
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,
37082
+ const instanceCtx = {
37083
+ filePath: finalPath,
37084
+ fileSize,
37032
37085
  associationId: ctx.associationId,
37033
37086
  associationDir: ctx.associationDir,
37034
37087
  callingAE: data.callingAE,
37035
37088
  calledAE: data.calledAE,
37036
37089
  source: data.source
37037
37090
  };
37038
- void DicomInstance.open(filePath).then((openResult) => {
37091
+ worker.trackInstance(this.parseAndEmitInstance(worker, instanceCtx));
37092
+ }
37093
+ /** Parses a DICOM file and emits INSTANCE_RECEIVED or INSTANCE_ERROR. */
37094
+ async parseAndEmitInstance(worker, ctx) {
37095
+ try {
37096
+ const openResult = await DicomInstance.open(ctx.filePath);
37039
37097
  if (!openResult.ok) {
37040
- this.emit("error", { error: openResult.error, ...errorCtx });
37098
+ worker.recordInstanceError();
37099
+ this.emit("INSTANCE_ERROR", { error: openResult.error, thrown: false, ...ctx });
37041
37100
  return;
37042
37101
  }
37043
- this.emit("INSTANCE_RECEIVED", { ...errorCtx, fileSize, instance: openResult.value });
37044
- }).catch((thrown) => {
37102
+ worker.recordInstanceSuccess();
37103
+ this.emit("INSTANCE_RECEIVED", { ...ctx, instance: openResult.value });
37104
+ } catch (thrown) {
37045
37105
  const error = thrown instanceof Error ? thrown : new Error(String(thrown));
37046
- this.emit("error", { error, ...errorCtx });
37047
- });
37106
+ worker.recordInstanceError();
37107
+ this.emit("INSTANCE_ERROR", { error, thrown: true, ...ctx });
37108
+ }
37048
37109
  }
37049
37110
  /** Returns worker to idle pool on association complete, emits summary. */
37050
37111
  wireAssociationComplete(worker) {
@@ -37052,10 +37113,12 @@ var DicomReceiver = class _DicomReceiver extends EventEmitter {
37052
37113
  void this.finalizeAssociation(worker, data);
37053
37114
  });
37054
37115
  }
37055
- /** Awaits ALL pending file operations, emits ASSOCIATION_COMPLETE, resets worker state. */
37116
+ /** Awaits file ops, emits ASSOCIATION_COMPLETE, awaits parsing, emits ASSOCIATION_FINALIZED. */
37056
37117
  async finalizeAssociation(worker, data) {
37057
37118
  await worker.drainPendingFiles();
37058
37119
  this.emitAssociationComplete(worker, data);
37120
+ await worker.drainInstancePending();
37121
+ this.emitAssociationFinalized(worker, data);
37059
37122
  worker.endAssociation();
37060
37123
  void this.scaleDown();
37061
37124
  }
@@ -37087,6 +37150,20 @@ var DicomReceiver = class _DicomReceiver extends EventEmitter {
37087
37150
  output
37088
37151
  });
37089
37152
  }
37153
+ /** Emits ASSOCIATION_FINALIZED after all instance parsing is done. */
37154
+ emitAssociationFinalized(worker, data) {
37155
+ const ctx = worker.context;
37156
+ this.emit("ASSOCIATION_FINALIZED", {
37157
+ associationId: ctx?.associationId ?? data.associationId,
37158
+ associationDir: ctx?.associationDir ?? "",
37159
+ callingAE: data.callingAE,
37160
+ calledAE: data.calledAE,
37161
+ source: data.source,
37162
+ files: [...worker.files],
37163
+ instancesReceived: worker.instancesReceived,
37164
+ instanceErrors: worker.instanceErrors
37165
+ });
37166
+ }
37090
37167
  /** Bubbles ASSOCIATION_RECEIVED from dcmrecv worker. */
37091
37168
  wireAssociationReceived(worker) {
37092
37169
  worker.dcmrecv.onEvent("ASSOCIATION_RECEIVED", (data) => {