A-Shleifman / eslint-plugin-export-scope

Disallows importing scoped exports outside their scope
https://www.npmjs.com/package/eslint-plugin-export-scope
105 stars 0 forks source link
eslint eslint-plugin import package package-private private scope typescript

eslint-plugin-export-scope

Don't leak LOCAL utils, states, contexts, components into the global scope.

Basics

Demo

Demo

Scopes

| scope | importable from | | | --------------- | --------------------------------------- | ----------------------------- | | . | current directory and children | default for all exports | | .. | parent directory and children | default for **`index`** files | | ../.. | two directories above and children | | | src/consumer | within specified directory and children | | | src/consumer.ts | within specified file | | | \* | anywhere | |

Scoped Exports

/** @scopeDefault ../.. */
/** ☝ Applies to all exports in the file unless overriden with a local `@scope` */

/** @scope * */
export const helper1 = ""; // 👈 Available everywhere

export const helper2 = ""; // 👈 inherits scope `../..` from `@scopeDefault`

/** @scope src/components */
export default "";

Default folder scope with .scope.ts files

└── src
  └── `common`
    ├── utils.ts
    ├── context.ts
    └── `.scope.ts`
             │
             │
  ╭────────────────────╮
  │ export default '*' │
  ╰────────────────────╯
// ⬆ this will make all exports within `common`
// importable from anywhere unless a
// specific export is overriden on a lower level

Exceptions

Export scope exceptions

// schema.ts
/**
 * @scope ..
 * @scopeException src/schemaConsumer 👈 whole folder has access
 * @scopeException src/schemaConsumer/index.ts 👈 whole file has access
 */
export default "";

Folder scope exceptions in .scope.ts files

└── src
  └── `generated`
    ├── schema.ts
    └── `.scope.ts`
             │
             │
  ╭──────────────────────────────────╮
  │ export default '.';              │
  │                                  │
  │ export const exceptions = [      │
  │   'src/schemaConsumer',          │
  │   'src/scripts/schemaParser.ts', │
  │ ]                                │
  ╰──────────────────────────────────╯
// ⬆ by default exports are only importable
// within `generated` folder, but
// folders/files in `exceptions` are exempt.

Installation

Install ESLint and the export-scope package. This package includes both an ESLint plugin and a TS Language Server plugin.

ESLint plugin will highlight imports outside the scope

Using ESLint Flat Config (ESLint v8 if enabled, ESLint v9) ```sh npm i -D eslint typescript-eslint eslint-plugin-export-scope ``` ```json // package.json { "type": "module" } ``` ```js // eslint.config.js // @ts-check import tseslint from "typescript-eslint"; import exportScope from "eslint-plugin-export-scope"; export default tseslint.config( // other configs, exportScope.configs.flatConfigRecommended, ); ```
Manual Flat Config ```js // eslint.config.js // @ts-check import tseslint from "typescript-eslint"; import exportScope from "eslint-plugin-export-scope"; export default tseslint.config( // other configs, { files: ["**/*.ts", "**/*.tsx", "**/*.js", "**/*.jsx", "**/*.mts", "**/*.mjs", "**/*.cjs"], plugins: { "export-scope": exportScope.plugin }, rules: { "export-scope/no-imports-outside-export-scope": "error" }, languageOptions: { parser: tseslint.parser, parserOptions: { project: true } }, }, ); ```
Using Legacy Config ```sh npm i -D eslint @typescript-eslint/parser eslint-plugin-export-scope # ⬆ v6 or above ``` ```js // .eslintrc.js module.exports = { // ... extends: ["plugin:eslint-plugin-export-scope/recommended"], parser: "@typescript-eslint/parser", parserOptions: { project: true, tsconfigRootDir: __dirname }, ignorePatterns: ["!.scope.ts"], }; ```
Manual Legacy Config ```js // .eslintrc.js module.exports = { // ... parser: "@typescript-eslint/parser", parserOptions: { project: true, tsconfigRootDir: __dirname }, plugins: ["export-scope"], rules: { "export-scope/no-imports-outside-export-scope": "error" }, ignorePatterns: ["!.scope.ts"], }; ```

TS plugin will disable autocompletion for exports outside the scope

// tsconfig.json
"compilerOptions": {
  "plugins": [{ "name": "eslint-plugin-export-scope" }],
},
"include": ["**/*", "**/.scope.ts"]
//                  "../../**/.scope.ts" for monorepos

Tell VSCode to Use Workspace Version of TypeScript. Otherwise TS plugin won't work.

Select TS version

Configuration for JS projects - `tsconfig.json` file is still required for the plugin to work - replace `.scope.ts` in both configs with `.scope.js` - set `compilerOptions.allowJs`to `true` in `tsconfig.json`

Upgrading from v1 to v2

Hints

Issues

⚠️ To re-lint an import in VSCode after updating a scope declaration either touch this import or restart the ESLint Server (ESLint limitation).

Restart ESLint Server