AphrodyBun GitHub

Runtime docs · Linter · Rules

max-nested-callbacks

Enforce a maximum depth that callbacks can be nested

Callbacks inside callbacks push the code to the right, and each level needs its own error handling. This rule reports any callback nested deeper than the maximum, which is 10 by default.

A callback is a function expression or an arrow function that's passed as an argument to a call.

Configure

Off by default. To turn it on:

bunfig.toml
[lint.rules]
"max-nested-callbacks" = "error" # or "warn"

Every option, set to its default. The ones that are commented out are unset by default.

bunfig.toml
[lint.rules]
"max-nested-callbacks" = ["error", {
  max = 10,
  checkConstructorCallCallbacks = false,
  # maximum = <number>,
}]

Examples

With a maximum of 2, the third callback is reported:

readConfig((config) => {
  connect(config, (db) => {
    db.query("select 1", (rows) => {
      console.log(rows);
    });
  });
});

Not reported:

const config = await readConfig();
const db = await connect(config);
const rows = await db.query("select 1");
console.log(rows);

Options

bunfig.toml
[lint.rules]
max-nested-callbacks = ["error", 3]
OptionDefaultWhat it does
max10The deepest level allowed. maximum is an older name for it.
checkConstructorCallCallbacksfalseAlso count a function passed to new, as in new Promise(() => {}).

A number alone is short for { "max": number }.

By default the function passed to new Promise doesn't count as a level:

button.addEventListener("click", () => {
  return new Promise((resolve) => {
    setTimeout(resolve, 100);
  });
});

With checkConstructorCallCallbacks it's the second level:

button.addEventListener("click", () => {
  return new Promise((resolve) => {
    setTimeout(resolve, 100);
  });
});