@crutchcrew/oxlint-plugin-import-access

中文文档
1.1.0发布于 2026/10/28MITTypeScriptES Module构建来源已验证近 30 天下载 8723

Oxlint JS plugin for import access via JSDoc @public, @package and @private, without a type checker

原始使用文档
文档目录12 节
  1. Access tags
  2. Why?
  3. Why this package
  4. Install
  5. Configure
  6. Options
  7. How it works
  8. Performance
  9. Coming from eslint-plugin-import-access
  10. Contributing
  11. Credits
  12. License

@crutchcrew/oxlint-plugin-import-access 📦🔒

npm version coverage provenance license

JSDoc import access for TypeScript, enforced by oxlint. Only @public exports can be imported from anywhere, and an export without an access tag is @package: only files in its own package (its directory and subdirectories) can import it. Tag an export @public to share it with the whole project, or @private so no other file can import it. To make untagged exports @public or @private instead, set defaultImportability.

A native oxlint JS plugin port of eslint-plugin-import-access that needs no type checker: no typescript dependency, no tsconfig.json project loading, no typed linting setup.

Access tags

sub/foo.ts exports api tagged @public, helper without a tag and secret tagged @private. sub/bar.ts, in the same package, can import api and helper but not secret. src/main.ts, outside the package, can import only api.

Each export's JSDoc access tag decides which files can import it. A package is a directory with its subdirectories, and by default every directory is one (see packageDirectory). In the picture, sub/foo.ts has three exports:

  • api is @public: any file can import it, sub/bar.ts as well as src/main.ts.
  • helper has no tag, so it is @package: files in sub/ and its subdirectories can import it, so sub/bar.ts can and src/main.ts can't.
  • secret is @private: no file can import it, not even sub/bar.ts next to it.

Imports from Node.js builtins and from anything in node_modules are never checked.

Why?

The largest encapsulation unit TypeScript gives you is a file. Once something is exported, the whole project can import it. Keeping things private means keeping them in one file, and files grow large.

This plugin adds a directory-level layer between a file and the whole project: an export stays inside its directory (@package) until you tag it @public. Tag what the rest of the project may use @public, and what no other file may use @private.

Why this package

This packageeslint-plugin-import-accessoxlint-plugin-import-access
LinteroxlintESLintoxlint
Needs type information❌✅ typed linting✅ TypeScript 7 unstable API
typescript dependency❌✅✅ ^7
Works without tsconfig.json✅❌❌
Checks unsaved edits in the editor✅✅❌ skipped until saved
Same results as the original rule✅ verified¹–✅

¹ With defaultImportability: "public", which makes exports without an access tag @public like in the original. This plugin's default is "package". This plugin also checks the members used through namespace imports (import * as foo), which the original doesn't check.

Install

Choose your fighter 🥊

pnpm add -D oxlint @crutchcrew/oxlint-plugin-import-access
bun add -D oxlint @crutchcrew/oxlint-plugin-import-access
yarn add -D oxlint @crutchcrew/oxlint-plugin-import-access
npm add -D oxlint @crutchcrew/oxlint-plugin-import-access

Requires Node.js ^20.19.0 || >=22.12.0 (the same as oxlint) and oxlint >=1.40.0.

Configure

In .oxlintrc.json:

{
    "jsPlugins": ["@crutchcrew/oxlint-plugin-import-access"],
    "rules": {
        "import-access/jsdoc": "error"
    }
}

Or in oxlint.config.ts:

import { defineConfig } from "oxlint"

export default defineConfig({
    jsPlugins: ["@crutchcrew/oxlint-plugin-import-access"],
    rules: {
        // Untagged exports are @package; tag an export @public to import it from anywhere
        "import-access/jsdoc": "error",
    },
})

That's all: there is no parser or project to configure. Diagnostics also show up in your editor through the oxc extension (oxlint's language server).

Options

OptionDefaultDescription
indexLoopholetruesub/index.ts counts as sub.ts, so its package-private exports are visible one level up
filenameLoopholefalsefoo.ts may import package-private exports from foo/
defaultImportability"package"Access of exports without a tag: "package" (@package), "public" or "private"
treatSelfReferenceAs"external"Whether imports through your own package name are checked ("internal") or not
excludeSourcePatterns[]Globs (relative to the working directory) of exporter files to skip, e.g. generated code
packageDirectoryevery dirGlobs of directories that are package boundaries, e.g. ["**", "!**/_internal"]

All options and access tags (@public, @package, @private, @access <level>) behave as in the original plugin, except that defaultImportability defaults to "package" instead of "public". See the rule documentation for details and examples.

