code icon Code

Truncate Text Fields

Truncate long string fields in array items

Source Code

import fs from "fs";
import path from "path";

const [inputPath, fieldsArg, maxLengthArg, outputPath] = process.argv.slice(2);

if (!inputPath || !fieldsArg || !maxLengthArg || !outputPath) {
  console.error("Usage: inputPath fields maxLength outputPath");
  process.exit(1);
}

const maxLength = parseInt(maxLengthArg);
if (isNaN(maxLength) || maxLength < 1) {
  console.error("maxLength must be a positive number");
  process.exit(1);
}

/**
 * Get nested field value using dot notation
 */
function getField(obj, fieldPath) {
  const parts = fieldPath.split(".");
  let value = obj;
  for (const part of parts) {
    if (value == null) return undefined;
    value = value[part];
  }
  return value;
}

/**
 * Set nested field value using dot notation
 */
function setField(obj, fieldPath, value) {
  const parts = fieldPath.split(".");
  let current = obj;

  for (let i = 0; i < parts.length - 1; i++) {
    const part = parts[i];
    if (current[part] == null) {
      current[part] = {};
    }
    current = current[part];
  }

  current[parts[parts.length - 1]] = value;
}

/**
 * Truncate string with ellipsis
 */
function truncate(str, maxLen) {
  if (typeof str !== "string") return str;
  if (str.length <= maxLen) return str;
  return str.slice(0, maxLen - 3) + "...";
}

try {
  console.log(`Reading ${inputPath}...`);
  const raw = fs.readFileSync(inputPath, "utf-8");
  const data = JSON.parse(raw);

  const items = Array.isArray(data)
    ? data
    : data.items || data.results || data.messages || [];

  if (!Array.isArray(items)) {
    console.error("Input must be a JSON array or object with array property");
    process.exit(1);
  }

  const fields = fieldsArg.split(",").map((f) => f.trim());

  console.log(
    `Truncating fields [${fields.join(", ")}] to max ${maxLength} chars...`
  );

  let truncatedCount = 0;

  const result = items.map((item) => {
    const newItem = JSON.parse(JSON.stringify(item)); // Deep clone

    for (const field of fields) {
      const value = getField(newItem, field);
      if (typeof value === "string" && value.length > maxLength) {
        setField(newItem, field, truncate(value, maxLength));
        truncatedCount++;
      }
    }

    return newItem;
  });

  // Ensure output directory exists
  const dir = path.dirname(outputPath);
  if (dir && dir !== ".") {
    fs.mkdirSync(dir, { recursive: true });
  }

  fs.writeFileSync(outputPath, JSON.stringify(result, null, 2));

  console.log(`\nāœ“ Processed ${items.length} items`);
  console.log(`  Fields: ${fields.join(", ")}`);
  console.log(`  Max length: ${maxLength}`);
  console.log(`  Values truncated: ${truncatedCount}`);
  console.log(`  Written to: ${outputPath}`);

  console.log(
    JSON.stringify({
      success: true,
      outputPath,
      count: items.length,
      fields,
      maxLength,
      truncatedCount,
    })
  );
} catch (error) {
  console.error("Error:", error.message);
  process.exit(1);
}