@ubercode/dcmtk 0.6.5 → 0.7.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_ew9kha.d.cts → index-AYvUunlI.d.cts} +6 -0
- package/dist/{index-DHsEm87K.d.ts → index-C20fLU5U.d.ts} +6 -0
- package/dist/index.cjs +70 -22
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +36 -2
- package/dist/index.d.ts +36 -2
- package/dist/index.js +70 -22
- package/dist/index.js.map +1 -1
- package/dist/servers.cjs +7 -1
- 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 +7 -1
- package/dist/servers.js.map +1 -1
- package/dist/tools.cjs +1 -1
- package/dist/tools.cjs.map +1 -1
- package/dist/tools.d.cts +2 -0
- package/dist/tools.d.ts +2 -0
- package/dist/tools.js +1 -1
- package/dist/tools.js.map +1 -1
- package/package.json +1 -1
|
@@ -1569,6 +1569,12 @@ interface DicomReceiverOptions {
|
|
|
1569
1569
|
readonly dimseTimeout?: number | undefined;
|
|
1570
1570
|
/** Maximum PDU receive size (passed through to Dcmrecv workers). */
|
|
1571
1571
|
readonly maxPdu?: number | undefined;
|
|
1572
|
+
/** Filename generation mode for received files (passed through to Dcmrecv workers). */
|
|
1573
|
+
readonly filenameMode?: FilenameModeValue | undefined;
|
|
1574
|
+
/** Extension appended to received filenames, e.g. `'.dcm'` (passed through to Dcmrecv workers). */
|
|
1575
|
+
readonly filenameExtension?: string | undefined;
|
|
1576
|
+
/** Storage mode for received files (passed through to Dcmrecv workers). */
|
|
1577
|
+
readonly storageMode?: StorageModeValue | undefined;
|
|
1572
1578
|
/** AbortSignal for external cancellation. */
|
|
1573
1579
|
readonly signal?: AbortSignal | undefined;
|
|
1574
1580
|
}
|
|
@@ -1569,6 +1569,12 @@ interface DicomReceiverOptions {
|
|
|
1569
1569
|
readonly dimseTimeout?: number | undefined;
|
|
1570
1570
|
/** Maximum PDU receive size (passed through to Dcmrecv workers). */
|
|
1571
1571
|
readonly maxPdu?: number | undefined;
|
|
1572
|
+
/** Filename generation mode for received files (passed through to Dcmrecv workers). */
|
|
1573
|
+
readonly filenameMode?: FilenameModeValue | undefined;
|
|
1574
|
+
/** Extension appended to received filenames, e.g. `'.dcm'` (passed through to Dcmrecv workers). */
|
|
1575
|
+
readonly filenameExtension?: string | undefined;
|
|
1576
|
+
/** Storage mode for received files (passed through to Dcmrecv workers). */
|
|
1577
|
+
readonly storageMode?: StorageModeValue | undefined;
|
|
1572
1578
|
/** AbortSignal for external cancellation. */
|
|
1573
1579
|
readonly signal?: AbortSignal | undefined;
|
|
1574
1580
|
}
|
package/dist/index.cjs
CHANGED
|
@@ -33342,7 +33342,7 @@ async function storescu(options) {
|
|
|
33342
33342
|
if (result.value.exitCode !== 0) {
|
|
33343
33343
|
return err(createToolError("storescu", args, result.value.exitCode, result.value.stderr));
|
|
33344
33344
|
}
|
|
33345
|
-
return ok({ success: true, stderr: result.value.stderr });
|
|
33345
|
+
return ok({ success: true, stdout: result.value.stdout, stderr: result.value.stderr });
|
|
33346
33346
|
}
|
|
33347
33347
|
var QueryModel = {
|
|
33348
33348
|
WORKLIST: "worklist",
|
|
@@ -36197,6 +36197,9 @@ var DicomReceiverOptionsSchema = zod.z.object({
|
|
|
36197
36197
|
acseTimeout: zod.z.number().int().positive().optional(),
|
|
36198
36198
|
dimseTimeout: zod.z.number().int().positive().optional(),
|
|
36199
36199
|
maxPdu: zod.z.number().int().min(4096).max(131072).optional(),
|
|
36200
|
+
filenameMode: zod.z.enum(["default", "unique", "short-unique", "system-time"]).optional(),
|
|
36201
|
+
filenameExtension: zod.z.string().min(1).optional(),
|
|
36202
|
+
storageMode: zod.z.enum(["normal", "bit-preserving", "ignore"]).optional(),
|
|
36200
36203
|
signal: zod.z.instanceof(AbortSignal).optional()
|
|
36201
36204
|
}).strict().refine((data) => (data.minPoolSize ?? DEFAULT_MIN_POOL_SIZE) <= (data.maxPoolSize ?? DEFAULT_MAX_POOL_SIZE), {
|
|
36202
36205
|
message: "minPoolSize must be <= maxPoolSize"
|
|
@@ -36518,7 +36521,10 @@ var DicomReceiver = class _DicomReceiver extends events.EventEmitter {
|
|
|
36518
36521
|
configProfile: this.options.configProfile,
|
|
36519
36522
|
acseTimeout: this.options.acseTimeout,
|
|
36520
36523
|
dimseTimeout: this.options.dimseTimeout,
|
|
36521
|
-
maxPdu: this.options.maxPdu
|
|
36524
|
+
maxPdu: this.options.maxPdu,
|
|
36525
|
+
filenameMode: this.options.filenameMode,
|
|
36526
|
+
filenameExtension: this.options.filenameExtension,
|
|
36527
|
+
storageMode: this.options.storageMode
|
|
36522
36528
|
});
|
|
36523
36529
|
}
|
|
36524
36530
|
/** Spawns a single Dcmrecv worker with an ephemeral port. */
|
|
@@ -36880,6 +36886,14 @@ var DicomSenderOptionsSchema = zod.z.object({
|
|
|
36880
36886
|
retryDelayMs: zod.z.number().int().min(0).optional(),
|
|
36881
36887
|
bucketFlushMs: zod.z.number().int().positive().optional(),
|
|
36882
36888
|
maxBucketSize: zod.z.number().int().min(1).optional(),
|
|
36889
|
+
maxPduReceive: zod.z.number().int().min(4096).max(131072).optional(),
|
|
36890
|
+
maxPduSend: zod.z.number().int().min(4096).max(131072).optional(),
|
|
36891
|
+
associationTimeout: zod.z.number().int().positive().optional(),
|
|
36892
|
+
acseTimeout: zod.z.number().int().positive().optional(),
|
|
36893
|
+
dimseTimeout: zod.z.number().int().positive().optional(),
|
|
36894
|
+
noHostnameLookup: zod.z.boolean().optional(),
|
|
36895
|
+
noUidChecks: zod.z.boolean().optional(),
|
|
36896
|
+
verbosity: zod.z.enum(["verbose", "debug"]).optional(),
|
|
36883
36897
|
signal: zod.z.instanceof(AbortSignal).optional()
|
|
36884
36898
|
}).strict();
|
|
36885
36899
|
function resolveConfig(options) {
|
|
@@ -36978,14 +36992,22 @@ var DicomSender = class _DicomSender extends events.EventEmitter {
|
|
|
36978
36992
|
if (files.length === 0) {
|
|
36979
36993
|
return Promise.resolve(err(new Error("DicomSender: no files provided")));
|
|
36980
36994
|
}
|
|
36981
|
-
const
|
|
36982
|
-
|
|
36995
|
+
const params = {
|
|
36996
|
+
timeoutMs: options?.timeoutMs ?? this.defaultTimeoutMs,
|
|
36997
|
+
maxRetries: options?.maxRetries ?? this.defaultMaxRetries,
|
|
36998
|
+
calledAETitle: options?.calledAETitle,
|
|
36999
|
+
callingAETitle: options?.callingAETitle
|
|
37000
|
+
};
|
|
37001
|
+
return this.dispatchSend(files, params);
|
|
37002
|
+
}
|
|
37003
|
+
/** Dispatches a send to the appropriate mode handler. */
|
|
37004
|
+
dispatchSend(files, params) {
|
|
36983
37005
|
switch (this.mode) {
|
|
36984
37006
|
case "single":
|
|
36985
37007
|
case "multiple":
|
|
36986
|
-
return this.enqueueSend(files,
|
|
37008
|
+
return this.enqueueSend(files, params);
|
|
36987
37009
|
case "bucket":
|
|
36988
|
-
return this.enqueueBucket(files,
|
|
37010
|
+
return this.enqueueBucket(files, params);
|
|
36989
37011
|
default:
|
|
36990
37012
|
assertUnreachable(this.mode);
|
|
36991
37013
|
}
|
|
@@ -37080,14 +37102,21 @@ var DicomSender = class _DicomSender extends events.EventEmitter {
|
|
|
37080
37102
|
// Single/Multiple mode: queue-based dispatch
|
|
37081
37103
|
// -----------------------------------------------------------------------
|
|
37082
37104
|
/** Enqueues a send and dispatches immediately if capacity allows. */
|
|
37083
|
-
enqueueSend(files,
|
|
37105
|
+
enqueueSend(files, params) {
|
|
37084
37106
|
return new Promise((resolve) => {
|
|
37085
37107
|
const totalQueued = this.queue.length + this.currentBucket.length;
|
|
37086
37108
|
if (totalQueued >= this.maxQueueLength) {
|
|
37087
37109
|
resolve(err(new Error("DicomSender: queue full")));
|
|
37088
37110
|
return;
|
|
37089
37111
|
}
|
|
37090
|
-
const entry = {
|
|
37112
|
+
const entry = {
|
|
37113
|
+
files,
|
|
37114
|
+
timeoutMs: params.timeoutMs,
|
|
37115
|
+
maxRetries: params.maxRetries,
|
|
37116
|
+
calledAETitle: params.calledAETitle,
|
|
37117
|
+
callingAETitle: params.callingAETitle,
|
|
37118
|
+
resolve
|
|
37119
|
+
};
|
|
37091
37120
|
if (this.activeAssociations < this.effectiveMaxAssociations) {
|
|
37092
37121
|
void this.executeEntry(entry);
|
|
37093
37122
|
} else {
|
|
@@ -37107,14 +37136,15 @@ var DicomSender = class _DicomSender extends events.EventEmitter {
|
|
|
37107
37136
|
// Bucket mode: accumulate-then-flush
|
|
37108
37137
|
// -----------------------------------------------------------------------
|
|
37109
37138
|
/** Adds files to the current bucket and triggers flush if full. */
|
|
37110
|
-
enqueueBucket(files,
|
|
37139
|
+
enqueueBucket(files, params) {
|
|
37111
37140
|
return new Promise((resolve) => {
|
|
37112
37141
|
const totalQueued = this.queue.length + this.currentBucket.length;
|
|
37113
37142
|
if (totalQueued >= this.maxQueueLength) {
|
|
37114
37143
|
resolve(err(new Error("DicomSender: queue full")));
|
|
37115
37144
|
return;
|
|
37116
37145
|
}
|
|
37117
|
-
|
|
37146
|
+
const { timeoutMs, maxRetries, calledAETitle, callingAETitle } = params;
|
|
37147
|
+
this.currentBucket.push({ files, resolve, timeoutMs, maxRetries, calledAETitle, callingAETitle });
|
|
37118
37148
|
const totalFiles = this.countBucketFiles();
|
|
37119
37149
|
if (totalFiles >= this.maxBucketSize) {
|
|
37120
37150
|
this.clearBucketTimer();
|
|
@@ -37154,6 +37184,8 @@ var DicomSender = class _DicomSender extends events.EventEmitter {
|
|
|
37154
37184
|
files: allFiles,
|
|
37155
37185
|
timeoutMs,
|
|
37156
37186
|
maxRetries,
|
|
37187
|
+
calledAETitle: entries[0]?.calledAETitle,
|
|
37188
|
+
callingAETitle: entries[0]?.callingAETitle,
|
|
37157
37189
|
resolve: (result) => {
|
|
37158
37190
|
for (let i = 0; i < entries.length; i++) {
|
|
37159
37191
|
entries[i].resolve(result);
|
|
@@ -37189,17 +37221,24 @@ var DicomSender = class _DicomSender extends events.EventEmitter {
|
|
|
37189
37221
|
this.activeAssociations++;
|
|
37190
37222
|
const startMs = Date.now();
|
|
37191
37223
|
const maxAttempts = entry.maxRetries + 1;
|
|
37192
|
-
const
|
|
37193
|
-
if (
|
|
37224
|
+
const failure = await this.attemptSend(entry, maxAttempts, startMs);
|
|
37225
|
+
if (failure === void 0) return;
|
|
37194
37226
|
this.activeAssociations--;
|
|
37195
37227
|
this.recordFailure();
|
|
37196
|
-
this.emit("SEND_FAILED", {
|
|
37197
|
-
|
|
37228
|
+
this.emit("SEND_FAILED", {
|
|
37229
|
+
files: entry.files,
|
|
37230
|
+
error: failure.error,
|
|
37231
|
+
attempts: maxAttempts,
|
|
37232
|
+
stdout: failure.output.stdout,
|
|
37233
|
+
stderr: failure.output.stderr
|
|
37234
|
+
});
|
|
37235
|
+
entry.resolve(err(failure.error));
|
|
37198
37236
|
this.drainQueue();
|
|
37199
37237
|
}
|
|
37200
|
-
/** Attempts storescu up to maxAttempts times. Returns undefined on success, or
|
|
37238
|
+
/** Attempts storescu up to maxAttempts times. Returns undefined on success, or failure info. */
|
|
37201
37239
|
async attemptSend(entry, maxAttempts, startMs) {
|
|
37202
37240
|
let lastError;
|
|
37241
|
+
const lastOutput = { stdout: "", stderr: "" };
|
|
37203
37242
|
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
37204
37243
|
if (this.isStopped) {
|
|
37205
37244
|
this.activeAssociations--;
|
|
@@ -37208,7 +37247,7 @@ var DicomSender = class _DicomSender extends events.EventEmitter {
|
|
|
37208
37247
|
}
|
|
37209
37248
|
const result = await this.callStorescu(entry);
|
|
37210
37249
|
if (result.ok) {
|
|
37211
|
-
this.handleSendSuccess(entry, startMs);
|
|
37250
|
+
this.handleSendSuccess(entry, startMs, result.value);
|
|
37212
37251
|
return void 0;
|
|
37213
37252
|
}
|
|
37214
37253
|
lastError = result.error;
|
|
@@ -37216,7 +37255,7 @@ var DicomSender = class _DicomSender extends events.EventEmitter {
|
|
|
37216
37255
|
await delay2(this.retryDelayMs * (attempt + 1));
|
|
37217
37256
|
}
|
|
37218
37257
|
}
|
|
37219
|
-
return lastError ?? new Error("DicomSender: send failed");
|
|
37258
|
+
return { error: lastError ?? new Error("DicomSender: send failed"), output: lastOutput };
|
|
37220
37259
|
}
|
|
37221
37260
|
/** Calls storescu with the configured options. */
|
|
37222
37261
|
callStorescu(entry) {
|
|
@@ -37224,20 +37263,29 @@ var DicomSender = class _DicomSender extends events.EventEmitter {
|
|
|
37224
37263
|
host: this.options.host,
|
|
37225
37264
|
port: this.options.port,
|
|
37226
37265
|
files: [...entry.files],
|
|
37227
|
-
calledAETitle: this.options.calledAETitle,
|
|
37228
|
-
callingAETitle: this.options.callingAETitle,
|
|
37266
|
+
calledAETitle: entry.calledAETitle ?? this.options.calledAETitle,
|
|
37267
|
+
callingAETitle: entry.callingAETitle ?? this.options.callingAETitle,
|
|
37229
37268
|
proposedTransferSyntax: this.options.proposedTransferSyntax,
|
|
37269
|
+
maxPduReceive: this.options.maxPduReceive,
|
|
37270
|
+
maxPduSend: this.options.maxPduSend,
|
|
37271
|
+
associationTimeout: this.options.associationTimeout,
|
|
37272
|
+
acseTimeout: this.options.acseTimeout,
|
|
37273
|
+
dimseTimeout: this.options.dimseTimeout,
|
|
37274
|
+
noHostnameLookup: this.options.noHostnameLookup,
|
|
37275
|
+
noUidChecks: this.options.noUidChecks,
|
|
37276
|
+
verbosity: this.options.verbosity,
|
|
37230
37277
|
timeoutMs: entry.timeoutMs,
|
|
37231
37278
|
signal: this.options.signal
|
|
37232
37279
|
});
|
|
37233
37280
|
}
|
|
37234
37281
|
/** Handles a successful send: updates state, emits event, resolves promise. */
|
|
37235
|
-
handleSendSuccess(entry, startMs) {
|
|
37282
|
+
handleSendSuccess(entry, startMs, output) {
|
|
37236
37283
|
this.activeAssociations--;
|
|
37237
37284
|
const durationMs = Date.now() - startMs;
|
|
37238
37285
|
this.recordSuccess();
|
|
37239
|
-
|
|
37240
|
-
|
|
37286
|
+
const data = { files: entry.files, fileCount: entry.files.length, durationMs, stdout: output.stdout, stderr: output.stderr };
|
|
37287
|
+
this.emit("SEND_COMPLETE", data);
|
|
37288
|
+
entry.resolve(ok(data));
|
|
37241
37289
|
this.drainQueue();
|
|
37242
37290
|
}
|
|
37243
37291
|
// -----------------------------------------------------------------------
|