@ubercode/dcmtk 0.12.0 → 0.13.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/{DicomInstance-CxLKC-oM.d.cts → DicomInstance-BGXtON9T.d.cts} +2 -0
- package/dist/{DicomInstance-BKUiir0G.d.ts → DicomInstance-DGWB2mfD.d.ts} +2 -0
- package/dist/dicom.cjs +30 -16
- package/dist/dicom.cjs.map +1 -1
- package/dist/dicom.d.cts +2 -2
- package/dist/dicom.d.ts +2 -2
- package/dist/dicom.js +30 -16
- package/dist/dicom.js.map +1 -1
- package/dist/{index-DV8HaHEX.d.cts → index-B1eynCVv.d.cts} +4 -1
- package/dist/{index-B5FQoIqM.d.ts → index-DM0yFtPO.d.ts} +4 -1
- package/dist/index.cjs +39 -17
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +39 -17
- package/dist/index.js.map +1 -1
- package/dist/servers.cjs +39 -17
- package/dist/servers.cjs.map +1 -1
- package/dist/servers.d.cts +2 -2
- package/dist/servers.d.ts +2 -2
- package/dist/servers.js +39 -17
- package/dist/servers.js.map +1 -1
- package/dist/tools.cjs +28 -15
- 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 +28 -15
- package/dist/tools.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { L as LineSource, R as Result } from './types-Cgumy1N4.cjs';
|
|
2
2
|
import { EventEmitter } from 'node:events';
|
|
3
3
|
import * as net from 'node:net';
|
|
4
|
-
import { d as DicomInstance } from './DicomInstance-
|
|
4
|
+
import { d as DicomInstance, e as DicomOpenOptions } from './DicomInstance-BGXtON9T.cjs';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Base class for long-lived DCMTK processes (servers).
|
|
@@ -1622,6 +1622,8 @@ interface DicomReceiverOptions {
|
|
|
1622
1622
|
readonly filenameExtension?: string | undefined;
|
|
1623
1623
|
/** Storage mode for received files (passed through to Dcmrecv workers). */
|
|
1624
1624
|
readonly storageMode?: StorageModeValue | undefined;
|
|
1625
|
+
/** Options passed to DicomInstance.open() for each received file. Defaults charsetFallback to `'Latin1'`. */
|
|
1626
|
+
readonly instanceOpenOptions?: DicomOpenOptions | undefined;
|
|
1625
1627
|
/** AbortSignal for external cancellation. */
|
|
1626
1628
|
readonly signal?: AbortSignal | undefined;
|
|
1627
1629
|
}
|
|
@@ -1654,6 +1656,7 @@ declare class DicomReceiver extends EventEmitter<DicomReceiverEventMap> {
|
|
|
1654
1656
|
private readonly minPoolSize;
|
|
1655
1657
|
private readonly maxPoolSize;
|
|
1656
1658
|
private readonly connectionTimeoutMs;
|
|
1659
|
+
private readonly resolvedInstanceOpenOptions;
|
|
1657
1660
|
private readonly workers;
|
|
1658
1661
|
private tcpServer;
|
|
1659
1662
|
private associationCounter;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { L as LineSource, R as Result } from './types-Cgumy1N4.js';
|
|
2
2
|
import { EventEmitter } from 'node:events';
|
|
3
3
|
import * as net from 'node:net';
|
|
4
|
-
import { d as DicomInstance } from './DicomInstance-
|
|
4
|
+
import { d as DicomInstance, e as DicomOpenOptions } from './DicomInstance-DGWB2mfD.js';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Base class for long-lived DCMTK processes (servers).
|
|
@@ -1622,6 +1622,8 @@ interface DicomReceiverOptions {
|
|
|
1622
1622
|
readonly filenameExtension?: string | undefined;
|
|
1623
1623
|
/** Storage mode for received files (passed through to Dcmrecv workers). */
|
|
1624
1624
|
readonly storageMode?: StorageModeValue | undefined;
|
|
1625
|
+
/** Options passed to DicomInstance.open() for each received file. Defaults charsetFallback to `'Latin1'`. */
|
|
1626
|
+
readonly instanceOpenOptions?: DicomOpenOptions | undefined;
|
|
1625
1627
|
/** AbortSignal for external cancellation. */
|
|
1626
1628
|
readonly signal?: AbortSignal | undefined;
|
|
1627
1629
|
}
|
|
@@ -1654,6 +1656,7 @@ declare class DicomReceiver extends EventEmitter<DicomReceiverEventMap> {
|
|
|
1654
1656
|
private readonly minPoolSize;
|
|
1655
1657
|
private readonly maxPoolSize;
|
|
1656
1658
|
private readonly connectionTimeoutMs;
|
|
1659
|
+
private readonly resolvedInstanceOpenOptions;
|
|
1657
1660
|
private readonly workers;
|
|
1658
1661
|
private tcpServer;
|
|
1659
1662
|
private associationCounter;
|
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 {
|
|
@@ -31463,6 +31468,7 @@ var Dcm2jsonOptionsSchema = zod.z.object({
|
|
|
31463
31468
|
signal: zod.z.instanceof(AbortSignal).optional(),
|
|
31464
31469
|
directOnly: zod.z.boolean().optional(),
|
|
31465
31470
|
charsetAssume: zod.z.string().min(1).optional(),
|
|
31471
|
+
charsetFallback: zod.z.string().min(1).optional(),
|
|
31466
31472
|
verbosity: zod.z.enum(["verbose", "debug"]).optional()
|
|
31467
31473
|
}).strict().optional();
|
|
31468
31474
|
var VERBOSITY_FLAGS2 = { verbose: "-v", debug: "-d" };
|
|
@@ -31476,27 +31482,34 @@ function buildXmlOpts(options) {
|
|
|
31476
31482
|
const result = {};
|
|
31477
31483
|
if (options?.verbosity !== void 0) result["verbosity"] = options.verbosity;
|
|
31478
31484
|
if (options?.charsetAssume !== void 0) result["charsetAssume"] = options.charsetAssume;
|
|
31485
|
+
if (options?.charsetFallback !== void 0) result["charsetFallback"] = options.charsetFallback;
|
|
31479
31486
|
return result;
|
|
31480
31487
|
}
|
|
31488
|
+
function isCharsetError(stderrOutput) {
|
|
31489
|
+
return stderrOutput.includes("convert character encoding") || stderrOutput.includes("Illegal byte sequence");
|
|
31490
|
+
}
|
|
31491
|
+
async function runXmlAndParse(binary, args, execOpts) {
|
|
31492
|
+
const xmlResult = await execCommand(binary, args, execOpts);
|
|
31493
|
+
if (!xmlResult.ok) return err(xmlResult.error);
|
|
31494
|
+
if (xmlResult.value.exitCode !== 0) {
|
|
31495
|
+
return err(createToolError("dcm2xml", args, xmlResult.value.exitCode, xmlResult.value.stderr));
|
|
31496
|
+
}
|
|
31497
|
+
const jsonResult = xmlToJson(xmlResult.value.stdout);
|
|
31498
|
+
if (!jsonResult.ok) return err(jsonResult.error);
|
|
31499
|
+
return ok({ data: jsonResult.value, source: "xml" });
|
|
31500
|
+
}
|
|
31481
31501
|
async function tryXmlPath(inputPath, timeoutMs, signal, opts) {
|
|
31482
31502
|
const xmlBinary = resolveBinary("dcm2xml");
|
|
31483
|
-
if (!xmlBinary.ok)
|
|
31484
|
-
return err(xmlBinary.error);
|
|
31485
|
-
}
|
|
31503
|
+
if (!xmlBinary.ok) return err(xmlBinary.error);
|
|
31486
31504
|
const charsetArgs = opts?.charsetAssume !== void 0 ? ["+Ca", opts.charsetAssume] : [];
|
|
31487
31505
|
const xmlArgs = [...buildVerbosityArgs(opts?.verbosity), ...charsetArgs, "-nat", inputPath];
|
|
31488
|
-
const
|
|
31489
|
-
|
|
31490
|
-
|
|
31506
|
+
const execOpts = signal !== void 0 ? { timeoutMs, signal } : { timeoutMs };
|
|
31507
|
+
const result = await runXmlAndParse(xmlBinary.value, xmlArgs, execOpts);
|
|
31508
|
+
if (!result.ok && opts?.charsetFallback !== void 0 && isCharsetError(result.error.message)) {
|
|
31509
|
+
const fallbackArgs = [...buildVerbosityArgs(opts.verbosity), "+Ca", opts.charsetFallback, "-nat", inputPath];
|
|
31510
|
+
return runXmlAndParse(xmlBinary.value, fallbackArgs, execOpts);
|
|
31491
31511
|
}
|
|
31492
|
-
|
|
31493
|
-
return err(createToolError("dcm2xml", xmlArgs, xmlResult.value.exitCode, xmlResult.value.stderr));
|
|
31494
|
-
}
|
|
31495
|
-
const jsonResult = xmlToJson(xmlResult.value.stdout);
|
|
31496
|
-
if (!jsonResult.ok) {
|
|
31497
|
-
return err(jsonResult.error);
|
|
31498
|
-
}
|
|
31499
|
-
return ok({ data: jsonResult.value, source: "xml" });
|
|
31512
|
+
return result;
|
|
31500
31513
|
}
|
|
31501
31514
|
async function tryDirectPath(inputPath, timeoutMs, signal, verbosity) {
|
|
31502
31515
|
const jsonBinary = resolveBinary("dcm2json");
|
|
@@ -34387,7 +34400,8 @@ var DicomInstance = class _DicomInstance {
|
|
|
34387
34400
|
const jsonResult = await dcm2json(path2, {
|
|
34388
34401
|
timeoutMs: options?.timeoutMs ?? DEFAULT_TIMEOUT_MS,
|
|
34389
34402
|
signal: options?.signal,
|
|
34390
|
-
charsetAssume: options?.charsetAssume
|
|
34403
|
+
charsetAssume: options?.charsetAssume,
|
|
34404
|
+
charsetFallback: options?.charsetFallback
|
|
34391
34405
|
});
|
|
34392
34406
|
if (!jsonResult.ok) return err(jsonResult.error);
|
|
34393
34407
|
const datasetResult = DicomDataset.fromJson(jsonResult.value.data);
|
|
@@ -36472,6 +36486,12 @@ var DicomReceiverOptionsSchema = zod.z.object({
|
|
|
36472
36486
|
filenameMode: zod.z.enum(["default", "unique", "short-unique", "system-time"]).optional(),
|
|
36473
36487
|
filenameExtension: zod.z.string().min(1).optional(),
|
|
36474
36488
|
storageMode: zod.z.enum(["normal", "bit-preserving", "ignore"]).optional(),
|
|
36489
|
+
instanceOpenOptions: zod.z.object({
|
|
36490
|
+
timeoutMs: zod.z.number().int().positive().optional(),
|
|
36491
|
+
signal: zod.z.instanceof(AbortSignal).optional(),
|
|
36492
|
+
charsetAssume: zod.z.string().min(1).optional(),
|
|
36493
|
+
charsetFallback: zod.z.string().min(1).optional()
|
|
36494
|
+
}).strict().optional(),
|
|
36475
36495
|
signal: zod.z.instanceof(AbortSignal).optional()
|
|
36476
36496
|
}).strict().refine((data) => (data.minPoolSize ?? DEFAULT_MIN_POOL_SIZE) <= (data.maxPoolSize ?? DEFAULT_MAX_POOL_SIZE), {
|
|
36477
36497
|
message: "minPoolSize must be <= maxPoolSize"
|
|
@@ -36641,6 +36661,7 @@ var DicomReceiver = class _DicomReceiver extends events.EventEmitter {
|
|
|
36641
36661
|
__publicField(this, "minPoolSize");
|
|
36642
36662
|
__publicField(this, "maxPoolSize");
|
|
36643
36663
|
__publicField(this, "connectionTimeoutMs");
|
|
36664
|
+
__publicField(this, "resolvedInstanceOpenOptions");
|
|
36644
36665
|
__publicField(this, "workers", /* @__PURE__ */ new Map());
|
|
36645
36666
|
__publicField(this, "tcpServer");
|
|
36646
36667
|
__publicField(this, "associationCounter", 0);
|
|
@@ -36652,6 +36673,7 @@ var DicomReceiver = class _DicomReceiver extends events.EventEmitter {
|
|
|
36652
36673
|
this.minPoolSize = options.minPoolSize ?? DEFAULT_MIN_POOL_SIZE;
|
|
36653
36674
|
this.maxPoolSize = options.maxPoolSize ?? DEFAULT_MAX_POOL_SIZE;
|
|
36654
36675
|
this.connectionTimeoutMs = options.connectionTimeoutMs ?? DEFAULT_CONNECTION_TIMEOUT_MS;
|
|
36676
|
+
this.resolvedInstanceOpenOptions = { charsetFallback: "Latin1", ...options.instanceOpenOptions };
|
|
36655
36677
|
}
|
|
36656
36678
|
// -----------------------------------------------------------------------
|
|
36657
36679
|
// Public API
|
|
@@ -37118,7 +37140,7 @@ var DicomReceiver = class _DicomReceiver extends events.EventEmitter {
|
|
|
37118
37140
|
/** Parses a DICOM file and emits INSTANCE_RECEIVED or INSTANCE_ERROR. */
|
|
37119
37141
|
async parseAndEmitInstance(worker, ctx) {
|
|
37120
37142
|
try {
|
|
37121
|
-
const openResult = await DicomInstance.open(ctx.filePath);
|
|
37143
|
+
const openResult = await DicomInstance.open(ctx.filePath, this.resolvedInstanceOpenOptions);
|
|
37122
37144
|
if (!openResult.ok) {
|
|
37123
37145
|
worker.recordInstanceError();
|
|
37124
37146
|
this.emit("INSTANCE_ERROR", { error: openResult.error, thrown: false, ...ctx });
|