Git Product home page Git Product logo

eslint-plugin-import-access's Introduction

eslint-plugin-import-access

What?

This package provides a typescript-eslint rule that restricts importing variables marked as @package from a file outside the same directory. Also, this package serves as a TypeScript Language Service Plugin that prevents auto-completion of such imports.

Illustration of how @package works.

Why?

The largest encapsulation unit available for a TypeScript project is a file. That is, variables not exported from a file is only visible to code in the same file. Once a variable is exported, it is visible from the entire project.

Sometimes this is insufficient. A rational effort for proper encapsulation may result in a large file that is hard to maintain.

This package solves this problem by providing a new directory-level layer and enabling a “package-private” export that is only visible to files in the same directory.

Installation

npm i -D eslint-plugin-import-access

Depending on how you configure ESLint, use either Flat Config or eslintrc to configure eslint-plugin-import-access.

Also, you can enable the TypeScript Language Service Plugin by adding it to the plugins array in tsconfig.json.

Flat Config

In eslint.config.js:

import typescriptEslintParser from "@typescript-eslint/parser";
import importAccess from "eslint-plugin-import-access/flat-config";

export default [
  // other settings...
  {
    // set up typescript-eslint
    languageOptions: {
      parser: typescriptEslintParser,
      parserOptions: {
        project: true,
        sourceType: "module",
      },
    },
  },
  {
    plugins: {
      "import-access": importAccess,
    },
  },
  {
    rules: {
      "import-access/jsdoc": ["error"],
    },
  },
];

Note: currently you need to import the plugin from the /flat-config subpath. In a future version, this will be simplified.

eslintrc

In .eslintrc.js:

  // set up typescript-eslint
  "parser": "@typescript-eslint/parser",
  "parserOptions": {
    "project": true,
    "sourceType": "module"
  },
  "plugins": [
    "import-access",
    // ...
  ],
  "rules": {
    "import-access/jsdoc": ["error"],
  }

TypeScript Language Service Plugin

In tsconfig.json:

{
  "compilerOptions": {
    // ...
    "plugins": [
      // ...
      {
        "name": "eslint-plugin-import-access"
      }
    ]
  }
}

Note: to enable TypeScript language service plugins installed locally, you must use TypeScript in node_modules, not the one bundled with VSCode.

Example

// ----- sub/foo.ts -----

/**
 * @package
 */
export const fooPackageVariable = "I am package-private export";

// ----- sub/bar.ts -----
// This is correct because foo.ts is in the same directory
import { fooPackageVariable } from "./foo";

// ----- baz.ts -----
// This is INCORRECT because package-private exports
// cannot be imported from outside the sub directory
import { fooPackageVariable } from "./sub/foo";

Rule References

Contributing

Welcome

License

MIT

eslint-plugin-import-access's People

Contributors

dependabot[bot] avatar m-shaka avatar mozisan avatar nguyentringhia avatar okunokentaro avatar seito2 avatar uhyo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

eslint-plugin-import-access's Issues

Proposal: selfReferencingLoophole

As this concerns the API design of this plugin, I will start from this proposal. As a new feature, I would like to add selfReferencingLoophole via the exports field in the package.json.

Let me explain in details with a specific use case. In the component library I am currently developing, I am writing Storybook stories only for the public API. In the package.json, I have specified the exports as follows, and I use them in Storybook like import { SomeComponent } from 'my-library/components'. (This is called as self-referencing in the Node.js document)

{
  "name": "my-library",
  "exports": {
    "./components": {
      "type": "./src/components/index.ts",
      "default": "./src/components/index.ts",
    },
    "./styles": {
      "type": "./src/styles/index.ts",
      "default": "./src/styles/index.ts",
    },
}

Currently, I have to manually add the @public comment tag to all the members exported from src/components/index.ts. This is because I have set the defaultImportability to 'package', and I place story files in a 'stories' directory which is a sibling directory of 'src'.

However, since src/components/index.ts is intended as the public API, the task of adding comment tags feels excessively cumbersome. It would be greatly appreciated if, as an option, we could have self-referencing automatically treated as public.

Flat Config Support

We cannot use eslint-plugin-import-access with Flat Config. 😨 This is caused by providing TypeScript Language Server Plugin from the same module.

Config

import typescriptEslintParser from "@typescript-eslint/parser";
import importAccess from 'eslint-plugin-import-access';

export default [
  {
    languageOptions: {
      parser: typescriptEslintParser,
    },
    files: ['**/*.ts'],
    plugins: {
      'import-access': importAccess,
    },
    rules: {
      'import-access/jsdoc': 'error'
    }
  }
]

Error message

ESLint: 9.0.0

ConfigError: Config (unnamed): Key "plugins": Key "import-access": Expected an object.

Workaround

    plugins: {
      'import-access': { ...importAccess },
    },

`import * as namespace` is not checked

When import a file via import * as, there is still a chance to expose package/private exports to outside. Is it a bug or design limitation?

// ----- sub/foo.ts -----
/** @public */
export const public_var = 0;

/** @package */
export const package_var = 0;

// ----- baz.ts -----
import * as Foo from "./sub/foo";
Foo.public_var;
Foo.package_var;
    // ^ expect error here

Import from export * cause error

When I try export from like this :

/app/bff/client.ts

export const function1 = () => {}
export const function2 = () => {}
...
export const function_n = () => {}

And in app folder I have exported will package jsdoc like this.

/*
@public
*/
export * from './client'

From the same level folder with bff. Let's say component folder . I try to to import like this.

import {function1} from './bff

It's will throw Cannot import a package-private export 'function1'.

Is that a bug of plugin. Or can you show me how to solve this problem.

Default exports; A rule for entire files

Thank you for this amazing plugin @uhyo!

I have two questions:

  1. Is there a way to make this rule work for default exports? Doesn't seem to work at the moment.
  2. Is there a way to apply @package rule to an entire file?

private:reexport is allowed

Hi.
I found that I can reexport members annotated with @private, although importing them is incorrect as expected)
I have a reproduction code available at the following GitHub repository: https://github.com/m-shaka/minimum-reproduction-private-access.

Interestingly, I added a test to check private:reexport in a forked repository, and the rule seems to be working fine!
You can find the commit with the test here:
f0d5fae

Do you have any idea about the cause behind this behavior?

An update is recommended.

This package is a very good project that implemented what I thought. However, there are some things that I would like to see updated further. It would be more perfect if we could restrict imports to each other even within the same folder path.

/**
 * @package
 * "./page/home.tsx"
 */

List the available paths as follows. Can you please update this feature??

A grammar that restricts all imports, a grammar that allows only some paths to be used

It would be nice to add these two.


If you don't have enough resources to work on this project, I'll blow a PR and add it! Just say something.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.