@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--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 +91 -14
- 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 +91 -14
- package/dist/index.js.map +1 -1
- package/dist/servers.cjs +91 -14
- 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 +91 -14
- 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,28 +3475,33 @@ var DicomReceiver = class _DicomReceiver extends events.EventEmitter {
|
|
|
3419
3475
|
calledAE: data.calledAE,
|
|
3420
3476
|
source: data.source
|
|
3421
3477
|
});
|
|
3422
|
-
|
|
3423
|
-
|
|
3424
|
-
|
|
3425
|
-
emitInstanceReceived(filePath, fileSize, data, ctx) {
|
|
3426
|
-
const errorCtx = {
|
|
3427
|
-
filePath,
|
|
3478
|
+
const instanceCtx = {
|
|
3479
|
+
filePath: finalPath,
|
|
3480
|
+
fileSize,
|
|
3428
3481
|
associationId: ctx.associationId,
|
|
3429
3482
|
associationDir: ctx.associationDir,
|
|
3430
3483
|
callingAE: data.callingAE,
|
|
3431
3484
|
calledAE: data.calledAE,
|
|
3432
3485
|
source: data.source
|
|
3433
3486
|
};
|
|
3434
|
-
|
|
3487
|
+
worker.trackInstance(this.parseAndEmitInstance(worker, instanceCtx));
|
|
3488
|
+
}
|
|
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);
|
|
3435
3493
|
if (!openResult.ok) {
|
|
3436
|
-
|
|
3494
|
+
worker.recordInstanceError();
|
|
3495
|
+
this.emit("INSTANCE_ERROR", { error: openResult.error, thrown: false, ...ctx });
|
|
3437
3496
|
return;
|
|
3438
3497
|
}
|
|
3439
|
-
|
|
3440
|
-
|
|
3498
|
+
worker.recordInstanceSuccess();
|
|
3499
|
+
this.emit("INSTANCE_RECEIVED", { ...ctx, instance: openResult.value });
|
|
3500
|
+
} catch (thrown) {
|
|
3441
3501
|
const error = thrown instanceof Error ? thrown : new Error(String(thrown));
|
|
3442
|
-
|
|
3443
|
-
|
|
3502
|
+
worker.recordInstanceError();
|
|
3503
|
+
this.emit("INSTANCE_ERROR", { error, thrown: true, ...ctx });
|
|
3504
|
+
}
|
|
3444
3505
|
}
|
|
3445
3506
|
/** Returns worker to idle pool on association complete, emits summary. */
|
|
3446
3507
|
wireAssociationComplete(worker) {
|
|
@@ -3448,10 +3509,12 @@ var DicomReceiver = class _DicomReceiver extends events.EventEmitter {
|
|
|
3448
3509
|
void this.finalizeAssociation(worker, data);
|
|
3449
3510
|
});
|
|
3450
3511
|
}
|
|
3451
|
-
/** Awaits
|
|
3512
|
+
/** Awaits file ops, emits ASSOCIATION_COMPLETE, awaits parsing, emits ASSOCIATION_FINALIZED. */
|
|
3452
3513
|
async finalizeAssociation(worker, data) {
|
|
3453
3514
|
await worker.drainPendingFiles();
|
|
3454
3515
|
this.emitAssociationComplete(worker, data);
|
|
3516
|
+
await worker.drainInstancePending();
|
|
3517
|
+
this.emitAssociationFinalized(worker, data);
|
|
3455
3518
|
worker.endAssociation();
|
|
3456
3519
|
void this.scaleDown();
|
|
3457
3520
|
}
|
|
@@ -3483,6 +3546,20 @@ var DicomReceiver = class _DicomReceiver extends events.EventEmitter {
|
|
|
3483
3546
|
output
|
|
3484
3547
|
});
|
|
3485
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
|
+
}
|
|
3486
3563
|
/** Bubbles ASSOCIATION_RECEIVED from dcmrecv worker. */
|
|
3487
3564
|
wireAssociationReceived(worker) {
|
|
3488
3565
|
worker.dcmrecv.onEvent("ASSOCIATION_RECEIVED", (data) => {
|