How to use `eslint-config-airbnb` with the new eslint config spec? - eslint

What is the correct way to use eslint-config-airbnb with new eslint config spec?
I tried to import eslint-config-airbnb. However, the config is not complying with the new spec.
import airbnb from 'eslint-config-airbnb';
console.log(airbnb);
/* this prints
{
extends: [
'<path_to_repo>/node_modules/eslint-config-airbnb-base/index.js',
'<path_to_repo>/node_modules/eslint-config-airbnb/rules/react.js',
'<path_to_repo>/node_modules/eslint-config-airbnb/rules/react-a11y.js'
],
rules: {}
}*/
I tried to import the files in the extends section in the above config. But those files aren't in the new spec either.

I believe esint-config-airbnb is not compatible with the new eslint config at the moment.
However, you can still use it with the new eslint config through #eslint/eslintrc which is a backward compatibility utility provided by ESLint team.
There was a how-to guide on eslint's blog here https://eslint.org/blog/2022/08/new-config-system-part-2/#backwards-compatibility-utility.

Related

Vite: Cannot use import statement outside a module

I know little about bundler and I'm using vite to build project, I got a error when import some package to configure dev server :
SyntaxError: Cannot use import statement outside a module
So here is the thing:
import pinyin from 'pinyin/esm/pinyin-web.js'
export const somePlugin = {
name: 'someplugin',
configureServer(server) {
server.middlewares.use('/somepath', (req, res, next) => {
const foo = pinyin('foo')
next()
})
},
}
I don't use the normal way(import pinyin from 'pinyin') , because that need a package nodejieba which need to install unnecessary node-gyp, so I choose the web version that don't need nodejieba.
I've searched the error, some says add "type": "module" to package.json file. but it already exist in my package.json.
however, I make the change:
// import pinyin from 'pinyin/esm/pinyin-web.js'
import pinyin from 'pinyin/lib/pinyin-web.js'
and problem get solved,I was confused because I thought vite prefer ES module.
So,
1> what cause the problem above?
2> why should I import file with extensions ? eg: import pinyin from 'pinyin/lib/pinyin-web.js'
I have to add extensions .js or it will cause error. while in vite.config.ts I needn't add extensions.
3> I tried to add field optimizeDeps in vite.config.ts like this
export default defineConfig({
plugins: [vue(), somePlugin],
optimizeDeps: {
include: ['pinyin'],
},
})
but it seems to be useless, the offical doc says:
"During development, Vite's dev serves all code as native ESM. Therefore, Vite must convert dependencies that are shipped as CommonJS or UMD into ESM first."
did that work for the frontend part and package "pinyin" is for the dev server so whether add the
field optimizeDeps there is no difference.
codesandbox

"SyntaxError: Cannot use import statement outside a module" when test Konva

