bun/prefer-local-module

Require importing a package through the module in your project that wraps it

fixable

A project often wraps a package in its own module, for example to give an HTTP client a base URL, a timeout and logging. A file that imports the package directly skips all of that, and nothing tells you.

The rule does nothing until you list the packages in modules. It then checks import, export .. from, import() and require(). The name must match exactly, so with axios listed, axios/lib isn't reported.

--fix changes the import to your module.

Configure#

Off by default. To turn it on:

bunfig.toml
[lint.rules]
"bun/prefer-local-module" = "error" # or "warn"

Every option, set to its default:

bunfig.toml
[lint.rules]
"bun/prefer-local-module" = ["error", {
  modules = [], # list of objects
  exemptFiles = [], # list of strings
}]

Examples#

These examples use this configuration:

bunfig.toml
[lint.rules]
"bun/prefer-local-module" = ["error", {
  modules = [{ package = "axios", use = "@/http" }],
}]
example.tswith { "modules": [{ "package": "axios", "use": "@/http" }] }1 problem
import axios from "axios";

const users = await axios.get("/users");
example.tswith { "modules": [{ "package": "axios", "use": "@/http" }] }No problems
import axios from "@/http";

const users = await axios.get("/users");

Options#

OptionDefaultWhat it does
modules[]The wrapped packages. See below.
exemptFiles[]Files that can import the packages directly. List the wrapper itself here.

Each entry in modules has:

KeyWhat it is
packageThe package that must not be imported directly. Required.
useThe specifier to import instead. Required.
defaultThe name your module uses to export the package's default export.
namesExports that have a different name in your module, like { "isCancel": "wasCancelled" }.

default and names only matter for --fix. With default set to "http", import axios from "axios" becomes import { http as axios } from "@/http". If either is set, only import statements are fixed, and not import * as or import type.

An entry in exemptFiles is the end of a path, in whole names. http.ts matches src/http.ts but not src/other-http.ts.

src/http.tswith { "modules": [{ "package": "axios", "use": "@/http" }], "exemptFiles": ["src/http.ts"] }No problems
import axios from "axios";

export default axios.create({ baseURL: "https://api.example.com", timeout: 5000 });