@ubercode/dcmtk 0.11.0 → 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.
@@ -1544,6 +1544,30 @@ interface PoolEchoRequestData {
1544
1544
  interface PoolRefusingAssociationData {
1545
1545
  readonly reason: string;
1546
1546
  }
1547
+ /** Data emitted with INSTANCE_ERROR events when DicomInstance.open fails. */
1548
+ interface ReceiverInstanceErrorData {
1549
+ readonly error: Error;
1550
+ /** Whether this was a thrown exception (true) or a Result error (false). */
1551
+ readonly thrown: boolean;
1552
+ readonly filePath: string;
1553
+ readonly fileSize: number;
1554
+ readonly associationId: string;
1555
+ readonly associationDir: string;
1556
+ readonly callingAE: string;
1557
+ readonly calledAE: string;
1558
+ readonly source: string;
1559
+ }
1560
+ /** Data emitted with ASSOCIATION_FINALIZED — all work (including parsing) is done. */
1561
+ interface ReceiverAssociationFinalizedData {
1562
+ readonly associationId: string;
1563
+ readonly associationDir: string;
1564
+ readonly callingAE: string;
1565
+ readonly calledAE: string;
1566
+ readonly source: string;
1567
+ readonly files: readonly string[];
1568
+ readonly instancesReceived: number;
1569
+ readonly instanceErrors: number;
1570
+ }
1547
1571
  /** Data emitted with error events. */
1548
1572
  interface ReceiverErrorData {
1549
1573
  readonly error: Error;
@@ -1559,7 +1583,9 @@ interface DicomReceiverEventMap {
1559
1583
  FILE_RECEIVED: [ReceiverFileReceivedData];
1560
1584
  FILE_STORED: [ReceiverFileStoredData];
1561
1585
  INSTANCE_RECEIVED: [ReceiverInstanceData];
1586
+ INSTANCE_ERROR: [ReceiverInstanceErrorData];
1562
1587
  ASSOCIATION_COMPLETE: [ReceiverAssociationData];
1588
+ ASSOCIATION_FINALIZED: [ReceiverAssociationFinalizedData];
1563
1589
  ASSOCIATION_RECEIVED: [PoolAssociationReceivedData];
1564
1590
  C_STORE_REQUEST: [PoolCStoreRequestData];
1565
1591
  ECHO_REQUEST: [PoolEchoRequestData];
@@ -1682,12 +1708,26 @@ declare class DicomReceiver extends EventEmitter<DicomReceiverEventMap> {
1682
1708
  */
1683
1709
  onInstanceReceived(listener: (data: ReceiverInstanceData) => void): this;
1684
1710
  /**
1685
- * Registers a listener for completed associations.
1711
+ * Registers a listener for DicomInstance.open failures.
1712
+ *
1713
+ * @param listener - Callback receiving instance error data
1714
+ * @returns this for chaining
1715
+ */
1716
+ onInstanceError(listener: (data: ReceiverInstanceErrorData) => void): this;
1717
+ /**
1718
+ * Registers a listener for completed associations (file moves done).
1686
1719
  *
1687
1720
  * @param listener - Callback receiving association data
1688
1721
  * @returns this for chaining
1689
1722
  */
1690
1723
  onAssociationComplete(listener: (data: ReceiverAssociationData) => void): this;
1724
+ /**
1725
+ * Registers a listener for fully finalized associations (all parsing done).
1726
+ *
1727
+ * @param listener - Callback receiving finalized data with instance counts
1728
+ * @returns this for chaining
1729
+ */
1730
+ onAssociationFinalized(listener: (data: ReceiverAssociationFinalizedData) => void): this;
1691
1731
  /**
1692
1732
  * Registers a listener for new associations (bubbled from workers).
1693
1733
  *
@@ -1759,14 +1799,16 @@ declare class DicomReceiver extends EventEmitter<DicomReceiverEventMap> {
1759
1799
  private handleFileReceived;
1760
1800
  /** Inner handler: move file, emit FILE_STORED, parse DICOM, emit INSTANCE_RECEIVED. */
1761
1801
  private moveAndEmitFile;
1762
- /** Parses a DICOM file and emits INSTANCE_RECEIVED or error. */
1763
- private emitInstanceReceived;
1802
+ /** Parses a DICOM file and emits INSTANCE_RECEIVED or INSTANCE_ERROR. */
1803
+ private parseAndEmitInstance;
1764
1804
  /** Returns worker to idle pool on association complete, emits summary. */
1765
1805
  private wireAssociationComplete;
1766
- /** Awaits ALL pending file operations, emits ASSOCIATION_COMPLETE, resets worker state. */
1806
+ /** Awaits file ops, emits ASSOCIATION_COMPLETE, awaits parsing, emits ASSOCIATION_FINALIZED. */
1767
1807
  private finalizeAssociation;
1768
1808
  /** Emits the ASSOCIATION_COMPLETE event with transfer stats. */
1769
1809
  private emitAssociationComplete;
1810
+ /** Emits ASSOCIATION_FINALIZED after all instance parsing is done. */
1811
+ private emitAssociationFinalized;
1770
1812
  /** Bubbles ASSOCIATION_RECEIVED from dcmrecv worker. */
1771
1813
  private wireAssociationReceived;
1772
1814
  /** Bubbles C_STORE_REQUEST from dcmrecv worker. */
@@ -1783,4 +1825,4 @@ declare class DicomReceiver extends EventEmitter<DicomReceiverEventMap> {
1783
1825
  /** @deprecated Use ReceiverFileStoredData instead. */
1784
1826
  type ReceiverFileData = ReceiverFileStoredData;
1785
1827
 
1786
- export { type PoolCStoreRequestData as $, type AssociationAcknowledgedData as A, type DcmpsrcvEventValue as B, type CStoreRequestData as C, DCMPRSCP_FATAL_EVENTS as D, type DcmpsrcvOptions as E, DcmqrscpEvent as F, type DcmqrscpEventValue as G, Dcmrecv as H, DcmrecvEvent as I, type DcmrecvEventMap as J, type DcmrecvEventValue as K, type DcmrecvOptions as L, DcmtkProcess as M, type DcmtkProcessConfig as N, type DcmtkProcessEventMap as O, DicomReceiver as P, type DicomReceiverEventMap as Q, type DicomReceiverOptions as R, type EventPattern as S, type FileDeletedData as T, type FileReceivedData as U, FilenameMode as V, type FilenameModeValue as W, LineParser as X, type LineParserEventMap as Y, type MultiLineConfig as Z, type PoolAssociationReceivedData as _, type AssociationCompleteData as a, type PoolEchoRequestData as a0, type PoolRefusingAssociationData as a1, type PoolStatus as a2, PreferredTransferSyntax as a3, type PreferredTransferSyntaxValue as a4, type PrintAssociationAcknowledgedData as a5, type PrintAssociationReceivedData as a6, type PrintCannotStartListenerData as a7, ProcessState as a8, type ProcessStateValue as a9, type StorageModeValue as aA, StoreSCP as aB, type StoreSCPEventMap as aC, type StoreSCPOptions as aD, StoreSCPPreset as aE, type StoreSCPPresetName as aF, type StoredFileData as aG, StorescpEvent as aH, type StorescpEventValue as aI, type StoringFileData as aJ, type SubdirectoryCreatedData as aK, SubdirectoryMode as aL, type SubdirectoryModeValue as aM, type TrackedFile as aN, WLMSCPFS_FATAL_EVENTS as aO, WLMSCPFS_PATTERNS as aP, type WlmAssociationAcknowledgedData as aQ, type WlmAssociationReceivedData as aR, type WlmCFindRequestData as aS, type WlmCannotStartListenerData as aT, type WlmListeningData as aU, Wlmscpfs as aV, WlmscpfsEvent as aW, type WlmscpfsEventMap as aX, type WlmscpfsEventValue as aY, type WlmscpfsOptions as aZ, type QRAssociationAcknowledgedData as aa, type QRAssociationReceivedData as ab, type QRCFindRequestData as ac, type QRCGetRequestData as ad, type QRCMoveRequestData as ae, type QRCStoreRequestData as af, type QRCannotStartListenerData as ag, type QRListeningData as ah, type ReceiverAssociationAcknowledgedData as ai, type ReceiverAssociationData as aj, type ReceiverAssociationReceivedData as ak, type ReceiverCStoreRequestData as al, type ReceiverCannotStartListenerData as am, type ReceiverConfigErrorData as an, type ReceiverDatabaseReadyData as ao, type ReceiverEchoRequestData as ap, type ReceiverErrorData as aq, type ReceiverFileData as ar, type ReceiverFileReceivedData as as, type ReceiverFileStoredData as at, type ReceiverInstanceData as au, type ReceiverListeningData as av, type RefusingAssociationData as aw, STORESCP_FATAL_EVENTS as ax, STORESCP_PATTERNS as ay, StorageMode as az, type AssociationContext as b, type AssociationReceivedData as c, type AssociationSummary as d, AssociationTracker as e, type CannotStartListenerData as f, type ConfigErrorData as g, DCMPRSCP_PATTERNS as h, DCMPSRCV_FATAL_EVENTS as i, DCMPSRCV_PATTERNS as j, DCMQRSCP_FATAL_EVENTS as k, DCMQRSCP_PATTERNS as l, DCMRECV_FATAL_EVENTS as m, DCMRECV_PATTERNS as n, type DatabaseReadyData as o, DcmQRSCP as p, type DcmQRSCPEventMap as q, type DcmQRSCPOptions as r, DcmprsCP as s, type DcmprsCPEventMap as t, type DcmprsCPOptions as u, DcmprscpEvent as v, type DcmprscpEventValue as w, Dcmpsrcv as x, DcmpsrcvEvent as y, type DcmpsrcvEventMap as z };
1828
+ export { type PoolCStoreRequestData as $, type AssociationAcknowledgedData as A, type DcmpsrcvEventValue as B, type CStoreRequestData as C, DCMPRSCP_FATAL_EVENTS as D, type DcmpsrcvOptions as E, DcmqrscpEvent as F, type DcmqrscpEventValue as G, Dcmrecv as H, DcmrecvEvent as I, type DcmrecvEventMap as J, type DcmrecvEventValue as K, type DcmrecvOptions as L, DcmtkProcess as M, type DcmtkProcessConfig as N, type DcmtkProcessEventMap as O, DicomReceiver as P, type DicomReceiverEventMap as Q, type DicomReceiverOptions as R, type EventPattern as S, type FileDeletedData as T, type FileReceivedData as U, FilenameMode as V, type FilenameModeValue as W, LineParser as X, type LineParserEventMap as Y, type MultiLineConfig as Z, type PoolAssociationReceivedData as _, type AssociationCompleteData as a, type WlmscpfsOptions as a$, type PoolEchoRequestData as a0, type PoolRefusingAssociationData as a1, type PoolStatus as a2, PreferredTransferSyntax as a3, type PreferredTransferSyntaxValue as a4, type PrintAssociationAcknowledgedData as a5, type PrintAssociationReceivedData as a6, type PrintCannotStartListenerData as a7, ProcessState as a8, type ProcessStateValue as a9, STORESCP_PATTERNS as aA, StorageMode as aB, type StorageModeValue as aC, StoreSCP as aD, type StoreSCPEventMap as aE, type StoreSCPOptions as aF, StoreSCPPreset as aG, type StoreSCPPresetName as aH, type StoredFileData as aI, StorescpEvent as aJ, type StorescpEventValue as aK, type StoringFileData as aL, type SubdirectoryCreatedData as aM, SubdirectoryMode as aN, type SubdirectoryModeValue as aO, type TrackedFile as aP, WLMSCPFS_FATAL_EVENTS as aQ, WLMSCPFS_PATTERNS as aR, type WlmAssociationAcknowledgedData as aS, type WlmAssociationReceivedData as aT, type WlmCFindRequestData as aU, type WlmCannotStartListenerData as aV, type WlmListeningData as aW, Wlmscpfs as aX, WlmscpfsEvent as aY, type WlmscpfsEventMap as aZ, type WlmscpfsEventValue as a_, type QRAssociationAcknowledgedData as aa, type QRAssociationReceivedData as ab, type QRCFindRequestData as ac, type QRCGetRequestData as ad, type QRCMoveRequestData as ae, type QRCStoreRequestData as af, type QRCannotStartListenerData as ag, type QRListeningData as ah, type ReceiverAssociationAcknowledgedData as ai, type ReceiverAssociationData as aj, type ReceiverAssociationFinalizedData as ak, type ReceiverAssociationReceivedData as al, type ReceiverCStoreRequestData as am, type ReceiverCannotStartListenerData as an, type ReceiverConfigErrorData as ao, type ReceiverDatabaseReadyData as ap, type ReceiverEchoRequestData as aq, type ReceiverErrorData as ar, type ReceiverFileData as as, type ReceiverFileReceivedData as at, type ReceiverFileStoredData as au, type ReceiverInstanceData as av, type ReceiverInstanceErrorData as aw, type ReceiverListeningData as ax, type RefusingAssociationData as ay, STORESCP_FATAL_EVENTS as az, type AssociationContext as b, type AssociationReceivedData as c, type AssociationSummary as d, AssociationTracker as e, type CannotStartListenerData as f, type ConfigErrorData as g, DCMPRSCP_PATTERNS as h, DCMPSRCV_FATAL_EVENTS as i, DCMPSRCV_PATTERNS as j, DCMQRSCP_FATAL_EVENTS as k, DCMQRSCP_PATTERNS as l, DCMRECV_FATAL_EVENTS as m, DCMRECV_PATTERNS as n, type DatabaseReadyData as o, DcmQRSCP as p, type DcmQRSCPEventMap as q, type DcmQRSCPOptions as r, DcmprsCP as s, type DcmprsCPEventMap as t, type DcmprsCPOptions as u, DcmprscpEvent as v, type DcmprscpEventValue as w, Dcmpsrcv as x, DcmpsrcvEvent as y, type DcmpsrcvEventMap as z };
@@ -1544,6 +1544,30 @@ interface PoolEchoRequestData {
1544
1544
  interface PoolRefusingAssociationData {
1545
1545
  readonly reason: string;
1546
1546
  }
1547
+ /** Data emitted with INSTANCE_ERROR events when DicomInstance.open fails. */
1548
+ interface ReceiverInstanceErrorData {
1549
+ readonly error: Error;
1550
+ /** Whether this was a thrown exception (true) or a Result error (false). */
1551
+ readonly thrown: boolean;
1552
+ readonly filePath: string;
1553
+ readonly fileSize: number;
1554
+ readonly associationId: string;
1555
+ readonly associationDir: string;
1556
+ readonly callingAE: string;
1557
+ readonly calledAE: string;
1558
+ readonly source: string;
1559
+ }
1560
+ /** Data emitted with ASSOCIATION_FINALIZED — all work (including parsing) is done. */
1561
+ interface ReceiverAssociationFinalizedData {
1562
+ readonly associationId: string;
1563
+ readonly associationDir: string;
1564
+ readonly callingAE: string;
1565
+ readonly calledAE: string;
1566
+ readonly source: string;
1567
+ readonly files: readonly string[];
1568
+ readonly instancesReceived: number;
1569
+ readonly instanceErrors: number;
1570
+ }
1547
1571
  /** Data emitted with error events. */
1548
1572
  interface ReceiverErrorData {
1549
1573
  readonly error: Error;
@@ -1559,7 +1583,9 @@ interface DicomReceiverEventMap {
1559
1583
  FILE_RECEIVED: [ReceiverFileReceivedData];
1560
1584
  FILE_STORED: [ReceiverFileStoredData];
1561
1585
  INSTANCE_RECEIVED: [ReceiverInstanceData];
1586
+ INSTANCE_ERROR: [ReceiverInstanceErrorData];
1562
1587
  ASSOCIATION_COMPLETE: [ReceiverAssociationData];
1588
+ ASSOCIATION_FINALIZED: [ReceiverAssociationFinalizedData];
1563
1589
  ASSOCIATION_RECEIVED: [PoolAssociationReceivedData];
1564
1590
  C_STORE_REQUEST: [PoolCStoreRequestData];
1565
1591
  ECHO_REQUEST: [PoolEchoRequestData];
@@ -1682,12 +1708,26 @@ declare class DicomReceiver extends EventEmitter<DicomReceiverEventMap> {
1682
1708
  */
1683
1709
  onInstanceReceived(listener: (data: ReceiverInstanceData) => void): this;
1684
1710
  /**
1685
- * Registers a listener for completed associations.
1711
+ * Registers a listener for DicomInstance.open failures.
1712
+ *
1713
+ * @param listener - Callback receiving instance error data
1714
+ * @returns this for chaining
1715
+ */
1716
+ onInstanceError(listener: (data: ReceiverInstanceErrorData) => void): this;
1717
+ /**
1718
+ * Registers a listener for completed associations (file moves done).
1686
1719
  *
1687
1720
  * @param listener - Callback receiving association data
1688
1721
  * @returns this for chaining
1689
1722
  */
1690
1723
  onAssociationComplete(listener: (data: ReceiverAssociationData) => void): this;
1724
+ /**
1725
+ * Registers a listener for fully finalized associations (all parsing done).
1726
+ *
1727
+ * @param listener - Callback receiving finalized data with instance counts
1728
+ * @returns this for chaining
1729
+ */
1730
+ onAssociationFinalized(listener: (data: ReceiverAssociationFinalizedData) => void): this;
1691
1731
  /**
1692
1732
  * Registers a listener for new associations (bubbled from workers).
1693
1733
  *
@@ -1759,14 +1799,16 @@ declare class DicomReceiver extends EventEmitter<DicomReceiverEventMap> {
1759
1799
  private handleFileReceived;
1760
1800
  /** Inner handler: move file, emit FILE_STORED, parse DICOM, emit INSTANCE_RECEIVED. */
1761
1801
  private moveAndEmitFile;
1762
- /** Parses a DICOM file and emits INSTANCE_RECEIVED or error. */
1763
- private emitInstanceReceived;
1802
+ /** Parses a DICOM file and emits INSTANCE_RECEIVED or INSTANCE_ERROR. */
1803
+ private parseAndEmitInstance;
1764
1804
  /** Returns worker to idle pool on association complete, emits summary. */
1765
1805
  private wireAssociationComplete;
1766
- /** Awaits ALL pending file operations, emits ASSOCIATION_COMPLETE, resets worker state. */
1806
+ /** Awaits file ops, emits ASSOCIATION_COMPLETE, awaits parsing, emits ASSOCIATION_FINALIZED. */
1767
1807
  private finalizeAssociation;
1768
1808
  /** Emits the ASSOCIATION_COMPLETE event with transfer stats. */
1769
1809
  private emitAssociationComplete;
1810
+ /** Emits ASSOCIATION_FINALIZED after all instance parsing is done. */
1811
+ private emitAssociationFinalized;
1770
1812
  /** Bubbles ASSOCIATION_RECEIVED from dcmrecv worker. */
1771
1813
  private wireAssociationReceived;
1772
1814
  /** Bubbles C_STORE_REQUEST from dcmrecv worker. */
@@ -1783,4 +1825,4 @@ declare class DicomReceiver extends EventEmitter<DicomReceiverEventMap> {
1783
1825
  /** @deprecated Use ReceiverFileStoredData instead. */
1784
1826
  type ReceiverFileData = ReceiverFileStoredData;
1785
1827
 
1786
- export { type PoolCStoreRequestData as $, type AssociationAcknowledgedData as A, type DcmpsrcvEventValue as B, type CStoreRequestData as C, DCMPRSCP_FATAL_EVENTS as D, type DcmpsrcvOptions as E, DcmqrscpEvent as F, type DcmqrscpEventValue as G, Dcmrecv as H, DcmrecvEvent as I, type DcmrecvEventMap as J, type DcmrecvEventValue as K, type DcmrecvOptions as L, DcmtkProcess as M, type DcmtkProcessConfig as N, type DcmtkProcessEventMap as O, DicomReceiver as P, type DicomReceiverEventMap as Q, type DicomReceiverOptions as R, type EventPattern as S, type FileDeletedData as T, type FileReceivedData as U, FilenameMode as V, type FilenameModeValue as W, LineParser as X, type LineParserEventMap as Y, type MultiLineConfig as Z, type PoolAssociationReceivedData as _, type AssociationCompleteData as a, type PoolEchoRequestData as a0, type PoolRefusingAssociationData as a1, type PoolStatus as a2, PreferredTransferSyntax as a3, type PreferredTransferSyntaxValue as a4, type PrintAssociationAcknowledgedData as a5, type PrintAssociationReceivedData as a6, type PrintCannotStartListenerData as a7, ProcessState as a8, type ProcessStateValue as a9, type StorageModeValue as aA, StoreSCP as aB, type StoreSCPEventMap as aC, type StoreSCPOptions as aD, StoreSCPPreset as aE, type StoreSCPPresetName as aF, type StoredFileData as aG, StorescpEvent as aH, type StorescpEventValue as aI, type StoringFileData as aJ, type SubdirectoryCreatedData as aK, SubdirectoryMode as aL, type SubdirectoryModeValue as aM, type TrackedFile as aN, WLMSCPFS_FATAL_EVENTS as aO, WLMSCPFS_PATTERNS as aP, type WlmAssociationAcknowledgedData as aQ, type WlmAssociationReceivedData as aR, type WlmCFindRequestData as aS, type WlmCannotStartListenerData as aT, type WlmListeningData as aU, Wlmscpfs as aV, WlmscpfsEvent as aW, type WlmscpfsEventMap as aX, type WlmscpfsEventValue as aY, type WlmscpfsOptions as aZ, type QRAssociationAcknowledgedData as aa, type QRAssociationReceivedData as ab, type QRCFindRequestData as ac, type QRCGetRequestData as ad, type QRCMoveRequestData as ae, type QRCStoreRequestData as af, type QRCannotStartListenerData as ag, type QRListeningData as ah, type ReceiverAssociationAcknowledgedData as ai, type ReceiverAssociationData as aj, type ReceiverAssociationReceivedData as ak, type ReceiverCStoreRequestData as al, type ReceiverCannotStartListenerData as am, type ReceiverConfigErrorData as an, type ReceiverDatabaseReadyData as ao, type ReceiverEchoRequestData as ap, type ReceiverErrorData as aq, type ReceiverFileData as ar, type ReceiverFileReceivedData as as, type ReceiverFileStoredData as at, type ReceiverInstanceData as au, type ReceiverListeningData as av, type RefusingAssociationData as aw, STORESCP_FATAL_EVENTS as ax, STORESCP_PATTERNS as ay, StorageMode as az, type AssociationContext as b, type AssociationReceivedData as c, type AssociationSummary as d, AssociationTracker as e, type CannotStartListenerData as f, type ConfigErrorData as g, DCMPRSCP_PATTERNS as h, DCMPSRCV_FATAL_EVENTS as i, DCMPSRCV_PATTERNS as j, DCMQRSCP_FATAL_EVENTS as k, DCMQRSCP_PATTERNS as l, DCMRECV_FATAL_EVENTS as m, DCMRECV_PATTERNS as n, type DatabaseReadyData as o, DcmQRSCP as p, type DcmQRSCPEventMap as q, type DcmQRSCPOptions as r, DcmprsCP as s, type DcmprsCPEventMap as t, type DcmprsCPOptions as u, DcmprscpEvent as v, type DcmprscpEventValue as w, Dcmpsrcv as x, DcmpsrcvEvent as y, type DcmpsrcvEventMap as z };
1828
+ export { type PoolCStoreRequestData as $, type AssociationAcknowledgedData as A, type DcmpsrcvEventValue as B, type CStoreRequestData as C, DCMPRSCP_FATAL_EVENTS as D, type DcmpsrcvOptions as E, DcmqrscpEvent as F, type DcmqrscpEventValue as G, Dcmrecv as H, DcmrecvEvent as I, type DcmrecvEventMap as J, type DcmrecvEventValue as K, type DcmrecvOptions as L, DcmtkProcess as M, type DcmtkProcessConfig as N, type DcmtkProcessEventMap as O, DicomReceiver as P, type DicomReceiverEventMap as Q, type DicomReceiverOptions as R, type EventPattern as S, type FileDeletedData as T, type FileReceivedData as U, FilenameMode as V, type FilenameModeValue as W, LineParser as X, type LineParserEventMap as Y, type MultiLineConfig as Z, type PoolAssociationReceivedData as _, type AssociationCompleteData as a, type WlmscpfsOptions as a$, type PoolEchoRequestData as a0, type PoolRefusingAssociationData as a1, type PoolStatus as a2, PreferredTransferSyntax as a3, type PreferredTransferSyntaxValue as a4, type PrintAssociationAcknowledgedData as a5, type PrintAssociationReceivedData as a6, type PrintCannotStartListenerData as a7, ProcessState as a8, type ProcessStateValue as a9, STORESCP_PATTERNS as aA, StorageMode as aB, type StorageModeValue as aC, StoreSCP as aD, type StoreSCPEventMap as aE, type StoreSCPOptions as aF, StoreSCPPreset as aG, type StoreSCPPresetName as aH, type StoredFileData as aI, StorescpEvent as aJ, type StorescpEventValue as aK, type StoringFileData as aL, type SubdirectoryCreatedData as aM, SubdirectoryMode as aN, type SubdirectoryModeValue as aO, type TrackedFile as aP, WLMSCPFS_FATAL_EVENTS as aQ, WLMSCPFS_PATTERNS as aR, type WlmAssociationAcknowledgedData as aS, type WlmAssociationReceivedData as aT, type WlmCFindRequestData as aU, type WlmCannotStartListenerData as aV, type WlmListeningData as aW, Wlmscpfs as aX, WlmscpfsEvent as aY, type WlmscpfsEventMap as aZ, type WlmscpfsEventValue as a_, type QRAssociationAcknowledgedData as aa, type QRAssociationReceivedData as ab, type QRCFindRequestData as ac, type QRCGetRequestData as ad, type QRCMoveRequestData as ae, type QRCStoreRequestData as af, type QRCannotStartListenerData as ag, type QRListeningData as ah, type ReceiverAssociationAcknowledgedData as ai, type ReceiverAssociationData as aj, type ReceiverAssociationFinalizedData as ak, type ReceiverAssociationReceivedData as al, type ReceiverCStoreRequestData as am, type ReceiverCannotStartListenerData as an, type ReceiverConfigErrorData as ao, type ReceiverDatabaseReadyData as ap, type ReceiverEchoRequestData as aq, type ReceiverErrorData as ar, type ReceiverFileData as as, type ReceiverFileReceivedData as at, type ReceiverFileStoredData as au, type ReceiverInstanceData as av, type ReceiverInstanceErrorData as aw, type ReceiverListeningData as ax, type RefusingAssociationData as ay, STORESCP_FATAL_EVENTS as az, type AssociationContext as b, type AssociationReceivedData as c, type AssociationSummary as d, AssociationTracker as e, type CannotStartListenerData as f, type ConfigErrorData as g, DCMPRSCP_PATTERNS as h, DCMPSRCV_FATAL_EVENTS as i, DCMPSRCV_PATTERNS as j, DCMQRSCP_FATAL_EVENTS as k, DCMQRSCP_PATTERNS as l, DCMRECV_FATAL_EVENTS as m, DCMRECV_PATTERNS as n, type DatabaseReadyData as o, DcmQRSCP as p, type DcmQRSCPEventMap as q, type DcmQRSCPOptions as r, DcmprsCP as s, type DcmprsCPEventMap as t, type DcmprsCPOptions as u, DcmprscpEvent as v, type DcmprscpEventValue as w, Dcmpsrcv as x, DcmpsrcvEvent as y, type DcmpsrcvEventMap as z };
package/dist/index.cjs CHANGED
@@ -36484,6 +36484,9 @@ var Worker = class {
36484
36484
  __publicField(this, "_state", "idle");
36485
36485
  __publicField(this, "_context");
36486
36486
  __publicField(this, "_pending", /* @__PURE__ */ new Set());
36487
+ __publicField(this, "_instancePending", /* @__PURE__ */ new Set());
36488
+ __publicField(this, "_instancesReceived", 0);
36489
+ __publicField(this, "_instanceErrors", 0);
36487
36490
  __publicField(this, "_files", []);
36488
36491
  __publicField(this, "_fileSizes", []);
36489
36492
  __publicField(this, "_outputLines", []);
@@ -36521,6 +36524,9 @@ var Worker = class {
36521
36524
  this._fileSizes.length = 0;
36522
36525
  this._outputLines.length = 0;
36523
36526
  this._pending.clear();
36527
+ this._instancePending.clear();
36528
+ this._instancesReceived = 0;
36529
+ this._instanceErrors = 0;
36524
36530
  }
36525
36531
  /** Returns the worker to idle and clears all association state. */
36526
36532
  endAssociation() {
@@ -36530,6 +36536,9 @@ var Worker = class {
36530
36536
  this._fileSizes.length = 0;
36531
36537
  this._outputLines.length = 0;
36532
36538
  this._pending.clear();
36539
+ this._instancePending.clear();
36540
+ this._instancesReceived = 0;
36541
+ this._instanceErrors = 0;
36533
36542
  this._remoteSocket = void 0;
36534
36543
  this._workerSocket = void 0;
36535
36544
  }
@@ -36540,6 +36549,35 @@ var Worker = class {
36540
36549
  this._pending.delete(promise);
36541
36550
  });
36542
36551
  }
36552
+ /** Tracks an in-flight instance parsing promise; auto-removes on completion. */
36553
+ trackInstance(promise) {
36554
+ this._instancePending.add(promise);
36555
+ void promise.finally(() => {
36556
+ this._instancePending.delete(promise);
36557
+ });
36558
+ }
36559
+ /** Records a successful instance parse. */
36560
+ recordInstanceSuccess() {
36561
+ this._instancesReceived++;
36562
+ }
36563
+ /** Records a failed instance parse. */
36564
+ recordInstanceError() {
36565
+ this._instanceErrors++;
36566
+ }
36567
+ /** Awaits all in-flight instance parsing promises. */
36568
+ async drainInstancePending() {
36569
+ if (this._instancePending.size > 0) {
36570
+ await Promise.all(this._instancePending);
36571
+ }
36572
+ }
36573
+ /** Number of successfully parsed instances in this association. */
36574
+ get instancesReceived() {
36575
+ return this._instancesReceived;
36576
+ }
36577
+ /** Number of failed instance parses in this association. */
36578
+ get instanceErrors() {
36579
+ return this._instanceErrors;
36580
+ }
36543
36581
  /** Records a successfully received file path and its size. */
36544
36582
  recordFile(filePath, size) {
36545
36583
  this._files.push(filePath);
@@ -36711,7 +36749,16 @@ var DicomReceiver = class _DicomReceiver extends events.EventEmitter {
36711
36749
  return this.on("INSTANCE_RECEIVED", listener);
36712
36750
  }
36713
36751
  /**
36714
- * Registers a listener for completed associations.
36752
+ * Registers a listener for DicomInstance.open failures.
36753
+ *
36754
+ * @param listener - Callback receiving instance error data
36755
+ * @returns this for chaining
36756
+ */
36757
+ onInstanceError(listener) {
36758
+ return this.on("INSTANCE_ERROR", listener);
36759
+ }
36760
+ /**
36761
+ * Registers a listener for completed associations (file moves done).
36715
36762
  *
36716
36763
  * @param listener - Callback receiving association data
36717
36764
  * @returns this for chaining
@@ -36719,6 +36766,15 @@ var DicomReceiver = class _DicomReceiver extends events.EventEmitter {
36719
36766
  onAssociationComplete(listener) {
36720
36767
  return this.on("ASSOCIATION_COMPLETE", listener);
36721
36768
  }
36769
+ /**
36770
+ * Registers a listener for fully finalized associations (all parsing done).
36771
+ *
36772
+ * @param listener - Callback receiving finalized data with instance counts
36773
+ * @returns this for chaining
36774
+ */
36775
+ onAssociationFinalized(listener) {
36776
+ return this.on("ASSOCIATION_FINALIZED", listener);
36777
+ }
36722
36778
  /**
36723
36779
  * Registers a listener for new associations (bubbled from workers).
36724
36780
  *
@@ -37048,34 +37104,33 @@ var DicomReceiver = class _DicomReceiver extends events.EventEmitter {
37048
37104
  calledAE: data.calledAE,
37049
37105
  source: data.source
37050
37106
  });
37051
- this.emitInstanceReceived(finalPath, fileSize, data, ctx);
37107
+ const instanceCtx = {
37108
+ filePath: finalPath,
37109
+ fileSize,
37110
+ associationId: ctx.associationId,
37111
+ associationDir: ctx.associationDir,
37112
+ callingAE: data.callingAE,
37113
+ calledAE: data.calledAE,
37114
+ source: data.source
37115
+ };
37116
+ worker.trackInstance(this.parseAndEmitInstance(worker, instanceCtx));
37052
37117
  }
37053
- /** Parses a DICOM file and emits INSTANCE_RECEIVED or error. */
37054
- emitInstanceReceived(filePath, fileSize, data, ctx) {
37055
- void DicomInstance.open(filePath).then((openResult) => {
37118
+ /** Parses a DICOM file and emits INSTANCE_RECEIVED or INSTANCE_ERROR. */
37119
+ async parseAndEmitInstance(worker, ctx) {
37120
+ try {
37121
+ const openResult = await DicomInstance.open(ctx.filePath);
37056
37122
  if (!openResult.ok) {
37057
- this.emit("error", {
37058
- error: openResult.error,
37059
- filePath,
37060
- associationId: ctx.associationId,
37061
- associationDir: ctx.associationDir,
37062
- callingAE: data.callingAE,
37063
- calledAE: data.calledAE,
37064
- source: data.source
37065
- });
37123
+ worker.recordInstanceError();
37124
+ this.emit("INSTANCE_ERROR", { error: openResult.error, thrown: false, ...ctx });
37066
37125
  return;
37067
37126
  }
37068
- this.emit("INSTANCE_RECEIVED", {
37069
- filePath,
37070
- fileSize,
37071
- associationId: ctx.associationId,
37072
- associationDir: ctx.associationDir,
37073
- callingAE: data.callingAE,
37074
- calledAE: data.calledAE,
37075
- source: data.source,
37076
- instance: openResult.value
37077
- });
37078
- });
37127
+ worker.recordInstanceSuccess();
37128
+ this.emit("INSTANCE_RECEIVED", { ...ctx, instance: openResult.value });
37129
+ } catch (thrown) {
37130
+ const error = thrown instanceof Error ? thrown : new Error(String(thrown));
37131
+ worker.recordInstanceError();
37132
+ this.emit("INSTANCE_ERROR", { error, thrown: true, ...ctx });
37133
+ }
37079
37134
  }
37080
37135
  /** Returns worker to idle pool on association complete, emits summary. */
37081
37136
  wireAssociationComplete(worker) {
@@ -37083,10 +37138,12 @@ var DicomReceiver = class _DicomReceiver extends events.EventEmitter {
37083
37138
  void this.finalizeAssociation(worker, data);
37084
37139
  });
37085
37140
  }
37086
- /** Awaits ALL pending file operations, emits ASSOCIATION_COMPLETE, resets worker state. */
37141
+ /** Awaits file ops, emits ASSOCIATION_COMPLETE, awaits parsing, emits ASSOCIATION_FINALIZED. */
37087
37142
  async finalizeAssociation(worker, data) {
37088
37143
  await worker.drainPendingFiles();
37089
37144
  this.emitAssociationComplete(worker, data);
37145
+ await worker.drainInstancePending();
37146
+ this.emitAssociationFinalized(worker, data);
37090
37147
  worker.endAssociation();
37091
37148
  void this.scaleDown();
37092
37149
  }
@@ -37118,6 +37175,20 @@ var DicomReceiver = class _DicomReceiver extends events.EventEmitter {
37118
37175
  output
37119
37176
  });
37120
37177
  }
37178
+ /** Emits ASSOCIATION_FINALIZED after all instance parsing is done. */
37179
+ emitAssociationFinalized(worker, data) {
37180
+ const ctx = worker.context;
37181
+ this.emit("ASSOCIATION_FINALIZED", {
37182
+ associationId: ctx?.associationId ?? data.associationId,
37183
+ associationDir: ctx?.associationDir ?? "",
37184
+ callingAE: data.callingAE,
37185
+ calledAE: data.calledAE,
37186
+ source: data.source,
37187
+ files: [...worker.files],
37188
+ instancesReceived: worker.instancesReceived,
37189
+ instanceErrors: worker.instanceErrors
37190
+ });
37191
+ }
37121
37192
  /** Bubbles ASSOCIATION_RECEIVED from dcmrecv worker. */
37122
37193
  wireAssociationReceived(worker) {
37123
37194
  worker.dcmrecv.onEvent("ASSOCIATION_RECEIVED", (data) => {