@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.
@@ -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
@@ -31402,7 +31402,12 @@ var parser = new fastXmlParser.XMLParser({
31402
31402
  ignoreAttributes: false,
31403
31403
  attributeNamePrefix: "@_",
31404
31404
  parseTagValue: false,
31405
- isArray: (name) => ARRAY_TAG_NAMES.has(name)
31405
+ isArray: (name) => ARRAY_TAG_NAMES.has(name),
31406
+ // DICOM XML does not use XML entities. Disable entity processing to avoid
31407
+ // the default expansion limit (1000) which rejects files with >1000 tags.
31408
+ // Without this, large studies fall through to dcm2json which hangs on
31409
+ // compressed pixel data (DCMTK bug).
31410
+ processEntities: false
31406
31411
  });
31407
31412
  function xmlToJson(xml) {
31408
31413
  try {
@@ -36484,6 +36489,9 @@ var Worker = class {
36484
36489
  __publicField(this, "_state", "idle");
36485
36490
  __publicField(this, "_context");
36486
36491
  __publicField(this, "_pending", /* @__PURE__ */ new Set());
36492
+ __publicField(this, "_instancePending", /* @__PURE__ */ new Set());
36493
+ __publicField(this, "_instancesReceived", 0);
36494
+ __publicField(this, "_instanceErrors", 0);
36487
36495
  __publicField(this, "_files", []);
36488
36496
  __publicField(this, "_fileSizes", []);
36489
36497
  __publicField(this, "_outputLines", []);
@@ -36521,6 +36529,9 @@ var Worker = class {
36521
36529
  this._fileSizes.length = 0;
36522
36530
  this._outputLines.length = 0;
36523
36531
  this._pending.clear();
36532
+ this._instancePending.clear();
36533
+ this._instancesReceived = 0;
36534
+ this._instanceErrors = 0;
36524
36535
  }
36525
36536
  /** Returns the worker to idle and clears all association state. */
36526
36537
  endAssociation() {
@@ -36530,6 +36541,9 @@ var Worker = class {
36530
36541
  this._fileSizes.length = 0;
36531
36542
  this._outputLines.length = 0;
36532
36543
  this._pending.clear();
36544
+ this._instancePending.clear();
36545
+ this._instancesReceived = 0;
36546
+ this._instanceErrors = 0;
36533
36547
  this._remoteSocket = void 0;
36534
36548
  this._workerSocket = void 0;
36535
36549
  }
@@ -36540,6 +36554,35 @@ var Worker = class {
36540
36554
  this._pending.delete(promise);
36541
36555
  });
36542
36556
  }
36557
+ /** Tracks an in-flight instance parsing promise; auto-removes on completion. */
36558
+ trackInstance(promise) {
36559
+ this._instancePending.add(promise);
36560
+ void promise.finally(() => {
36561
+ this._instancePending.delete(promise);
36562
+ });
36563
+ }
36564
+ /** Records a successful instance parse. */
36565
+ recordInstanceSuccess() {
36566
+ this._instancesReceived++;
36567
+ }
36568
+ /** Records a failed instance parse. */
36569
+ recordInstanceError() {
36570
+ this._instanceErrors++;
36571
+ }
36572
+ /** Awaits all in-flight instance parsing promises. */
36573
+ async drainInstancePending() {
36574
+ if (this._instancePending.size > 0) {
36575
+ await Promise.all(this._instancePending);
36576
+ }
36577
+ }
36578
+ /** Number of successfully parsed instances in this association. */
36579
+ get instancesReceived() {
36580
+ return this._instancesReceived;
36581
+ }
36582
+ /** Number of failed instance parses in this association. */
36583
+ get instanceErrors() {
36584
+ return this._instanceErrors;
36585
+ }
36543
36586
  /** Records a successfully received file path and its size. */
36544
36587
  recordFile(filePath, size) {
36545
36588
  this._files.push(filePath);
@@ -36711,7 +36754,16 @@ var DicomReceiver = class _DicomReceiver extends events.EventEmitter {
36711
36754
  return this.on("INSTANCE_RECEIVED", listener);
36712
36755
  }
36713
36756
  /**
36714
- * Registers a listener for completed associations.
36757
+ * Registers a listener for DicomInstance.open failures.
36758
+ *
36759
+ * @param listener - Callback receiving instance error data
36760
+ * @returns this for chaining
36761
+ */
36762
+ onInstanceError(listener) {
36763
+ return this.on("INSTANCE_ERROR", listener);
36764
+ }
36765
+ /**
36766
+ * Registers a listener for completed associations (file moves done).
36715
36767
  *
36716
36768
  * @param listener - Callback receiving association data
36717
36769
  * @returns this for chaining
@@ -36719,6 +36771,15 @@ var DicomReceiver = class _DicomReceiver extends events.EventEmitter {
36719
36771
  onAssociationComplete(listener) {
36720
36772
  return this.on("ASSOCIATION_COMPLETE", listener);
36721
36773
  }
36774
+ /**
36775
+ * Registers a listener for fully finalized associations (all parsing done).
36776
+ *
36777
+ * @param listener - Callback receiving finalized data with instance counts
36778
+ * @returns this for chaining
36779
+ */
36780
+ onAssociationFinalized(listener) {
36781
+ return this.on("ASSOCIATION_FINALIZED", listener);
36782
+ }
36722
36783
  /**
36723
36784
  * Registers a listener for new associations (bubbled from workers).
36724
36785
  *
@@ -37048,28 +37109,33 @@ var DicomReceiver = class _DicomReceiver extends events.EventEmitter {
37048
37109
  calledAE: data.calledAE,
37049
37110
  source: data.source
37050
37111
  });
37051
- this.emitInstanceReceived(finalPath, fileSize, data, ctx);
37052
- }
37053
- /** Parses a DICOM file and emits INSTANCE_RECEIVED or error. */
37054
- emitInstanceReceived(filePath, fileSize, data, ctx) {
37055
- const errorCtx = {
37056
- filePath,
37112
+ const instanceCtx = {
37113
+ filePath: finalPath,
37114
+ fileSize,
37057
37115
  associationId: ctx.associationId,
37058
37116
  associationDir: ctx.associationDir,
37059
37117
  callingAE: data.callingAE,
37060
37118
  calledAE: data.calledAE,
37061
37119
  source: data.source
37062
37120
  };
37063
- void DicomInstance.open(filePath).then((openResult) => {
37121
+ worker.trackInstance(this.parseAndEmitInstance(worker, instanceCtx));
37122
+ }
37123
+ /** Parses a DICOM file and emits INSTANCE_RECEIVED or INSTANCE_ERROR. */
37124
+ async parseAndEmitInstance(worker, ctx) {
37125
+ try {
37126
+ const openResult = await DicomInstance.open(ctx.filePath);
37064
37127
  if (!openResult.ok) {
37065
- this.emit("error", { error: openResult.error, ...errorCtx });
37128
+ worker.recordInstanceError();
37129
+ this.emit("INSTANCE_ERROR", { error: openResult.error, thrown: false, ...ctx });
37066
37130
  return;
37067
37131
  }
37068
- this.emit("INSTANCE_RECEIVED", { ...errorCtx, fileSize, instance: openResult.value });
37069
- }).catch((thrown) => {
37132
+ worker.recordInstanceSuccess();
37133
+ this.emit("INSTANCE_RECEIVED", { ...ctx, instance: openResult.value });
37134
+ } catch (thrown) {
37070
37135
  const error = thrown instanceof Error ? thrown : new Error(String(thrown));
37071
- this.emit("error", { error, ...errorCtx });
37072
- });
37136
+ worker.recordInstanceError();
37137
+ this.emit("INSTANCE_ERROR", { error, thrown: true, ...ctx });
37138
+ }
37073
37139
  }
37074
37140
  /** Returns worker to idle pool on association complete, emits summary. */
37075
37141
  wireAssociationComplete(worker) {
@@ -37077,10 +37143,12 @@ var DicomReceiver = class _DicomReceiver extends events.EventEmitter {
37077
37143
  void this.finalizeAssociation(worker, data);
37078
37144
  });
37079
37145
  }
37080
- /** Awaits ALL pending file operations, emits ASSOCIATION_COMPLETE, resets worker state. */
37146
+ /** Awaits file ops, emits ASSOCIATION_COMPLETE, awaits parsing, emits ASSOCIATION_FINALIZED. */
37081
37147
  async finalizeAssociation(worker, data) {
37082
37148
  await worker.drainPendingFiles();
37083
37149
  this.emitAssociationComplete(worker, data);
37150
+ await worker.drainInstancePending();
37151
+ this.emitAssociationFinalized(worker, data);
37084
37152
  worker.endAssociation();
37085
37153
  void this.scaleDown();
37086
37154
  }
@@ -37112,6 +37180,20 @@ var DicomReceiver = class _DicomReceiver extends events.EventEmitter {
37112
37180
  output
37113
37181
  });
37114
37182
  }
37183
+ /** Emits ASSOCIATION_FINALIZED after all instance parsing is done. */
37184
+ emitAssociationFinalized(worker, data) {
37185
+ const ctx = worker.context;
37186
+ this.emit("ASSOCIATION_FINALIZED", {
37187
+ associationId: ctx?.associationId ?? data.associationId,
37188
+ associationDir: ctx?.associationDir ?? "",
37189
+ callingAE: data.callingAE,
37190
+ calledAE: data.calledAE,
37191
+ source: data.source,
37192
+ files: [...worker.files],
37193
+ instancesReceived: worker.instancesReceived,
37194
+ instanceErrors: worker.instanceErrors
37195
+ });
37196
+ }
37115
37197
  /** Bubbles ASSOCIATION_RECEIVED from dcmrecv worker. */
37116
37198
  wireAssociationReceived(worker) {
37117
37199
  worker.dcmrecv.onEvent("ASSOCIATION_RECEIVED", (data) => {