{"id":14978269,"url":"https://github.com/a-shleifman/eslint-plugin-export-scope","last_synced_at":"2025-04-12T20:46:45.493Z","repository":{"id":63442111,"uuid":"565250513","full_name":"A-Shleifman/eslint-plugin-export-scope","owner":"A-Shleifman","description":"Disallows importing scoped exports outside their scope","archived":false,"fork":false,"pushed_at":"2025-02-18T15:26:04.000Z","size":1460,"stargazers_count":115,"open_issues_count":2,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-12T20:46:34.380Z","etag":null,"topics":["eslint","eslint-plugin","import","package","package-private","private","scope","typescript"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/eslint-plugin-export-scope","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/A-Shleifman.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-11-12T19:59:52.000Z","updated_at":"2025-04-11T21:28:57.000Z","dependencies_parsed_at":"2024-05-29T01:43:51.563Z","dependency_job_id":"3ffd6e4a-15d1-4bdc-9d38-4a5407f5987e","html_url":"https://github.com/A-Shleifman/eslint-plugin-export-scope","commit_stats":{"total_commits":96,"total_committers":1,"mean_commits":96.0,"dds":0.0,"last_synced_commit":"05e9cc19fea047c7e10aac2a71a2778da70cb188"},"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/A-Shleifman%2Feslint-plugin-export-scope","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/A-Shleifman%2Feslint-plugin-export-scope/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/A-Shleifman%2Feslint-plugin-export-scope/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/A-Shleifman%2Feslint-plugin-export-scope/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/A-Shleifman","download_url":"https://codeload.github.com/A-Shleifman/eslint-plugin-export-scope/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248631718,"owners_count":21136559,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["eslint","eslint-plugin","import","package","package-private","private","scope","typescript"],"created_at":"2024-09-24T13:57:15.318Z","updated_at":"2025-04-12T20:46:45.463Z","avatar_url":"https://github.com/A-Shleifman.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# eslint-plugin-export-scope\n\nDon't leak **LOCAL** utils, states, contexts, components into the global scope.\n\n![Basics](/readme-src/basics.jpg \"Basics\")\n\n## Demo\n\n![Demo](/readme-src/demo.gif \"Demo\")\n\n## Scopes\n\n\u003cp align=\"center\"\u003e\n\n| scope           | importable from                         |                               |\n| --------------- | --------------------------------------- | ----------------------------- |\n| .               | current directory and children          | default for all exports       |\n| ..              | parent directory and children           | default for **`index`** files |\n| ../..           | two directories above and children      |                               |\n| src/consumer    | within specified directory and children |                               |\n| src/consumer.ts | within specified file                   |                               |\n| \\*              | anywhere                                |                               |\n\n\u003c/p\u003e\n\n## Scoped Exports\n\n```ts\n/** @scopeDefault ../.. */\n/** ☝ Applies to all exports in the file unless overriden with a local `@scope` */\n\n/** @scope * */\nexport const helper1 = \"\"; // 👈 Available everywhere\n\nexport const helper2 = \"\"; // 👈 inherits scope `../..` from `@scopeDefault`\n\n/** @scope src/components */\nexport default \"\";\n```\n\n```ts\n/** @scope .. */\nconst helper3 = \"\";\n\nexport { helper3 }; // 👈 inherits the scope from the variable declaration\n```\n\n## Default folder scope with `.scope.ts` files\n\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"./readme-src/scope_file.png\" width=\"500\" title=\"Scope File example\"\u003e\n\u003c/p\u003e\n\n```ts\n└── src\n  └── `common`\n    ├── utils.ts\n    ├── context.ts\n    └── `.scope.ts`\n             │\n             │\n  ╭────────────────────╮\n  │ export default '*' │\n  ╰────────────────────╯\n// ⬆ this will make all exports within `common`\n// importable from anywhere unless a\n// specific export is overriden on a lower level\n\n```\n\n### Exceptions\n\n#### Export scope exceptions\n\n```ts\n// schema.ts\n/**\n * @scope ..\n * @scopeException src/schemaConsumer 👈 whole folder has access\n * @scopeException src/schemaConsumer/index.ts 👈 whole file has access\n */\nexport default \"\";\n```\n\n#### Folder scope exceptions in `.scope.ts` files\n\n```ts\n└── src\n  └── `generated`\n    ├── schema.ts\n    └── `.scope.ts`\n             │\n             │\n  ╭──────────────────────────────────╮\n  │ export default '.';              │\n  │                                  │\n  │ export const exceptions = [      │\n  │   'src/schemaConsumer',          │\n  │   'src/scripts/schemaParser.ts', │\n  │ ]                                │\n  ╰──────────────────────────────────╯\n// ⬆ by default exports are only importable\n// within `generated` folder, but\n// folders/files in `exceptions` are exempt.\n\n```\n\n## Installation\n\nInstall [ESLint](https://eslint.org/) and the `export-scope` package. This package includes both an `ESLint` plugin and a `TS Language Server` plugin.\n\n#### ESLint plugin will highlight imports outside the scope\n\n\u003cdetails\u003e\n  \u003csummary\u003eUsing ESLint Flat Config (ESLint v8 if enabled, ESLint v9)\u003c/summary\u003e\n\n```sh\nnpm i -D eslint typescript-eslint eslint-plugin-export-scope\n```\n\n```json\n// package.json\n\n{\n  \"type\": \"module\"\n}\n```\n\n```js\n// eslint.config.js\n\n// @ts-check\n\nimport tseslint from \"typescript-eslint\";\nimport exportScope from \"eslint-plugin-export-scope\";\n\nexport default tseslint.config(\n  // other configs,\n  exportScope.configs.flatConfigRecommended,\n);\n```\n\n\u003cdetails\u003e\n  \u003csummary\u003eManual Flat Config\u003c/summary\u003e\n\n```js\n// eslint.config.js\n\n// @ts-check\n\nimport tseslint from \"typescript-eslint\";\nimport exportScope from \"eslint-plugin-export-scope\";\n\nexport default tseslint.config(\n  // other configs,\n  {\n    files: [\"**/*.ts\", \"**/*.tsx\", \"**/*.js\", \"**/*.jsx\", \"**/*.mts\", \"**/*.mjs\", \"**/*.cjs\"],\n    plugins: { \"export-scope\": exportScope.plugin },\n    rules: { \"export-scope/no-imports-outside-export-scope\": \"error\" },\n    languageOptions: { parser: tseslint.parser, parserOptions: { projectService: true }, sourceType: \"module\" },\n  },\n);\n```\n\n\u003c/details\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eUsing Legacy Config\u003c/summary\u003e\n\n```sh\nnpm i -D eslint @typescript-eslint/parser eslint-plugin-export-scope\n                    # ⬆ ^8.0.0\n```\n\n```js\n// .eslintrc.js\nmodule.exports = {\n  // ...\n  extends: [\"plugin:eslint-plugin-export-scope/recommended\"],\n  parser: \"@typescript-eslint/parser\",\n  parserOptions: { project: true, tsconfigRootDir: __dirname },\n  ignorePatterns: [\"!.scope.ts\"],\n};\n```\n\n\u003cdetails\u003e\n  \u003csummary\u003eManual Legacy Config\u003c/summary\u003e\n\n```js\n// .eslintrc.js\nmodule.exports = {\n  // ...\n  parser: \"@typescript-eslint/parser\",\n  parserOptions: { project: true, tsconfigRootDir: __dirname },\n  plugins: [\"export-scope\"],\n  rules: { \"export-scope/no-imports-outside-export-scope\": \"error\" },\n  ignorePatterns: [\"!.scope.ts\"],\n};\n```\n\n\u003c/details\u003e\n\u003c/details\u003e\n\n#### TS plugin will disable autocompletion for exports outside the scope\n\n```js\n// tsconfig.json\n\"compilerOptions\": {\n  \"plugins\": [{ \"name\": \"eslint-plugin-export-scope\" }],\n},\n\"include\": [\"**/*\", \"**/.scope.ts\"]\n//                  \"../../**/.scope.ts\" for monorepos\n```\n\nTell VSCode to `Use Workspace Version` of TypeScript. Otherwise TS plugin won't work.\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"readme-src/ts_version.png\" alt=\"Select TS version\" width=\"600\" /\u003e\n\u003c/p\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eConfiguration for JS projects\u003c/summary\u003e\n\n- `tsconfig.json` file is still required for the plugin to work\n- replace `.scope.ts` in both configs with `.scope.js`\n- set `compilerOptions.allowJs`to `true` in `tsconfig.json`\n\u003c/details\u003e\n\n## Upgrading from v1 to v2\n\n- Replace all `//` comments with jsDocs `/** */`\n- Replace `@scope default` with `@scopeDefault`\n- Relace `@..` file/folder prefixes with `.scope.ts` files.\n- Make sure `.eslintrc.js` and `tsconfig.json` configs are updated\n\n## Hints\n\n- Type `@` above exports for automatic jsDoc generation.\n- Use autocompletion provided within jsDocs and `.scope.ts` files.\n- Root `.scope.ts` file (next to package.json) sets the default for the whole project. Having `export default '*'` there will make all exports global by default if you prefer a less strict approach.\n\n## Issues\n\n⚠️ To re-lint an import in VSCode after updating a `scope` declaration either `touch` this import or restart the ESLint Server [(ESLint limitation)](https://github.com/microsoft/vscode-eslint/issues/1565#event-7958473201).\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"readme-src/restart_eslint_server.png\" alt=\"Restart ESLint Server\" width=\"200\" /\u003e\n\u003c/p\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fa-shleifman%2Feslint-plugin-export-scope","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fa-shleifman%2Feslint-plugin-export-scope","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fa-shleifman%2Feslint-plugin-export-scope/lists"}