node util.inspect breaking simple array unexpectedly

Viewed 76

I am using util.inspect to format a manipulated object before writing it back to a file. Recently I have introduced simple numeric arrays to this object and they are being formatted in an unexpected way. Here is what I want from my output (partial example):

  app_preferred_items: [ 0, 6, 13, 16, 19, 23, 26 ],
  main_set: [
    {
      name: 'item1',
      show: true,
      description: 'Item One',
      id: 12,
      version: 1
    },
   {
      name: 'item2',
      show: true,
      description: 'Item Two',
      id: 13,
      version: 1
    }
  ]

but here is what I am getting:

  app_preferred_items: [
     0,  6, 13, 16,
    19, 23, 26
  ],
  main_set: [
    {
      name: 'item1',
      show: true,
      description: 'Item One',
      id: 12,
      version: 1
    },
   {
      name: 'item2',
      show: true,
      description: 'Item Two',
      id: 13,
      version: 1
    }
  ]

I have tried various options from here but to no avail yet. I either get a single line for the entire file (using compact option) which makes readability difficult, or this simple number array breaking pattern which I don't want. Is there any way to make simple numeric arrays stay on one line?

1 Answers

There is no clean way to change this behavior since a bound for array grouping is hard coded in node.js. However, if you want to make simple numeric arrays stay on a single line, this function should work:

const util = require('util');

const inspect = (obj, options) => {
  const clone = structuredClone(obj);
  const stack = [clone];
  while (stack.length) {
    const curr = stack.pop();

    if (typeof curr !== 'object') continue;

    if (Array.isArray(curr)) {
      // patch arrays that are all numbers
      if (curr.filter((v) => typeof v !== 'number').length == 0) {
        const repr = `[ ${curr.join(', ')} ]`;
        const patch = { [util.inspect.custom]: () => repr };
        curr.__proto__ = patch;
      }
    }

    for (const child of Object.values(curr)) stack.push(child);
  }
  return util.inspect(clone, options ?? {});
};

Essentially, this makes a copy of your object and for numeric arrays, provides a custom implementation of util.inspect that simply separates the elements with spaces.

Related