@ubercode/dcmtk 0.6.5 → 0.7.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.
- 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 +68 -26
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +34 -2
- package/dist/index.d.ts +34 -2
- package/dist/index.js +68 -26
- 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 -5
- package/dist/tools.cjs.map +1 -1
- package/dist/tools.d.cts +2 -2
- package/dist/tools.d.ts +2 -2
- package/dist/tools.js +1 -5
- 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
|
@@ -33257,7 +33257,6 @@ var StorescuOptionsSchema = zod.z.object({
|
|
|
33257
33257
|
acseTimeout: zod.z.number().int().positive().optional(),
|
|
33258
33258
|
dimseTimeout: zod.z.number().int().positive().optional(),
|
|
33259
33259
|
noHostnameLookup: zod.z.boolean().optional(),
|
|
33260
|
-
noUidChecks: zod.z.boolean().optional(),
|
|
33261
33260
|
proposedTransferSyntax: zod.z.enum([
|
|
33262
33261
|
"uncompressed",
|
|
33263
33262
|
"littleEndian",
|
|
@@ -33299,9 +33298,6 @@ function pushNetworkArgs3(args, options) {
|
|
|
33299
33298
|
function buildArgs34(options) {
|
|
33300
33299
|
const args = [];
|
|
33301
33300
|
pushNetworkArgs3(args, options);
|
|
33302
|
-
if (options.noUidChecks === true) {
|
|
33303
|
-
args.push("--no-uid-checks");
|
|
33304
|
-
}
|
|
33305
33301
|
if (options.callingAETitle !== void 0) {
|
|
33306
33302
|
args.push("-aet", options.callingAETitle);
|
|
33307
33303
|
}
|
|
@@ -33342,7 +33338,7 @@ async function storescu(options) {
|
|
|
33342
33338
|
if (result.value.exitCode !== 0) {
|
|
33343
33339
|
return err(createToolError("storescu", args, result.value.exitCode, result.value.stderr));
|
|
33344
33340
|
}
|
|
33345
|
-
return ok({ success: true, stderr: result.value.stderr });
|
|
33341
|
+
return ok({ success: true, stdout: result.value.stdout, stderr: result.value.stderr });
|
|
33346
33342
|
}
|
|
33347
33343
|
var QueryModel = {
|
|
33348
33344
|
WORKLIST: "worklist",
|
|
@@ -36197,6 +36193,9 @@ var DicomReceiverOptionsSchema = zod.z.object({
|
|
|
36197
36193
|
acseTimeout: zod.z.number().int().positive().optional(),
|
|
36198
36194
|
dimseTimeout: zod.z.number().int().positive().optional(),
|
|
36199
36195
|
maxPdu: zod.z.number().int().min(4096).max(131072).optional(),
|
|
36196
|
+
filenameMode: zod.z.enum(["default", "unique", "short-unique", "system-time"]).optional(),
|
|
36197
|
+
filenameExtension: zod.z.string().min(1).optional(),
|
|
36198
|
+
storageMode: zod.z.enum(["normal", "bit-preserving", "ignore"]).optional(),
|
|
36200
36199
|
signal: zod.z.instanceof(AbortSignal).optional()
|
|
36201
36200
|
}).strict().refine((data) => (data.minPoolSize ?? DEFAULT_MIN_POOL_SIZE) <= (data.maxPoolSize ?? DEFAULT_MAX_POOL_SIZE), {
|
|
36202
36201
|
message: "minPoolSize must be <= maxPoolSize"
|
|
@@ -36518,7 +36517,10 @@ var DicomReceiver = class _DicomReceiver extends events.EventEmitter {
|
|
|
36518
36517
|
configProfile: this.options.configProfile,
|
|
36519
36518
|
acseTimeout: this.options.acseTimeout,
|
|
36520
36519
|
dimseTimeout: this.options.dimseTimeout,
|
|
36521
|
-
maxPdu: this.options.maxPdu
|
|
36520
|
+
maxPdu: this.options.maxPdu,
|
|
36521
|
+
filenameMode: this.options.filenameMode,
|
|
36522
|
+
filenameExtension: this.options.filenameExtension,
|
|
36523
|
+
storageMode: this.options.storageMode
|
|
36522
36524
|
});
|
|
36523
36525
|
}
|
|
36524
36526
|
/** Spawns a single Dcmrecv worker with an ephemeral port. */
|
|
@@ -36880,6 +36882,13 @@ var DicomSenderOptionsSchema = zod.z.object({
|
|
|
36880
36882
|
retryDelayMs: zod.z.number().int().min(0).optional(),
|
|
36881
36883
|
bucketFlushMs: zod.z.number().int().positive().optional(),
|
|
36882
36884
|
maxBucketSize: zod.z.number().int().min(1).optional(),
|
|
36885
|
+
maxPduReceive: zod.z.number().int().min(4096).max(131072).optional(),
|
|
36886
|
+
maxPduSend: zod.z.number().int().min(4096).max(131072).optional(),
|
|
36887
|
+
associationTimeout: zod.z.number().int().positive().optional(),
|
|
36888
|
+
acseTimeout: zod.z.number().int().positive().optional(),
|
|
36889
|
+
dimseTimeout: zod.z.number().int().positive().optional(),
|
|
36890
|
+
noHostnameLookup: zod.z.boolean().optional(),
|
|
36891
|
+
verbosity: zod.z.enum(["verbose", "debug"]).optional(),
|
|
36883
36892
|
signal: zod.z.instanceof(AbortSignal).optional()
|
|
36884
36893
|
}).strict();
|
|
36885
36894
|
function resolveConfig(options) {
|
|
@@ -36978,14 +36987,22 @@ var DicomSender = class _DicomSender extends events.EventEmitter {
|
|
|
36978
36987
|
if (files.length === 0) {
|
|
36979
36988
|
return Promise.resolve(err(new Error("DicomSender: no files provided")));
|
|
36980
36989
|
}
|
|
36981
|
-
const
|
|
36982
|
-
|
|
36990
|
+
const params = {
|
|
36991
|
+
timeoutMs: options?.timeoutMs ?? this.defaultTimeoutMs,
|
|
36992
|
+
maxRetries: options?.maxRetries ?? this.defaultMaxRetries,
|
|
36993
|
+
calledAETitle: options?.calledAETitle,
|
|
36994
|
+
callingAETitle: options?.callingAETitle
|
|
36995
|
+
};
|
|
36996
|
+
return this.dispatchSend(files, params);
|
|
36997
|
+
}
|
|
36998
|
+
/** Dispatches a send to the appropriate mode handler. */
|
|
36999
|
+
dispatchSend(files, params) {
|
|
36983
37000
|
switch (this.mode) {
|
|
36984
37001
|
case "single":
|
|
36985
37002
|
case "multiple":
|
|
36986
|
-
return this.enqueueSend(files,
|
|
37003
|
+
return this.enqueueSend(files, params);
|
|
36987
37004
|
case "bucket":
|
|
36988
|
-
return this.enqueueBucket(files,
|
|
37005
|
+
return this.enqueueBucket(files, params);
|
|
36989
37006
|
default:
|
|
36990
37007
|
assertUnreachable(this.mode);
|
|
36991
37008
|
}
|
|
@@ -37080,14 +37097,21 @@ var DicomSender = class _DicomSender extends events.EventEmitter {
|
|
|
37080
37097
|
// Single/Multiple mode: queue-based dispatch
|
|
37081
37098
|
// -----------------------------------------------------------------------
|
|
37082
37099
|
/** Enqueues a send and dispatches immediately if capacity allows. */
|
|
37083
|
-
enqueueSend(files,
|
|
37100
|
+
enqueueSend(files, params) {
|
|
37084
37101
|
return new Promise((resolve) => {
|
|
37085
37102
|
const totalQueued = this.queue.length + this.currentBucket.length;
|
|
37086
37103
|
if (totalQueued >= this.maxQueueLength) {
|
|
37087
37104
|
resolve(err(new Error("DicomSender: queue full")));
|
|
37088
37105
|
return;
|
|
37089
37106
|
}
|
|
37090
|
-
const entry = {
|
|
37107
|
+
const entry = {
|
|
37108
|
+
files,
|
|
37109
|
+
timeoutMs: params.timeoutMs,
|
|
37110
|
+
maxRetries: params.maxRetries,
|
|
37111
|
+
calledAETitle: params.calledAETitle,
|
|
37112
|
+
callingAETitle: params.callingAETitle,
|
|
37113
|
+
resolve
|
|
37114
|
+
};
|
|
37091
37115
|
if (this.activeAssociations < this.effectiveMaxAssociations) {
|
|
37092
37116
|
void this.executeEntry(entry);
|
|
37093
37117
|
} else {
|
|
@@ -37107,14 +37131,15 @@ var DicomSender = class _DicomSender extends events.EventEmitter {
|
|
|
37107
37131
|
// Bucket mode: accumulate-then-flush
|
|
37108
37132
|
// -----------------------------------------------------------------------
|
|
37109
37133
|
/** Adds files to the current bucket and triggers flush if full. */
|
|
37110
|
-
enqueueBucket(files,
|
|
37134
|
+
enqueueBucket(files, params) {
|
|
37111
37135
|
return new Promise((resolve) => {
|
|
37112
37136
|
const totalQueued = this.queue.length + this.currentBucket.length;
|
|
37113
37137
|
if (totalQueued >= this.maxQueueLength) {
|
|
37114
37138
|
resolve(err(new Error("DicomSender: queue full")));
|
|
37115
37139
|
return;
|
|
37116
37140
|
}
|
|
37117
|
-
|
|
37141
|
+
const { timeoutMs, maxRetries, calledAETitle, callingAETitle } = params;
|
|
37142
|
+
this.currentBucket.push({ files, resolve, timeoutMs, maxRetries, calledAETitle, callingAETitle });
|
|
37118
37143
|
const totalFiles = this.countBucketFiles();
|
|
37119
37144
|
if (totalFiles >= this.maxBucketSize) {
|
|
37120
37145
|
this.clearBucketTimer();
|
|
@@ -37154,6 +37179,8 @@ var DicomSender = class _DicomSender extends events.EventEmitter {
|
|
|
37154
37179
|
files: allFiles,
|
|
37155
37180
|
timeoutMs,
|
|
37156
37181
|
maxRetries,
|
|
37182
|
+
calledAETitle: entries[0]?.calledAETitle,
|
|
37183
|
+
callingAETitle: entries[0]?.callingAETitle,
|
|
37157
37184
|
resolve: (result) => {
|
|
37158
37185
|
for (let i = 0; i < entries.length; i++) {
|
|
37159
37186
|
entries[i].resolve(result);
|
|
@@ -37189,17 +37216,24 @@ var DicomSender = class _DicomSender extends events.EventEmitter {
|
|
|
37189
37216
|
this.activeAssociations++;
|
|
37190
37217
|
const startMs = Date.now();
|
|
37191
37218
|
const maxAttempts = entry.maxRetries + 1;
|
|
37192
|
-
const
|
|
37193
|
-
if (
|
|
37219
|
+
const failure = await this.attemptSend(entry, maxAttempts, startMs);
|
|
37220
|
+
if (failure === void 0) return;
|
|
37194
37221
|
this.activeAssociations--;
|
|
37195
37222
|
this.recordFailure();
|
|
37196
|
-
this.emit("SEND_FAILED", {
|
|
37197
|
-
|
|
37223
|
+
this.emit("SEND_FAILED", {
|
|
37224
|
+
files: entry.files,
|
|
37225
|
+
error: failure.error,
|
|
37226
|
+
attempts: maxAttempts,
|
|
37227
|
+
stdout: failure.output.stdout,
|
|
37228
|
+
stderr: failure.output.stderr
|
|
37229
|
+
});
|
|
37230
|
+
entry.resolve(err(failure.error));
|
|
37198
37231
|
this.drainQueue();
|
|
37199
37232
|
}
|
|
37200
|
-
/** Attempts storescu up to maxAttempts times. Returns undefined on success, or
|
|
37233
|
+
/** Attempts storescu up to maxAttempts times. Returns undefined on success, or failure info. */
|
|
37201
37234
|
async attemptSend(entry, maxAttempts, startMs) {
|
|
37202
37235
|
let lastError;
|
|
37236
|
+
const lastOutput = { stdout: "", stderr: "" };
|
|
37203
37237
|
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
37204
37238
|
if (this.isStopped) {
|
|
37205
37239
|
this.activeAssociations--;
|
|
@@ -37208,7 +37242,7 @@ var DicomSender = class _DicomSender extends events.EventEmitter {
|
|
|
37208
37242
|
}
|
|
37209
37243
|
const result = await this.callStorescu(entry);
|
|
37210
37244
|
if (result.ok) {
|
|
37211
|
-
this.handleSendSuccess(entry, startMs);
|
|
37245
|
+
this.handleSendSuccess(entry, startMs, result.value);
|
|
37212
37246
|
return void 0;
|
|
37213
37247
|
}
|
|
37214
37248
|
lastError = result.error;
|
|
@@ -37216,7 +37250,7 @@ var DicomSender = class _DicomSender extends events.EventEmitter {
|
|
|
37216
37250
|
await delay2(this.retryDelayMs * (attempt + 1));
|
|
37217
37251
|
}
|
|
37218
37252
|
}
|
|
37219
|
-
return lastError ?? new Error("DicomSender: send failed");
|
|
37253
|
+
return { error: lastError ?? new Error("DicomSender: send failed"), output: lastOutput };
|
|
37220
37254
|
}
|
|
37221
37255
|
/** Calls storescu with the configured options. */
|
|
37222
37256
|
callStorescu(entry) {
|
|
@@ -37224,20 +37258,28 @@ var DicomSender = class _DicomSender extends events.EventEmitter {
|
|
|
37224
37258
|
host: this.options.host,
|
|
37225
37259
|
port: this.options.port,
|
|
37226
37260
|
files: [...entry.files],
|
|
37227
|
-
calledAETitle: this.options.calledAETitle,
|
|
37228
|
-
callingAETitle: this.options.callingAETitle,
|
|
37261
|
+
calledAETitle: entry.calledAETitle ?? this.options.calledAETitle,
|
|
37262
|
+
callingAETitle: entry.callingAETitle ?? this.options.callingAETitle,
|
|
37229
37263
|
proposedTransferSyntax: this.options.proposedTransferSyntax,
|
|
37264
|
+
maxPduReceive: this.options.maxPduReceive,
|
|
37265
|
+
maxPduSend: this.options.maxPduSend,
|
|
37266
|
+
associationTimeout: this.options.associationTimeout,
|
|
37267
|
+
acseTimeout: this.options.acseTimeout,
|
|
37268
|
+
dimseTimeout: this.options.dimseTimeout,
|
|
37269
|
+
noHostnameLookup: this.options.noHostnameLookup,
|
|
37270
|
+
verbosity: this.options.verbosity,
|
|
37230
37271
|
timeoutMs: entry.timeoutMs,
|
|
37231
37272
|
signal: this.options.signal
|
|
37232
37273
|
});
|
|
37233
37274
|
}
|
|
37234
37275
|
/** Handles a successful send: updates state, emits event, resolves promise. */
|
|
37235
|
-
handleSendSuccess(entry, startMs) {
|
|
37276
|
+
handleSendSuccess(entry, startMs, output) {
|
|
37236
37277
|
this.activeAssociations--;
|
|
37237
37278
|
const durationMs = Date.now() - startMs;
|
|
37238
37279
|
this.recordSuccess();
|
|
37239
|
-
|
|
37240
|
-
|
|
37280
|
+
const data = { files: entry.files, fileCount: entry.files.length, durationMs, stdout: output.stdout, stderr: output.stderr };
|
|
37281
|
+
this.emit("SEND_COMPLETE", data);
|
|
37282
|
+
entry.resolve(ok(data));
|
|
37241
37283
|
this.drainQueue();
|
|
37242
37284
|
}
|
|
37243
37285
|
// -----------------------------------------------------------------------
|