@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/tools.cjs CHANGED
@@ -476,7 +476,12 @@ var parser = new fastXmlParser.XMLParser({
476
476
  ignoreAttributes: false,
477
477
  attributeNamePrefix: "@_",
478
478
  parseTagValue: false,
479
- isArray: (name) => ARRAY_TAG_NAMES.has(name)
479
+ isArray: (name) => ARRAY_TAG_NAMES.has(name),
480
+ // DICOM XML does not use XML entities. Disable entity processing to avoid
481
+ // the default expansion limit (1000) which rejects files with >1000 tags.
482
+ // Without this, large studies fall through to dcm2json which hangs on
483
+ // compressed pixel data (DCMTK bug).
484
+ processEntities: false
480
485
  });
481
486
  function xmlToJson(xml) {
482
487
  try {
@@ -537,6 +542,7 @@ var Dcm2jsonOptionsSchema = zod.z.object({
537
542
  signal: zod.z.instanceof(AbortSignal).optional(),
538
543
  directOnly: zod.z.boolean().optional(),
539
544
  charsetAssume: zod.z.string().min(1).optional(),
545
+ charsetFallback: zod.z.string().min(1).optional(),
540
546
  verbosity: zod.z.enum(["verbose", "debug"]).optional()
541
547
  }).strict().optional();
542
548
  var VERBOSITY_FLAGS2 = { verbose: "-v", debug: "-d" };
@@ -550,27 +556,34 @@ function buildXmlOpts(options) {
550
556
  const result = {};
551
557
  if (options?.verbosity !== void 0) result["verbosity"] = options.verbosity;
552
558
  if (options?.charsetAssume !== void 0) result["charsetAssume"] = options.charsetAssume;
559
+ if (options?.charsetFallback !== void 0) result["charsetFallback"] = options.charsetFallback;
553
560
  return result;
554
561
  }
562
+ function isCharsetError(stderrOutput) {
563
+ return stderrOutput.includes("convert character encoding") || stderrOutput.includes("Illegal byte sequence");
564
+ }
565
+ async function runXmlAndParse(binary, args, execOpts) {
566
+ const xmlResult = await execCommand(binary, args, execOpts);
567
+ if (!xmlResult.ok) return err(xmlResult.error);
568
+ if (xmlResult.value.exitCode !== 0) {
569
+ return err(createToolError("dcm2xml", args, xmlResult.value.exitCode, xmlResult.value.stderr));
570
+ }
571
+ const jsonResult = xmlToJson(xmlResult.value.stdout);
572
+ if (!jsonResult.ok) return err(jsonResult.error);
573
+ return ok({ data: jsonResult.value, source: "xml" });
574
+ }
555
575
  async function tryXmlPath(inputPath, timeoutMs, signal, opts) {
556
576
  const xmlBinary = resolveBinary("dcm2xml");
557
- if (!xmlBinary.ok) {
558
- return err(xmlBinary.error);
559
- }
577
+ if (!xmlBinary.ok) return err(xmlBinary.error);
560
578
  const charsetArgs = opts?.charsetAssume !== void 0 ? ["+Ca", opts.charsetAssume] : [];
561
579
  const xmlArgs = [...buildVerbosityArgs(opts?.verbosity), ...charsetArgs, "-nat", inputPath];
562
- const xmlResult = await execCommand(xmlBinary.value, xmlArgs, { timeoutMs, signal });
563
- if (!xmlResult.ok) {
564
- return err(xmlResult.error);
580
+ const execOpts = signal !== void 0 ? { timeoutMs, signal } : { timeoutMs };
581
+ const result = await runXmlAndParse(xmlBinary.value, xmlArgs, execOpts);
582
+ if (!result.ok && opts?.charsetFallback !== void 0 && isCharsetError(result.error.message)) {
583
+ const fallbackArgs = [...buildVerbosityArgs(opts.verbosity), "+Ca", opts.charsetFallback, "-nat", inputPath];
584
+ return runXmlAndParse(xmlBinary.value, fallbackArgs, execOpts);
565
585
  }
566
- if (xmlResult.value.exitCode !== 0) {
567
- return err(createToolError("dcm2xml", xmlArgs, xmlResult.value.exitCode, xmlResult.value.stderr));
568
- }
569
- const jsonResult = xmlToJson(xmlResult.value.stdout);
570
- if (!jsonResult.ok) {
571
- return err(jsonResult.error);
572
- }
573
- return ok({ data: jsonResult.value, source: "xml" });
586
+ return result;
574
587
  }
575
588
  async function tryDirectPath(inputPath, timeoutMs, signal, verbosity) {
576
589
  const jsonBinary = resolveBinary("dcm2json");