Skip to main content

no-internal-modules

Disallow importing nested internal module paths.

Targeted pattern scopeโ€‹

This rule matches import/export sources that look like deep/internal module paths, using these default disallow globs:

  • ./*/**
  • [^@]*/**
  • @?*/*/**

What this rule reportsโ€‹

This rule reports imports/exports that target internal module segments such as:

  • ./folder/internal
  • package/internal
  • @scope/package/internal

It allows top-level entry imports such as ./folder, package, and @scope/package.

Why this rule existsโ€‹

It enforces package entrypoint usage instead of importing deep internal files.

โŒ Incorrectโ€‹

import a from "./folder/internal";
import b from "package/internal";
import c from "@scope/package/internal";

โœ… Correctโ€‹

import a from "./folder";
import b from "package";
import c from "@scope/package";

Behavior and migration notesโ€‹

This rule reports only and does not provide an autofix.

Use allow to carve out explicit exceptions while migrating toward public entrypoint imports.

Optionsโ€‹

type Options = {
allow?: string[];
disallow?: string[];
};

Default:

{
"disallow": ["./*/**", "[^@]*/**", "@?*/*/**"]
}

Additional examplesโ€‹

// default disallow includes "@?*/*/**"
import c from "@scope/package/internal/file";
// โŒ reported

import c from "@scope/package";
// โœ… valid

ESLint flat config exampleโ€‹

import etcMisc from "eslint-plugin-etc-misc";

export default [
{
plugins: { "etc-misc": etcMisc },
rules: {
"etc-misc/no-internal-modules": "error",
},
},
];

When not to use itโ€‹

Disable this rule if your project intentionally imports deep internal module paths.

Package documentationโ€‹

Rule catalog ID: R029

Further readingโ€‹

Adoption resourcesโ€‹

  • Start at warning level in CI, then move to error after cleanup.
  • Use focused codemods/autofix batches per package or directory.