{"_id":"@adamhl8/eslint-plugin-clean-modules","_rev":"6-5617083d79da31186b1fec9ad33049e2","name":"@adamhl8/eslint-plugin-clean-modules","dist-tags":{"latest":"0.1.5"},"versions":{"0.1.0":{"name":"@adamhl8/eslint-plugin-clean-modules","version":"0.1.0","keywords":["eslint","eslint-plugin","lint","oxlint","subpath imports"],"author":{"url":"https://github.com/adamhl8","name":"Adam Langbert","email":"adamhl@pm.me"},"license":"MIT","_id":"@adamhl8/eslint-plugin-clean-modules@0.1.0","maintainers":[{"name":"adamhl8","email":"adamhl@pm.me"}],"homepage":"https://github.com/adamhl8/eslint-plugin-clean-modules","bugs":{"url":"https://github.com/adamhl8/eslint-plugin-clean-modules/issues"},"dist":{"shasum":"702635590a54e4e30b23d5e7a9070808ad8b069b","tarball":"https://registry.npmjs.org/@adamhl8/eslint-plugin-clean-modules/-/eslint-plugin-clean-modules-0.1.0.tgz","fileCount":17,"integrity":"sha512-gA6AuvSJFAeG0Z1jzbd0RKTjGymKdVKKYI+Vfua7Y9SACNxfsPuKmthFBV45hwWGauuPpGP5Ik+UhXqKrBAasg==","signatures":[{"sig":"MEUCIQDh3oT8uTDWKc3GjG4Funb38JDZjapPWQG++/J9jfyNvQIgQ4c0GO0SbpL1OLWevoVcA4p82rqnT9DG5IJdVU8Taxg=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":53296},"type":"module","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"imports":{"#/*":"./src/*"},"scripts":{"lint":"markdown-toc -i --bullets '-' --maxdepth 3 ./README.md && oxfmt && oxlint --fix --fix-suggestions --fix-dangerously && adamhl8-knip && nub run test","test":"vitest run","bundle":"nub run lint && tsdown","prepare":"lefthook install","release":"release-it --ci -i \"$(adamhl8-cliff --bumped-version)\"","bump-deps":"nub update -L && rm -f lock.yaml && nub i && oxfmt lock.yaml"},"_npmUser":{"name":"adamhl8","email":"adamhl@pm.me"},"repository":{"url":"git+https://github.com/adamhl8/eslint-plugin-clean-modules.git","type":"git"},"description":"oxlint/ESLint plugin: require subpath imports, direct exports, and explicit import extensions","directories":{},"dependencies":{"@typescript-eslint/types":"^8.62.1","@typescript-eslint/utils":"^8.62.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"knip":"^6.23.0","oxfmt":"^0.56.0","eslint":"^10.6.0","oxlint":"^1.71.0","tsdown":"^0.22.3","vitest":"^4.1.9","publint":"^0.3.21","release-it":"^20.2.1","typescript":"^6.0.3","@types/node":"^26.0.1","markdown-toc":"^1.2.0","@commitlint/cli":"^21.1.0","oxlint-tsgolint":"^0.23.0","@adamhl8/configs":"^0.23.9","@vitest/coverage-v8":"^4.1.9","@arethetypeswrong/core":"^0.18.4","@typescript-eslint/rule-tester":"^8.62.1","@commitlint/config-conventional":"^21.1.0"},"_npmOperationalInternal":{"tmp":"tmp/eslint-plugin-clean-modules_0.1.0_1782794545560_0.7967472421578532","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@adamhl8/eslint-plugin-clean-modules","version":"0.1.1","keywords":["eslint","eslint-plugin","lint","oxlint","subpath imports"],"author":{"url":"https://github.com/adamhl8","name":"Adam Langbert","email":"adamhl@pm.me"},"license":"MIT","_id":"@adamhl8/eslint-plugin-clean-modules@0.1.1","maintainers":[{"name":"adamhl8","email":"adamhl@pm.me"}],"homepage":"https://github.com/adamhl8/eslint-plugin-clean-modules","bugs":{"url":"https://github.com/adamhl8/eslint-plugin-clean-modules/issues"},"dist":{"shasum":"f355226ce6aaf4952be60cda115efb28d2989963","tarball":"https://registry.npmjs.org/@adamhl8/eslint-plugin-clean-modules/-/eslint-plugin-clean-modules-0.1.1.tgz","fileCount":17,"integrity":"sha512-+EKD39npFqYesxWw2MBfM2+Mhwkxn4TtNZ/j9/qn4s7SAp75Fe2BYTkoagvb9pQIbnGq0+MMDyYtqrUNTMB1/Q==","signatures":[{"sig":"MEUCIQCr3Dh5UpDLfO8QLJKub0BRzg2FAfDGUCcwpQIT0cllHgIgeee4On8Ni+NWo8V2zKlnNWhBcZVJtzWf8Oy+RWeuV7U=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":53296},"type":"module","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"imports":{"#/*":"./src/*"},"scripts":{"lint":"markdown-toc -i --bullets '-' --maxdepth 3 ./README.md && oxfmt && oxlint --fix --fix-suggestions --fix-dangerously && adamhl8-knip && nub run test","test":"vitest run","bundle":"nub run lint && tsdown","prepare":"lefthook install","release":"release-it --ci -i \"$(adamhl8-cliff --bumped-version)\"","bump-deps":"nub update -L && rm -f lock.yaml && nub i && oxfmt lock.yaml"},"_npmUser":{"name":"adamhl8","email":"adamhl@pm.me"},"repository":{"url":"git+https://github.com/adamhl8/eslint-plugin-clean-modules.git","type":"git"},"description":"oxlint/ESLint plugin: require subpath imports, direct exports, and explicit import extensions","directories":{},"dependencies":{"@typescript-eslint/types":"^8.62.1","@typescript-eslint/utils":"^8.62.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"knip":"^6.23.0","oxfmt":"^0.56.0","eslint":"^10.6.0","oxlint":"^1.71.0","tsdown":"^0.22.3","vitest":"^4.1.9","publint":"^0.3.21","release-it":"^20.2.1","typescript":"^6.0.3","@types/node":"^26.0.1","markdown-toc":"^1.2.0","@commitlint/cli":"^21.1.0","oxlint-tsgolint":"^0.23.0","@adamhl8/configs":"^0.23.9","@vitest/coverage-v8":"^4.1.9","@arethetypeswrong/core":"^0.18.4","@typescript-eslint/rule-tester":"^8.62.1","@commitlint/config-conventional":"^21.1.0"},"_npmOperationalInternal":{"tmp":"tmp/eslint-plugin-clean-modules_0.1.1_1782794899399_0.6846307366407289","host":"s3://npm-registry-packages-npm-production"}},"0.1.2":{"name":"@adamhl8/eslint-plugin-clean-modules","version":"0.1.2","keywords":["eslint","eslint-plugin","lint","oxlint","subpath imports"],"author":{"url":"https://github.com/adamhl8","name":"Adam Langbert","email":"adamhl@pm.me"},"license":"MIT","_id":"@adamhl8/eslint-plugin-clean-modules@0.1.2","maintainers":[{"name":"adamhl8","email":"adamhl@pm.me"}],"homepage":"https://github.com/adamhl8/eslint-plugin-clean-modules","bugs":{"url":"https://github.com/adamhl8/eslint-plugin-clean-modules/issues"},"dist":{"shasum":"e2d36d708c2b2b6d97c5aa427c353c2be4fb2b43","tarball":"https://registry.npmjs.org/@adamhl8/eslint-plugin-clean-modules/-/eslint-plugin-clean-modules-0.1.2.tgz","fileCount":17,"integrity":"sha512-X5ZHOFXujg2n6toU2B6W4GPHsJUlUVseAz5Q8Oo8oR8BBfqrLnLiYKJYmBsTfN1GFj+3LO97ndgqx3gKSO6fUg==","signatures":[{"sig":"MEYCIQC5WooumB+tdM/JgOxHe9iS8tDHtVFhOOXy1XpIt95XfAIhAOGc1ohDP/OmtSOaeZfIA67u9/sG/tPcA/huKeFG56S4","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":53346},"type":"module","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"imports":{"#/*":"./src/*"},"scripts":{"lint":"markdown-toc -i --bullets '-' --maxdepth 3 ./README.md && oxfmt && oxlint --fix --fix-suggestions --fix-dangerously && adamhl8-knip && nub run test","test":"vitest run","bundle":"nub run lint && tsdown","prepare":"lefthook install","release":"gh workflow run release.yml","bump-deps":"nub update -L && rm -f lock.yaml && nub i && oxfmt lock.yaml","release:run":"release-it --ci -i \"$(adamhl8-cliff --bumped-version)\""},"_npmUser":{"name":"adamhl8","email":"adamhl@pm.me"},"repository":{"url":"git+https://github.com/adamhl8/eslint-plugin-clean-modules.git","type":"git"},"description":"oxlint/ESLint plugin: require subpath imports, direct exports, and explicit import extensions","directories":{},"dependencies":{"@typescript-eslint/types":"^8.62.1","@typescript-eslint/utils":"^8.62.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"knip":"^6.23.0","oxfmt":"^0.57.0","eslint":"^10.6.0","oxlint":"^1.72.0","tsdown":"^0.22.3","vitest":"^4.1.9","publint":"^0.3.21","release-it":"^20.2.1","typescript":"^6.0.3","@types/node":"^26.0.1","markdown-toc":"^1.2.0","@commitlint/cli":"^21.2.0","oxlint-tsgolint":"^0.24.0","@adamhl8/configs":"^0.24.5","@vitest/coverage-v8":"^4.1.9","@arethetypeswrong/core":"^0.18.4","@typescript-eslint/rule-tester":"^8.62.1","@commitlint/config-conventional":"^21.2.0"},"_npmOperationalInternal":{"tmp":"tmp/eslint-plugin-clean-modules_0.1.2_1782849983269_0.46483662837250916","host":"s3://npm-registry-packages-npm-production"}},"0.1.3":{"name":"@adamhl8/eslint-plugin-clean-modules","version":"0.1.3","keywords":["eslint","eslint-plugin","lint","oxlint","subpath imports"],"author":{"url":"https://github.com/adamhl8","name":"Adam Langbert","email":"adamhl@pm.me"},"license":"MIT","_id":"@adamhl8/eslint-plugin-clean-modules@0.1.3","maintainers":[{"name":"adamhl8","email":"adamhl@pm.me"}],"homepage":"https://github.com/adamhl8/eslint-plugin-clean-modules","bugs":{"url":"https://github.com/adamhl8/eslint-plugin-clean-modules/issues"},"dist":{"shasum":"90e7afddf5313554cd3e4f3120d23343cb2f2bc7","tarball":"https://registry.npmjs.org/@adamhl8/eslint-plugin-clean-modules/-/eslint-plugin-clean-modules-0.1.3.tgz","fileCount":17,"integrity":"sha512-k5mFuU3ElM4p1ZvVGOnelOO6Qb4DN69iM5myZ6VxMTC2cnnOdJUeqssojdmgF3I6uUS70zbOmZ290CbZ7Fh1wg==","signatures":[{"sig":"MEUCIQCtcpYrY8bB1Lhn2FMj+wVdh+V5/hHayPtmmZ9be+aNawIgEtJgKitzi42ntm3MdriaOlcH0oCyGn9W/HCNVZrFQdA=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":56735},"type":"module","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"imports":{"#/*":"./src/*"},"scripts":{"lint":"markdown-toc -i --bullets '-' --maxdepth 3 ./README.md && oxfmt && oxlint --fix --fix-suggestions --fix-dangerously && adamhl8-knip && nub run test","test":"vitest run","bundle":"nub run lint && tsdown","prepare":"lefthook install","release":"gh workflow run release.yml","bump-deps":"nub update -L && rm -f lock.yaml && nub i && oxfmt lock.yaml","release:run":"release-it --ci -i \"$(adamhl8-cliff --bumped-version)\""},"_npmUser":{"name":"adamhl8","email":"adamhl@pm.me"},"repository":{"url":"git+https://github.com/adamhl8/eslint-plugin-clean-modules.git","type":"git"},"description":"oxlint/ESLint plugin: require subpath imports, direct exports, and explicit import extensions","directories":{},"dependencies":{"@typescript-eslint/types":"^8.62.1","@typescript-eslint/utils":"^8.62.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"knip":"^6.23.0","oxfmt":"^0.57.0","eslint":"^10.6.0","oxlint":"^1.72.0","tsdown":"^0.22.3","vitest":"^4.1.9","publint":"^0.3.21","release-it":"^20.2.1","typescript":"^6.0.3","@types/node":"^26.0.1","markdown-toc":"^1.2.0","@commitlint/cli":"^21.2.0","oxlint-tsgolint":"^0.24.0","@adamhl8/configs":"^0.24.5","@vitest/coverage-v8":"^4.1.9","@arethetypeswrong/core":"^0.18.4","@typescript-eslint/rule-tester":"^8.62.1","@commitlint/config-conventional":"^21.2.0"},"_npmOperationalInternal":{"tmp":"tmp/eslint-plugin-clean-modules_0.1.3_1782855312384_0.9582448547314499","host":"s3://npm-registry-packages-npm-production"}},"0.1.4":{"name":"@adamhl8/eslint-plugin-clean-modules","version":"0.1.4","keywords":["eslint","eslint-plugin","lint","oxlint","subpath-imports"],"author":{"url":"https://github.com/adamhl8","name":"Adam Langbert","email":"adamhl@pm.me"},"license":"MIT","_id":"@adamhl8/eslint-plugin-clean-modules@0.1.4","maintainers":[{"name":"adamhl8","email":"adamhl@pm.me"}],"homepage":"https://github.com/adamhl8/eslint-plugin-clean-modules","bugs":{"url":"https://github.com/adamhl8/eslint-plugin-clean-modules/issues"},"dist":{"shasum":"365c0a6a50b90f3921516c35b12bb2486de17159","tarball":"https://registry.npmjs.org/@adamhl8/eslint-plugin-clean-modules/-/eslint-plugin-clean-modules-0.1.4.tgz","fileCount":17,"integrity":"sha512-Vhw/WAyCAnWgkcOydiT+bB+dsZxWvOPMo5kmTX7ltzmh9aAfWBokvxZEpijxw8nNMnGjgLcAuuZi2Baa6QkZLQ==","signatures":[{"sig":"MEUCIBFCTTgM65lm27ORjo9p+/qMa7ZI4B0UaY22iG+07pY4AiEAmrcrgjTFMA7xadgsL4priDHxor8FewKmZC06rM3TV1A=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":56298},"type":"module","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"imports":{"#/*":"./src/*"},"scripts":{"prepare":"just prepare"},"_npmUser":{"name":"adamhl8","email":"adamhl@pm.me"},"repository":{"url":"git+https://github.com/adamhl8/eslint-plugin-clean-modules.git","type":"git"},"description":"oxlint/ESLint plugin: require subpath imports, direct exports, and explicit import extensions","directories":{},"dependencies":{"@typescript-eslint/types":"^8.63.0","@typescript-eslint/utils":"^8.63.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"knip":"^6.24.0","oxfmt":"^0.57.0","eslint":"^10.6.0","oxlint":"^1.72.0","tsdown":"^0.22.3","vitest":"^4.1.10","publint":"^0.3.21","release-it":"^20.2.1","typescript":"^6.0.3","@types/node":"^26.1.0","markdown-toc":"^1.2.0","@commitlint/cli":"^21.2.0","oxlint-tsgolint":"^0.24.0","@adamhl8/configs":"^0.36.0","@vitest/coverage-v8":"^4.1.10","@arethetypeswrong/core":"^0.18.4","@typescript-eslint/rule-tester":"^8.63.0","@commitlint/config-conventional":"^21.2.0"},"_npmOperationalInternal":{"tmp":"tmp/eslint-plugin-clean-modules_0.1.4_1783370362627_0.8314929754082883","host":"s3://npm-registry-packages-npm-production"}},"0.1.5":{"name":"@adamhl8/eslint-plugin-clean-modules","version":"0.1.5","description":"oxlint/ESLint plugin: require subpath imports, direct exports, and explicit import extensions","keywords":["eslint","eslint-plugin","lint","oxlint","subpath-imports"],"homepage":"https://github.com/adamhl8/eslint-plugin-clean-modules","bugs":{"url":"https://github.com/adamhl8/eslint-plugin-clean-modules/issues"},"license":"MIT","author":{"name":"Adam Langbert","email":"adamhl@pm.me","url":"https://github.com/adamhl8"},"repository":{"type":"git","url":"git+https://github.com/adamhl8/eslint-plugin-clean-modules.git"},"type":"module","imports":{"#*":"./src/*"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"publishConfig":{"access":"public"},"scripts":{"prepare":"just prepare"},"dependencies":{"@typescript-eslint/types":"^8.63.0","@typescript-eslint/utils":"^8.63.0"},"devDependencies":{"@adamhl8/configs":"^2.2.0","@arethetypeswrong/core":"^0.18.5","@commitlint/cli":"^21.2.1","@commitlint/config-conventional":"^21.2.0","@types/bun":"^1.3.14","@typescript-eslint/rule-tester":"^8.63.0","@typescript/native-preview":"npm:typescript@^7.0.2","eslint":"^10.7.0","knip":"^6.26.0","markdown-toc":"^1.2.0","oxfmt":"^0.58.0","oxlint":"^1.73.0","oxlint-tsgolint":"^0.24.0","publint":"^0.3.21","release-it":"^20.2.1","tsdown":"^0.22.7","typescript":"npm:typescript@^6.0.3"},"_id":"@adamhl8/eslint-plugin-clean-modules@0.1.5","_integrity":"sha512-0Icl5jzQobbjwikMCOpZENa6caNrRNBRaIt/4Y0tISnZGXN8iCB30OCynOho2TbSkC/xfnUqg3p2v6mb+cMc9g==","_nodeVersion":"24.3.0","_npmVersion":"10.8.3","shasum":"eb1c26535795604d92ce08ffc2f98706770c924f","dist":{"integrity":"sha512-0Icl5jzQobbjwikMCOpZENa6caNrRNBRaIt/4Y0tISnZGXN8iCB30OCynOho2TbSkC/xfnUqg3p2v6mb+cMc9g==","shasum":"eb1c26535795604d92ce08ffc2f98706770c924f","tarball":"https://registry.npmjs.org/@adamhl8/eslint-plugin-clean-modules/-/eslint-plugin-clean-modules-0.1.5.tgz","fileCount":17,"unpackedSize":56357,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQCUqJ7Xj2aiOnWKSCco4TNGmzEyjH6ypOxzv63GFCSntwIhAL/c6gDAgA7YeBwkO1qPacz8331Q0gRm6WnxSyduKD12"}]},"_npmUser":{"name":"adamhl8","email":"adamhl@pm.me"},"directories":{},"maintainers":[{"name":"adamhl8","email":"adamhl@pm.me"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/eslint-plugin-clean-modules_0.1.5_1783915060705_0.5956153542437668"},"_hasShrinkwrap":false}},"time":{"created":"2026-06-30T04:42:25.378Z","modified":"2026-07-13T03:57:40.952Z","0.1.0":"2026-06-30T04:42:25.703Z","0.1.1":"2026-06-30T04:48:19.534Z","0.1.2":"2026-06-30T20:06:23.401Z","0.1.3":"2026-06-30T21:35:12.555Z","0.1.4":"2026-07-06T20:39:22.765Z","0.1.5":"2026-07-13T03:57:40.847Z"},"bugs":{"url":"https://github.com/adamhl8/eslint-plugin-clean-modules/issues"},"author":{"name":"Adam Langbert","email":"adamhl@pm.me","url":"https://github.com/adamhl8"},"license":"MIT","homepage":"https://github.com/adamhl8/eslint-plugin-clean-modules","keywords":["eslint","eslint-plugin","lint","oxlint","subpath-imports"],"repository":{"type":"git","url":"git+https://github.com/adamhl8/eslint-plugin-clean-modules.git"},"description":"oxlint/ESLint plugin: require subpath imports, direct exports, and explicit import extensions","maintainers":[{"name":"adamhl8","email":"adamhl@pm.me"}],"readme":"# @adamhl8/eslint-plugin-clean-modules\n\nAn [oxlint](https://oxc.rs/docs/guide/usage/linter) (ESLint-compatible) plugin with three rules for keeping module imports and exports clean in TypeScript projects:\n\n- [`require-subpath-imports`](#require-subpath-imports) -> ban relative imports in favor of native [Node.js subpath imports](https://nodejs.org/api/packages.html#subpath-imports)\n- [`require-direct-exports`](#require-direct-exports) -> require `export` on the declaration instead of a separate `export { ... }`\n- [`require-import-extensions`](#require-import-extensions) -> require the correct explicit file extension on local imports\n\nAll three rules are auto-fixable.\n\n---\n\n<!-- toc -->\n\n- [Installation](#installation)\n- [Usage](#usage)\n- [Rules](#rules)\n  - [`require-subpath-imports`](#require-subpath-imports)\n  - [`require-direct-exports`](#require-direct-exports)\n  - [`require-import-extensions`](#require-import-extensions)\n\n<!-- tocstop -->\n\n## Installation\n\n```bash\nbun add -D @adamhl8/eslint-plugin-clean-modules\n```\n\nThis plugin targets [oxlint's JavaScript plugins](https://oxc.rs/docs/guide/usage/linter/js-plugins) (currently in alpha). It's authored against the ESLint v9 plugin API, so it also works as a regular ESLint plugin.\n\n## Usage\n\nAdd the plugin to `jsPlugins` and enable the rules in your `.oxlintrc.json`. The rule prefix is `clean-modules`:\n\n```json\n{\n  \"jsPlugins\": [\"@adamhl8/eslint-plugin-clean-modules\"],\n  \"rules\": {\n    \"clean-modules/require-subpath-imports\": \"error\",\n    \"clean-modules/require-direct-exports\": \"error\",\n    \"clean-modules/require-import-extensions\": \"error\"\n  }\n}\n```\n\nRun `oxlint --fix` to apply fixes. Because `require-subpath-imports` and `require-import-extensions` can both rewrite the same import (`./foo` -> `#foo` -> `#foo.ts`), full convergence may take more than one `--fix` pass.\n\n## Rules\n\n### `require-subpath-imports`\n\nRelative imports (`.`, `..`, `./`, `../`) are banned. Imports of modules within the same package should use a native Node.js subpath import, defined by the `imports` field in `package.json`.\n\nThe fix resolves the relative import to the matching `#` subpath. A directory import resolves to the directory's `index` file (`index.ts`, `index.tsx`, or `index.d.ts`), since ESM has no directory resolution. If no subpath entry matches, the import is reported without a fix.\n\n```jsonc\n// package.json\n{ \"imports\": { \"#*\": \"./src/*\" } }\n```\n\n```ts\nimport { foo } from \"./foo\" // error\nimport { foo } from \"#foo\" // autofixed\n\nimport { foo } from \".\" // error (directory import)\nimport { foo } from \"#index.ts\" // autofixed\n```\n\nApplies to `import`, dynamic `import()`, `export ... from`, and `export *`.\n\n#### Options\n\n- `ignore: string[]` - skip any import whose specifier contains one of these substrings (useful for cross-package relative imports that legitimately can't map to a subpath).\n\n```json\n{ \"clean-modules/require-subpath-imports\": [\"error\", { \"ignore\": [\"@generated\"] }] }\n```\n\n### `require-direct-exports`\n\nExports should be declared directly on the declaration. Indirect exports (`export { foo }`, `export { foo as bar }`) and re-exports (`export { x } from \"...\"`, `export * from \"...\"`) are banned. This is the inverse of [`import/no-named-export`](https://github.com/oxc-project/oxc/blob/main/crates/oxc_linter/src/rules/import/no_named_export.rs).\n\n`index.*` files are exempt, since barrel re-exports legitimately live there.\n\nThe fix only handles the safe case: a local, non-renamed `export { foo }` where `foo` is a top-level declaration in the same file. It prepends `export` to the declaration and removes the statement. Renamed exports, re-exports, and multi-declarator cases are reported without a fix.\n\n```ts\nconst foo = 1\nexport { foo } // error\n\nexport const foo = 1 // autofixed\n```\n\n#### Options\n\n- `allowEmpty: boolean` (default `false`) - allow the empty `export {}` module marker.\n\n### `require-import-extensions`\n\nLocal imports (relative and `#` subpath) must use the correct file extension as it exists on disk (`.ts`, `.tsx`, or `.d.ts`). Extensions are resolved by checking the filesystem, following [TypeScript's extension substitution](https://www.typescriptlang.org/docs/handbook/modules/reference.html#file-extension-substitution). Non-TypeScript extensions (`.json`, `.css`, ...) pass through unchanged. A directory import is rewritten to its explicit `index` file (e.g. `./dir` -> `./dir/index.ts`); a directory with no `index.{ts,tsx,d.ts}` is reported without a fix. If the target file can't be found, the import is reported without a fix.\n\n```ts\nimport { foo } from \"./foo\" // error (foo.ts on disk)\nimport { foo } from \"./foo.ts\" // autofixed\n```\n","readmeFilename":"README.md"}