i write a chess game by konva.js and typescript.
now i want to test it with ts-jest, but error happen when import Konva.
here is error messenge.
i know it possibly cause by esModule compiler.
i have tried to add konva in transformIgnorePatterns ,but not work.
or i should mock konva by _mock_?
how i fix it ,thanks all.
Jest encountered an unexpected token
Jest failed to parse a file. This happens e.g. when your code or its dependencies use non-standard JavaScript syntax, or when Jest is not configured to support such syntax.
Out of the box Jest supports Babel, which will be used to transform your files into valid JS based on your Babel configuration.
By default "node_modules" folder is ignored by transformers.
Here's what you can do:
• If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/ecmascript-modules for how to enable it.
• If you are trying to use TypeScript, see https://jestjs.io/docs/getting-started#using-typescript
• To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
• If you need a custom transformation specify a "transform" option in your config.
• If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.
You'll find more details and examples of these config options in the docs:
https://jestjs.io/docs/configuration
For information about custom transformations, see:
https://jestjs.io/docs/code-transformation
Details:
D:\code\chess\chess\node_modules\konva\lib\index-node.js:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){import { Konva } from './_FullInternals.js';
Here is my jest.config.js that worked for me with ts-jest:
/** #type {import('ts-jest/dist/types').InitialOptionsTsJest} */
module.exports = {
preset: 'ts-jest',
testEnvironment: 'jsdom',
moduleNameMapper: {
'^konva': 'konva/konva',
},
globals: {
'ts-jest': {
diagnostics: false,
useESM: true,
},
},
};

eslint rule #nrwl/nx/enforce-module-boundaries fails

Intro
I was very confused with that rule when I recently ported the Ng code base to Nx 12.x. I hope this post helps others who begin migrating from Ng to Nx.
The code base above is a rather small single repo which is now used in production. When using Nx it's a good practice to follow the recommendations for monorepo to be able to use the monorepo benefits in the future as the code base is growing. (E.g. here I'm avoiding the overexposing of the code in the current repo).
I put the code base above into my-org/apps/my-small-repo. By linting I was confused by the failure of the rule #nrwl/nx/enforce-module-boundaries. So I tried different possibilities of mapping the src/app of my-org/apps/my-small-repo where either compiler or linter or both just failed.
I figured out the following solutions.
Solution 1
Just put
"compilerOptions": {
"baseUrl": "src"
},
into the root of apps/my-small-repo/tsconfig.json and replace all of your imports inside of apps/my-small-repo with imports beginning with app.
Example for a DashboardComponent:
import { DashboardComponent } from 'app/components/dashboard/dashboard.component';
Probably a better solution
This solution is tested on nx 13.x, but it probably works on previous versions of nx also.
Put
"app/*": ["apps/my-org/src/app/*"]
to the paths in compilerOptions of your tsconfig.base.json in the repo root. Then put "allowCircularSelfDependency": true, to the rule #nrwl/nx/enforce-module-boundaries in the repo root.
We decided for "allowCircularSelfDependency": true, to avoid working with ugly relative paths like like e.g. this one ../../../../../ in the app. And we also want to have library namespaces in tsconfig.base.json only.
Documentation of the rule
https://github.com/nrwl/nx/blob/master/packages/eslint-plugin-nx/src/rules/enforce-module-boundaries.ts
For those who are coming here without this getting resolved. (nx monorepo usage)
Trouble shooting the 2 errors (TS error and lint error):
First the Alias error:
Cannot find module '#account/components/something' or its corresponding type declarations.
On your base tsconfig.base.json (not tsconfig.json under your apps as it gets overrided), add:
"compilerOptions":{
...
baseUrl:"." // Try "src" as well incase of boiler plates or if your resolved path (on the error) is missing an src.
path: {
"#account/*": ["app/*"],
"#account/components/*": ["app/components/*"]
}
},
The above will resolve:
import { authMiddleware } from '#account/components/something';
from
import { authMiddleware } from '../../../components/something';
For lint error:
Projects should use relative imports to import from other files within the same project - eslint rule #nrwl/nx/enforce-module-boundaries fails`
Add "allowCircularSelfDependency": true.
"#nrwl/nx/enforce-module-boundaries": [
"error",
{
"allowCircularSelfDependency": true, -> This may solve the lint error.
"allow": ["#account/**"], -> // White list the lint error.
...
}
Whitelist the folders: Add "allow": [#foldername]
"#nrwl/nx/enforce-module-boundaries": [
"error",
{
"allow": ["#account/**"], -> // White list the lint error.
...
}
That should fix it.
To get this working:
On your base tsconfig.base.json or your local tsconfig.json.
I suggest to do it on the tsconfig.base.json
Considering your path apps/my-org/src/app/*
"compilerOptions":{
...
baseUrl:"src"
path: {
"#app/*": ["app/*"] // << Here is the change
}
},
Import in your code files from this apps/my-org/src/app/*
to this #app/*

How to disable autofix for specific rules in eslint using CLI?

I want to be able to disable the rules that --fix fixes when running eslint in a console for a repo. The reason for this is because --fix leads to undesirable behavior for our jsdoc eslint rules. It creates invalid or sometimes empty jsdoc in our project- which typically leads to even more eslint rules (due to our configuration) and leads to tons of manual fixing or removal.
I want to just run --fix without it touching any jsdoc rules so that I can complete jsdoc manually- while eslint fixes all the rest of the rules.
I came across this SO question- but package mentioned in the answer does not support non-core plugins.
ESLint autofix ignore rule
Is there anything I can do short of modifying my eslintrc file every time I run the linter or using vscode for linting and modifying the config for the web editor instead? Its not a big deal for newer files- but linting legacy files is a chore when there's hundreds of spacing errors that I can't automatically fix easily.
Using an .eslintrc.js file you can do something like this:
const isFixMode = process.argv.includes('--fix');
const config = {
rules: {
'no-console': 'error',
...(isFixMode && {
'no-console': 'warn',
}),
},
};
module.exports = config;
Technically, that already exists, right? If a user wants to avoid auto-fixing a particular rule, they can use:
eslint somedir --fix --rule "somerule: 0"
Or, if they want to whitelist a set of rules, they can use &nbps --no-eslintrc and specify rules directly or use --config and point to a particular config that they want to use for fixes.
Ok here’s another idea. Convert you .eslinrc file into .eslintrc.js. This will allow you to programmatically set eslint config.
Then you could use the commander library to detect the —fix flag and set a Boolean to determine which eslint rules you would like to disable.
What worked best for me was setting the rule to warn and afterwards run.
eslint . --fix --quiet
It is not an error anymore, but better than getting my code broken by a erroneous fixer.

Yarn workspaces -- package alias

TL;DR How can I create an alias for a local yarn workspace dependency?
I've tried yarn workspaces before and never succeeded, and I'm giving it another try.
I've set "workspaces": ["packages/*"] in package.json.
For each package, I decided to use the naming convention #-/package-name to prevent naming conflicts and without worrying about having namespaces for internal packages.
When adding packages as dependencies, I've been following a style where I use an interface name for resolution, but point that towards a concrete implementation. This is what I did before using yarn workspaces:
"dependencies": {
"my-interface-name": "file:some/path/to/packages/some-concrete-implementation"
}
This is basically to allow what I like to call compile-time static dependency injection. And it also means each package can individually name their interface dependencies appropriately to their need and to prevent naming conflicts.
However, I can't figure out how to accomplish this with yarn workspaces. How do I create an alias for my yarn workspaces package #-/some-concrete-implementation called my-interface-name?
What I've already tried with no success:
Defining the dependency like "my-interface-name": "#-/some-concrete-implementation"} - for some reason this causes yarn to look for #-/some-concrete-implementation on the npm registry instead of in the local workspace
I've also tried to use the workspace protocol: "my-interface-name": "workspace:#-/some-concrete-implementation"} but it still looks for the package on the npm registry!
What I haven't yet tried and could work but removes benefits of using yarn workspaces in the first place:
"dependencies": {"my-interface-name": "file:../../node_modules/#-/some-concrete-implementation"}"
Have you seen the resolutions package.json key? Is it what you need?
I've used it for aliasing/overriding external packages but the example in the docs shows it working with local packages.
Resolutions
Allows you to override a version of a particular nested dependency. See the Selective Versions Resolutions RFC for the full spec.
{
"resolutions": {
"transitive-package-1": "0.0.29",
"transitive-package-2": "file:./local-forks/transitive-package-2",
"dependencies-package-1/transitive-package-3": "^2.1.1"
}
}
From the RFC:
"**/a" denotes all the nested dependencies a of the project.
"a" is an alias for **/a (for retro-compatibility, see below, and because if it wasn't such an alias, it wouldn't mean anything as it would represent one of the non-nested project dependencies, which can't be overridden as explained below).
So, I believe the rule you need is:
"**/my-interface-name": "file:some/path/to/packages/some-concrete-implementation"
// OR equivalent
"my-interface-name": "file:some/path/to/packages/some-concrete-implementation"
I believe it works in the package's package.json. Worst case you can hoist it to the workspace root and make the rule specific to the workspace e.g. "a/b".
The workspace: alias protocol (available in pnpm too) seems the direction to take.
I've also tried to use the workspace protocol: "my-interface-name": "workspace:#-/some-concrete-implementation"} but it still looks for the package on the npm registry!
Be sure to have yarn 3 installed, otherwise you'll run into weird issues.
Note that the syntax of "my-interface-name": "workspace:#-/some-concrete-implementation" looks incorrect.
It should be "#xxx/some-concrete-implementation": "workspace:*", assuming the name of linked the package is "name": "#xxx/some-concrete-implementation".
With this in mind you don't even need to create a specific #-/name. With workspace protocol, yarn will ensure it's never downloaded from npm. It becomes an internal workspace dependency.
PS:
Yarn 3 installation
Generally a simple yarn set version 3.0.2 && yarn plugin import workspace-tools) will work.
To avoid pnp current limitation, check the generated config .yarnrc.yml and ensure nmLinker is set to 'node-modules'
# Yarn 2+ supports pnp or regular node_modules installs. Use node-modules one.
nodeLinker: node-modules
plugins:
- path: .yarn/plugins/#yarnpkg/plugin-workspace-tools.cjs
spec: "#yarnpkg/plugin-workspace-tools"
yarnPath: .yarn/releases/yarn-3.0.2.cjs
PS: you might want to add this to .gitignore too
.yarn/*
!.yarn/patches
!.yarn/releases
!.yarn/plugins
!.yarn/sdks
!.yarn/versions
.pnp.*
Run a yarn install just after.
About package.json's
Like you did, the root package.json will define the workspace paths:
{
"name": "monorepo",
"workspaces": [
"packages/*" // Enable package discovery in packages/* directory.
],
// ...
"devDependencies": {
"husky": "7.0.2", // Only what's needed for monorepo management
}
In your app packages/app/package.json
{
"name": "my-app",
"devDependencies": {
"#types/node": "16.10.1",
//...
},
"dependencies": {
// Assuming the name of packages/shared is "#your-org/some-concrete-implementation",
// we explicitly declare the dependency on it through
// workspace: alias (package-manager perspective)
"#your-org/some-concrete-implementation": "workspace:*",
}
}
You consumed package should declare the same name
{
"name": "#your-org/some-concrete-implementation",
}
Bonus: Typescript aliases
If your project is written in ts, you can even replicate your paths through
typescript path mapping. It will allow to include the files just as is (no prior compilation needed).
Following your example, just edit a ./packages/xxx/tsconfig.json in this way
{
"compilerOptions": {
// here baseUrl is set at ./src (good practice), can
// be set to '.'
"baseUrl": "./src",
"paths": {
// Declare deps here (keep them in sync with what
// you defined in the package.json)
// PS: path are relative to baseUrl
"#your-org/some-concrete-implementation/*": ["../../some-concrete-implementation/src/*"],
// if you have a barrel in ui-lib
"#your-org/some-concrete-implementation": ["../../some-concrete-implementation/src/index"],
}
},
}
PS: for non typescript: babel/plugin-module-resolver can be used in a similar manner.

Resources