@ubercode/dcmtk 0.12.1 → 0.13.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/tools.d.cts CHANGED
@@ -78,6 +78,8 @@ interface Dcm2jsonOptions extends ToolBaseOptions {
78
78
  readonly directOnly?: boolean | undefined;
79
79
  /** Assume the specified character set when SpecificCharacterSet (0008,0005) is absent. Passed to dcm2xml as `+Ca`. Only effective on the XML path (dcm2json binary does not support this flag). */
80
80
  readonly charsetAssume?: string | undefined;
81
+ /** Fallback charset to retry with when UTF-8 conversion fails. On charset error, the XML path retries with `+Ca <fallback>`. `'Latin1'` recommended — maps every byte to a valid character. */
82
+ readonly charsetFallback?: string | undefined;
81
83
  /** Verbosity level for diagnostic output. `'verbose'` maps to `-v`, `'debug'` maps to `-d`. */
82
84
  readonly verbosity?: 'verbose' | 'debug' | undefined;
83
85
  }
package/dist/tools.d.ts CHANGED
@@ -78,6 +78,8 @@ interface Dcm2jsonOptions extends ToolBaseOptions {
78
78
  readonly directOnly?: boolean | undefined;
79
79
  /** Assume the specified character set when SpecificCharacterSet (0008,0005) is absent. Passed to dcm2xml as `+Ca`. Only effective on the XML path (dcm2json binary does not support this flag). */
80
80
  readonly charsetAssume?: string | undefined;
81
+ /** Fallback charset to retry with when UTF-8 conversion fails. On charset error, the XML path retries with `+Ca <fallback>`. `'Latin1'` recommended — maps every byte to a valid character. */
82
+ readonly charsetFallback?: string | undefined;
81
83
  /** Verbosity level for diagnostic output. `'verbose'` maps to `-v`, `'debug'` maps to `-d`. */
82
84
  readonly verbosity?: 'verbose' | 'debug' | undefined;
83
85
  }
package/dist/tools.js CHANGED
@@ -536,6 +536,7 @@ var Dcm2jsonOptionsSchema = z.object({
536
536
  signal: z.instanceof(AbortSignal).optional(),
537
537
  directOnly: z.boolean().optional(),
538
538
  charsetAssume: z.string().min(1).optional(),
539
+ charsetFallback: z.string().min(1).optional(),
539
540
  verbosity: z.enum(["verbose", "debug"]).optional()
540
541
  }).strict().optional();
541
542
  var VERBOSITY_FLAGS2 = { verbose: "-v", debug: "-d" };
@@ -549,27 +550,34 @@ function buildXmlOpts(options) {
549
550
  const result = {};
550
551
  if (options?.verbosity !== void 0) result["verbosity"] = options.verbosity;
551
552
  if (options?.charsetAssume !== void 0) result["charsetAssume"] = options.charsetAssume;
553
+ if (options?.charsetFallback !== void 0) result["charsetFallback"] = options.charsetFallback;
552
554
  return result;
553
555
  }
556
+ function isCharsetError(stderrOutput) {
557
+ return stderrOutput.includes("convert character encoding") || stderrOutput.includes("Illegal byte sequence");
558
+ }
559
+ async function runXmlAndParse(binary, args, execOpts) {
560
+ const xmlResult = await execCommand(binary, args, execOpts);
561
+ if (!xmlResult.ok) return err(xmlResult.error);
562
+ if (xmlResult.value.exitCode !== 0) {
563
+ return err(createToolError("dcm2xml", args, xmlResult.value.exitCode, xmlResult.value.stderr));
564
+ }
565
+ const jsonResult = xmlToJson(xmlResult.value.stdout);
566
+ if (!jsonResult.ok) return err(jsonResult.error);
567
+ return ok({ data: jsonResult.value, source: "xml" });
568
+ }
554
569
  async function tryXmlPath(inputPath, timeoutMs, signal, opts) {
555
570
  const xmlBinary = resolveBinary("dcm2xml");
556
- if (!xmlBinary.ok) {
557
- return err(xmlBinary.error);
558
- }
571
+ if (!xmlBinary.ok) return err(xmlBinary.error);
559
572
  const charsetArgs = opts?.charsetAssume !== void 0 ? ["+Ca", opts.charsetAssume] : [];
560
573
  const xmlArgs = [...buildVerbosityArgs(opts?.verbosity), ...charsetArgs, "-nat", inputPath];
561
- const xmlResult = await execCommand(xmlBinary.value, xmlArgs, { timeoutMs, signal });
562
- if (!xmlResult.ok) {
563
- return err(xmlResult.error);
574
+ const execOpts = signal !== void 0 ? { timeoutMs, signal } : { timeoutMs };
575
+ const result = await runXmlAndParse(xmlBinary.value, xmlArgs, execOpts);
576
+ if (!result.ok && opts?.charsetFallback !== void 0 && isCharsetError(result.error.message)) {
577
+ const fallbackArgs = [...buildVerbosityArgs(opts.verbosity), "+Ca", opts.charsetFallback, "-nat", inputPath];
578
+ return runXmlAndParse(xmlBinary.value, fallbackArgs, execOpts);
564
579
  }
565
- if (xmlResult.value.exitCode !== 0) {
566
- return err(createToolError("dcm2xml", xmlArgs, xmlResult.value.exitCode, xmlResult.value.stderr));
567
- }
568
- const jsonResult = xmlToJson(xmlResult.value.stdout);
569
- if (!jsonResult.ok) {
570
- return err(jsonResult.error);
571
- }
572
- return ok({ data: jsonResult.value, source: "xml" });
580
+ return result;
573
581
  }
574
582
  async function tryDirectPath(inputPath, timeoutMs, signal, verbosity) {
575
583
  const jsonBinary = resolveBinary("dcm2json");