@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.
- package/dist/{index--dDQfutR.d.ts → index-B5FQoIqM.d.ts} +47 -5
- package/dist/{index-CVDMaxd8.d.cts → index-DV8HaHEX.d.cts} +47 -5
- package/dist/index.cjs +97 -26
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +97 -26
- package/dist/index.js.map +1 -1
- package/dist/servers.cjs +97 -26
- package/dist/servers.cjs.map +1 -1
- package/dist/servers.d.cts +1 -1
- package/dist/servers.d.ts +1 -1
- package/dist/servers.js +97 -26
- package/dist/servers.js.map +1 -1
- package/package.json +1 -1
package/dist/servers.cjs
CHANGED
|
@@ -2855,6 +2855,9 @@ var Worker = class {
|
|
|
2855
2855
|
__publicField(this, "_state", "idle");
|
|
2856
2856
|
__publicField(this, "_context");
|
|
2857
2857
|
__publicField(this, "_pending", /* @__PURE__ */ new Set());
|
|
2858
|
+
__publicField(this, "_instancePending", /* @__PURE__ */ new Set());
|
|
2859
|
+
__publicField(this, "_instancesReceived", 0);
|
|
2860
|
+
__publicField(this, "_instanceErrors", 0);
|
|
2858
2861
|
__publicField(this, "_files", []);
|
|
2859
2862
|
__publicField(this, "_fileSizes", []);
|
|
2860
2863
|
__publicField(this, "_outputLines", []);
|
|
@@ -2892,6 +2895,9 @@ var Worker = class {
|
|
|
2892
2895
|
this._fileSizes.length = 0;
|
|
2893
2896
|
this._outputLines.length = 0;
|
|
2894
2897
|
this._pending.clear();
|
|
2898
|
+
this._instancePending.clear();
|
|
2899
|
+
this._instancesReceived = 0;
|
|
2900
|
+
this._instanceErrors = 0;
|
|
2895
2901
|
}
|
|
2896
2902
|
/** Returns the worker to idle and clears all association state. */
|
|
2897
2903
|
endAssociation() {
|
|
@@ -2901,6 +2907,9 @@ var Worker = class {
|
|
|
2901
2907
|
this._fileSizes.length = 0;
|
|
2902
2908
|
this._outputLines.length = 0;
|
|
2903
2909
|
this._pending.clear();
|
|
2910
|
+
this._instancePending.clear();
|
|
2911
|
+
this._instancesReceived = 0;
|
|
2912
|
+
this._instanceErrors = 0;
|
|
2904
2913
|
this._remoteSocket = void 0;
|
|
2905
2914
|
this._workerSocket = void 0;
|
|
2906
2915
|
}
|
|
@@ -2911,6 +2920,35 @@ var Worker = class {
|
|
|
2911
2920
|
this._pending.delete(promise);
|
|
2912
2921
|
});
|
|
2913
2922
|
}
|
|
2923
|
+
/** Tracks an in-flight instance parsing promise; auto-removes on completion. */
|
|
2924
|
+
trackInstance(promise) {
|
|
2925
|
+
this._instancePending.add(promise);
|
|
2926
|
+
void promise.finally(() => {
|
|
2927
|
+
this._instancePending.delete(promise);
|
|
2928
|
+
});
|
|
2929
|
+
}
|
|
2930
|
+
/** Records a successful instance parse. */
|
|
2931
|
+
recordInstanceSuccess() {
|
|
2932
|
+
this._instancesReceived++;
|
|
2933
|
+
}
|
|
2934
|
+
/** Records a failed instance parse. */
|
|
2935
|
+
recordInstanceError() {
|
|
2936
|
+
this._instanceErrors++;
|
|
2937
|
+
}
|
|
2938
|
+
/** Awaits all in-flight instance parsing promises. */
|
|
2939
|
+
async drainInstancePending() {
|
|
2940
|
+
if (this._instancePending.size > 0) {
|
|
2941
|
+
await Promise.all(this._instancePending);
|
|
2942
|
+
}
|
|
2943
|
+
}
|
|
2944
|
+
/** Number of successfully parsed instances in this association. */
|
|
2945
|
+
get instancesReceived() {
|
|
2946
|
+
return this._instancesReceived;
|
|
2947
|
+
}
|
|
2948
|
+
/** Number of failed instance parses in this association. */
|
|
2949
|
+
get instanceErrors() {
|
|
2950
|
+
return this._instanceErrors;
|
|
2951
|
+
}
|
|
2914
2952
|
/** Records a successfully received file path and its size. */
|
|
2915
2953
|
recordFile(filePath, size) {
|
|
2916
2954
|
this._files.push(filePath);
|
|
@@ -3082,7 +3120,16 @@ var DicomReceiver = class _DicomReceiver extends events.EventEmitter {
|
|
|
3082
3120
|
return this.on("INSTANCE_RECEIVED", listener);
|
|
3083
3121
|
}
|
|
3084
3122
|
/**
|
|
3085
|
-
* Registers a listener for
|
|
3123
|
+
* Registers a listener for DicomInstance.open failures.
|
|
3124
|
+
*
|
|
3125
|
+
* @param listener - Callback receiving instance error data
|
|
3126
|
+
* @returns this for chaining
|
|
3127
|
+
*/
|
|
3128
|
+
onInstanceError(listener) {
|
|
3129
|
+
return this.on("INSTANCE_ERROR", listener);
|
|
3130
|
+
}
|
|
3131
|
+
/**
|
|
3132
|
+
* Registers a listener for completed associations (file moves done).
|
|
3086
3133
|
*
|
|
3087
3134
|
* @param listener - Callback receiving association data
|
|
3088
3135
|
* @returns this for chaining
|
|
@@ -3090,6 +3137,15 @@ var DicomReceiver = class _DicomReceiver extends events.EventEmitter {
|
|
|
3090
3137
|
onAssociationComplete(listener) {
|
|
3091
3138
|
return this.on("ASSOCIATION_COMPLETE", listener);
|
|
3092
3139
|
}
|
|
3140
|
+
/**
|
|
3141
|
+
* Registers a listener for fully finalized associations (all parsing done).
|
|
3142
|
+
*
|
|
3143
|
+
* @param listener - Callback receiving finalized data with instance counts
|
|
3144
|
+
* @returns this for chaining
|
|
3145
|
+
*/
|
|
3146
|
+
onAssociationFinalized(listener) {
|
|
3147
|
+
return this.on("ASSOCIATION_FINALIZED", listener);
|
|
3148
|
+
}
|
|
3093
3149
|
/**
|
|
3094
3150
|
* Registers a listener for new associations (bubbled from workers).
|
|
3095
3151
|
*
|
|
@@ -3419,34 +3475,33 @@ var DicomReceiver = class _DicomReceiver extends events.EventEmitter {
|
|
|
3419
3475
|
calledAE: data.calledAE,
|
|
3420
3476
|
source: data.source
|
|
3421
3477
|
});
|
|
3422
|
-
|
|
3478
|
+
const instanceCtx = {
|
|
3479
|
+
filePath: finalPath,
|
|
3480
|
+
fileSize,
|
|
3481
|
+
associationId: ctx.associationId,
|
|
3482
|
+
associationDir: ctx.associationDir,
|
|
3483
|
+
callingAE: data.callingAE,
|
|
3484
|
+
calledAE: data.calledAE,
|
|
3485
|
+
source: data.source
|
|
3486
|
+
};
|
|
3487
|
+
worker.trackInstance(this.parseAndEmitInstance(worker, instanceCtx));
|
|
3423
3488
|
}
|
|
3424
|
-
/** Parses a DICOM file and emits INSTANCE_RECEIVED or
|
|
3425
|
-
|
|
3426
|
-
|
|
3489
|
+
/** Parses a DICOM file and emits INSTANCE_RECEIVED or INSTANCE_ERROR. */
|
|
3490
|
+
async parseAndEmitInstance(worker, ctx) {
|
|
3491
|
+
try {
|
|
3492
|
+
const openResult = await DicomInstance.open(ctx.filePath);
|
|
3427
3493
|
if (!openResult.ok) {
|
|
3428
|
-
|
|
3429
|
-
|
|
3430
|
-
filePath,
|
|
3431
|
-
associationId: ctx.associationId,
|
|
3432
|
-
associationDir: ctx.associationDir,
|
|
3433
|
-
callingAE: data.callingAE,
|
|
3434
|
-
calledAE: data.calledAE,
|
|
3435
|
-
source: data.source
|
|
3436
|
-
});
|
|
3494
|
+
worker.recordInstanceError();
|
|
3495
|
+
this.emit("INSTANCE_ERROR", { error: openResult.error, thrown: false, ...ctx });
|
|
3437
3496
|
return;
|
|
3438
3497
|
}
|
|
3439
|
-
|
|
3440
|
-
|
|
3441
|
-
|
|
3442
|
-
|
|
3443
|
-
|
|
3444
|
-
|
|
3445
|
-
|
|
3446
|
-
source: data.source,
|
|
3447
|
-
instance: openResult.value
|
|
3448
|
-
});
|
|
3449
|
-
});
|
|
3498
|
+
worker.recordInstanceSuccess();
|
|
3499
|
+
this.emit("INSTANCE_RECEIVED", { ...ctx, instance: openResult.value });
|
|
3500
|
+
} catch (thrown) {
|
|
3501
|
+
const error = thrown instanceof Error ? thrown : new Error(String(thrown));
|
|
3502
|
+
worker.recordInstanceError();
|
|
3503
|
+
this.emit("INSTANCE_ERROR", { error, thrown: true, ...ctx });
|
|
3504
|
+
}
|
|
3450
3505
|
}
|
|
3451
3506
|
/** Returns worker to idle pool on association complete, emits summary. */
|
|
3452
3507
|
wireAssociationComplete(worker) {
|
|
@@ -3454,10 +3509,12 @@ var DicomReceiver = class _DicomReceiver extends events.EventEmitter {
|
|
|
3454
3509
|
void this.finalizeAssociation(worker, data);
|
|
3455
3510
|
});
|
|
3456
3511
|
}
|
|
3457
|
-
/** Awaits
|
|
3512
|
+
/** Awaits file ops, emits ASSOCIATION_COMPLETE, awaits parsing, emits ASSOCIATION_FINALIZED. */
|
|
3458
3513
|
async finalizeAssociation(worker, data) {
|
|
3459
3514
|
await worker.drainPendingFiles();
|
|
3460
3515
|
this.emitAssociationComplete(worker, data);
|
|
3516
|
+
await worker.drainInstancePending();
|
|
3517
|
+
this.emitAssociationFinalized(worker, data);
|
|
3461
3518
|
worker.endAssociation();
|
|
3462
3519
|
void this.scaleDown();
|
|
3463
3520
|
}
|
|
@@ -3489,6 +3546,20 @@ var DicomReceiver = class _DicomReceiver extends events.EventEmitter {
|
|
|
3489
3546
|
output
|
|
3490
3547
|
});
|
|
3491
3548
|
}
|
|
3549
|
+
/** Emits ASSOCIATION_FINALIZED after all instance parsing is done. */
|
|
3550
|
+
emitAssociationFinalized(worker, data) {
|
|
3551
|
+
const ctx = worker.context;
|
|
3552
|
+
this.emit("ASSOCIATION_FINALIZED", {
|
|
3553
|
+
associationId: ctx?.associationId ?? data.associationId,
|
|
3554
|
+
associationDir: ctx?.associationDir ?? "",
|
|
3555
|
+
callingAE: data.callingAE,
|
|
3556
|
+
calledAE: data.calledAE,
|
|
3557
|
+
source: data.source,
|
|
3558
|
+
files: [...worker.files],
|
|
3559
|
+
instancesReceived: worker.instancesReceived,
|
|
3560
|
+
instanceErrors: worker.instanceErrors
|
|
3561
|
+
});
|
|
3562
|
+
}
|
|
3492
3563
|
/** Bubbles ASSOCIATION_RECEIVED from dcmrecv worker. */
|
|
3493
3564
|
wireAssociationReceived(worker) {
|
|
3494
3565
|
worker.dcmrecv.onEvent("ASSOCIATION_RECEIVED", (data) => {
|