How it works

The original rule asks the TypeScript type checker which declaration an import refers to. This plugin answers the same question from syntax alone:

  1. resolve the import like TypeScript (tsconfig paths, package.json exports, .js → .ts) with oxc-resolver,
  2. skip builtins and anything reached through node_modules,
  3. read the target file's exports and JSDoc with oxc-parser — the module record and comments; the syntax tree only for the few files with decorators, export =, re-exported imports or JSDoc inside variable statements — and cache them,
  4. follow export *, stop at direct re-exports like upstream, and read JSDoc with TypeScript's attachment and tag rules,
  5. check ambient declare module "…" and wildcard declare module "*.svg" declarations too.

Verified against the original: the upstream test suite passes unchanged (same lines, columns, messages), and the port was compared with upstream's TypeScript-based rule on every fixture file and option combination, including new fixtures for re-export chains, overloads, enums, export =, wildcard modules and JSDoc placement, whose expectations in the test suite were generated by the original rule. The known differences are edge cases such as module augmentation across files.

Performance

Generated project with nested feature directories, export * barrels and 6 imports per module (bun run bench), on an Apple M1 (8 cores, Asahi Linux), Node.js 26, oxlint 1.89:

Modules (imports)ESLint + eslint-plugin-import-accessoxlint + this pluginSpeedup
1,000 (6,000)1.90 s0.31 s6.1×
2,500 (15,000)4.89 s ¹0.55 s8.9×
5,000 (30,000)fails after 524 s ²0.95 s–

ESLint 10 with typescript-eslint 8 typed linting (projectService), single run; oxlint best of 3. Both report identical diagnostics on every file the TypeScript-based rule can analyze. Of the 0.95 s, about 0.33 s is oxlint's own cost of running any JS plugin over 5,000 files.

¹ TypeScript fails on 16 of the 2,600 files ("Maximum call stack size exceeded"), so those files went unchecked. ² TypeScript fails on every file of this heavily cyclic project.

In a long-running editor session, files are re-checked as they change: exporter files are re-validated by size and modification time, and only re-parsed when they changed.

Coming from eslint-plugin-import-access

  1. Install oxlint and this package, and remove eslint-plugin-import-access from your ESLint config.
  2. Move your rule options unchanged to "import-access/jsdoc" in the oxlint config. If you didn't set defaultImportability, set it to "public" to keep the original's behavior: here, untagged exports are @package by default.
  3. For IDE auto-import filtering you can keep using the original package's TypeScript language service plugin (it only needs TypeScript, not ESLint); this package has no language service plugin of its own.

Contributing

bun install
bun run test          # rule and unit tests (Node.js >= 22)
bun run build && bun run test:e2e
bun run check         # format, lint + typecheck (oxlint, with this plugin on its own sources), lockfile

Credits

Based on eslint-plugin-import-access by uhyo, whose rule design, options, documentation and test fixtures this port keeps.

License

MIT

版本与发布记录

@crutchcrew/oxlint-plugin-import-access 共发布 4 个版本,首次发布于 2026/10/27;过去 12 个月发布了 4 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
1.1.0latest2026/10/2814 天前
1.0.12026/10/2715 天前
1.0.02026/10/2715 天前
0.0.0-stage2026/10/2715 天前

关于 @crutchcrew/oxlint-plugin-import-access 的常见问题

@crutchcrew/oxlint-plugin-import-access 是什么?

Oxlint JS plugin for import access via JSDoc @public, @package and @private, without a type checker

如何安装 @crutchcrew/oxlint-plugin-import-access?

在项目目录运行 npm install @crutchcrew/oxlint-plugin-import-access,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:oxlint(>=1.40.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@crutchcrew/oxlint-plugin-import-access 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@crutchcrew/oxlint-plugin-import-access 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@crutchcrew/oxlint-plugin-import-access 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js ^20.19.0 || >=22.12.0。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@crutchcrew/oxlint-plugin-import-access 可以商用吗?

@crutchcrew/oxlint-plugin-import-access 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@crutchcrew/oxlint-plugin-import-access 的下载量有多少?

根据 npm 官方下载统计,@crutchcrew/oxlint-plugin-import-access 在 2026/10/11 – 2026/11/09 这 30 天内被下载 8,723 次,日均约 291 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@crutchcrew/oxlint-plugin-import-access 还在维护吗?

最新版本 1.1.0 发布于 2026/10/28(14 天前);至今共发布 4 个版本,其中过去 12 个月发布了 4 个;首次发布于 2026/10/27。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。