How to use import inside eslintrc file? - javascript

I'm trying to use imported object to setup some restrictions for globals inside .eslintrc.js file, but import doesnt work. How can i make dynamic eslint config?
import {loadedGlobals} from '#/util/globals'
module.exports = {
'globals': Object.keys(loadedGlobals).reduce((acum, key) => {
acum[key] = false
return acum
}, acum),
// ...
}

How to use import inside eslintrc file?
ESLint currently doesn't support a configuration file by the name of eslintrc so I'm going to assume you mean .eslintrc.js.
ESLint currently does not support ES Modules as you can see from the JavaScript (ESM) bullet item on their configuration file formats documentation.
If you are willing to install another dependency here is how you can use import inside of .eslintrc.js:
Install the esm module, npm i esm -D (Here I'm choosing as a devDependency).
Create a new file as a sibling to .eslintrc.js called .eslintrc.esm.js.
Inside of .eslintrc.esm.js include your ESLint configuration. Here you can use import and you should export your configuration as export default { // Your config }.
Inside .eslintrc.js include the following code:
const _require = require('esm')(module)
module.exports = _require('./.eslintrc.esm').default
Now you should be able to run eslint as usual. A bit clunky with the extra file, but you can organize them in a directory if you like and use the --config option of eslint to point to the new location.

You might notice that you are using the old syntax when exporting your object. You could try using require() instead of import.
Alternatively, you could look into Shareable Configs.

Related

Problem with the folder structure and dependencies

I have the following initial situation:
Our tests refer to a store that is available in multiple languages via country dropdown.
Depending on the country, the store has different features and therefore also different tests.
I have two problems here. The first is the folder structure
In order not to have a separate repo for each country, we would like to separate the test specs for the stores by folders.
But since the PageObjects are identical, I would like to define them only once, so that the test specs can access them.
However, it does not work as I imagine it.
Here is my idea of the folder structure in Cypress:
cypress-automation
cypress
fixtures
integration
shops
shop_de
sample-tests.spec.js
shop_en
sample-tests.spec.js
shop_es
sample-tests.spec.js
plugins
index.js
support
pageObjects
samplePageObject.js
index.js
commands.js
node_modules
cypress.json
package-lock.json
package.json
However, it doesn't work because Cypress misses the PageObjects. The following error occurs:
Error: webpack compilation error
./cypress/integration/shops/shop_en/sample-tests.spec.js
Module not found: Error: Unable to resolve '../support/pageObjects/samplePageObject.js' in 'C:\users\users\desktop\cypress-automation\cypress\integration\shops\shop_en'.
The second problem concerns the index.js
there I have to add a country switch in the beforeEach method, because the URLs of the stores are identical and the store can only be changed via dropdown.
Unfortunately I don't know how to integrate the index.js into the store folder, so that the sample-tests.spec.js access a specific index.js instead of a global one. Alternatively, I would have to adjust the beforeEach method in each sample-tests.spec.js but with so many test specs I find that impractical.
is that even possible, the way I imagine it?
EDIT:
#Fody
i did it exactly as you said. However, now I get an error:
PageObjects_homePage__WEBPACK_IMPORTED_MODULE_1_.HomePage is not a constructor
here is an example from my code how i included it:
import { HomePage } from "#PageObjects/homePage";
the constructor looks like this
const homePage = new HomePage();
HomePage Class:
class HomePage {
testMethod() {
testcode()
}
}
export default HomePage;
For part one, set up a webpack alias to make it easy to import from anywhere in the intergration folders, any level nesting.
Add the package Cypress Webpack Preprocessor, following their instructions
npm install --save-dev #cypress/webpack-preprocessor
npm install --save-dev #babel/core #babel/preset-env babel-loader webpack - if not already installed
or with yarn
yarn add -D #cypress/webpack-preprocessor
yarn add -D #babel/core #babel/preset-env babel-loader webpack - if not already installed
cypress/plugins.index.js
/// <reference types="cypress" />
const path = require('path');
const webpack = require('#cypress/webpack-preprocessor');
console.log('__dirname', __dirname) // __dirname is cypress/plugins
module.exports = (on) => {
const options = {
webpackOptions: {
resolve: {
alias: {
'#PageObjects': path.resolve(__dirname, '../../cypress/support/pageObjects')
},
},
},
watchOptions: {},
};
on('file:preprocessor', webpack(options));
};
cypress/integration/shops/shop_de/sample-tests.spec.js
// resolves any level of nesting
import {MyPageObject} from '#PageObjects/samplePageObject.js'
...
cypress/integration/shops/shop_de/bavaria/sample-tests.spec.jbs
// same import after move to sub-folder
import {MyPageObject} from '#PageObjects/samplePageObject.js'
...

How does webpack pick a relative path inside node_modules ? does it reference package.json at all?

When i do npm install react-slick, i get the following in my node_modules folder:
Now in my react application in a src/index.js file, when i do the following:
import Slider from "react-slick";
How does webpack know where to pick slider from ? will it at all look for some clue or definition inside node_modules/react-slick/package.json at all ?
Edit :- so here is the package.json file for webpack, when i import Slider from 'react-slick' , does it resolve to dist or lib ? and which file does it pick then and why ?
Well, the simple walkthrough of it will be as below:
Simple Walkthrough
If you carefully look at the node_modules/react-slick/package.json there is a property named main. Something like this:
{
"name": "react-slick",
"main": "index.js"
}
It will tell the Webpack which file is the entry file of the whole package (It's usually referred to index.js). All the necessary exports for the package lies in this file, so Webpack will only look for those exports and will import what you looking for. In this particular case, there should be a default export for the Slider that you using right now. So the index.js is probably something like this:
// index.js
var slider = require('./lib/slider'); // Usually all the main modules are lies under lib folder.
// other imports ...
module.exports = slider;
Difference between lib and dist
Usually, the dist folder is for shipping a UMD that a user can use if they aren't using package management. The lib folder is what package.json, main property points to, and users that install your package using npm will consume that directly. The only use of the lib as opposed to src is to transform your source using babel and Webpack to be more generally compatible since most build processes don't run babel transforms on packages in node_modules.
Webpack uses aliases to target node_modules using a shorthand.
Example #1:
import 'xyz'
/abc/node_modules/xyz/index.js
Example #2:
import 'xyz/file.js'
/abc/node_modules/xyz/file.js
Once it targets the correct folder in node_modules, it follows the rules written in the package itself (manifest, package.json)
You can also define your own aliases as such:
webpack.config.js
const path = require('path');
module.exports = {
//...
resolve: {
alias: {
xyz$: path.resolve(__dirname, 'path/to/file.js')
}
}
};
And then can be used as import xyz from $xyz

Webpack can't find import needed for Typescript type resolution. How to fix this?

My project uses typescript and built with webpack.
I have a typings file that comes from a third part lib located under node_modules/#types/libname/custom.d.ts. That file has a namespace declaration with a few types in it:
declare namespace MyNamespace {
export type A = ...;
}
Then in order to be able to use that type in my typescript code like so:
const x: MyNamespace.A;
...I need to add the import declaration as follows somewhere in the app:
import 'libname'
Which tsc resolves correctly to node_modules/#types/libname/custom.d.ts so everything works if I compile with tsc.
However webpack then can't build. It can't understand this import:
ERROR in ./Index.tsx
Module not found: Error: Can't resolve 'libname' in 'C:\<path_to_index_file>'
# ./Index.tsx 44:0-32
I tried to add an alias in my webpack.config like so:
resolve: {
alias: Object.assign({
'libname$': path.resolve(__dirname, 'node_modules/#types/libname/custom.d.ts'),
}
},
But then it fails because it can't understand that file's syntax and asks if I'm missing a loader.
How can I fix this so that webpack will understand this typings import statement?
I'm on webpack version 4.41.6
Thanks!
You should use the null-loader for this import so webpack will ignore it.

Error: Can't resolve lodash-mixins in typescript angular2

I'm trying to add custom functionality to extend lodash (note lodash
is npm'ed in). But I keep getting a resolve error.
I've added a new file called lodash-mixins.js to my test project scripts folder e.g: project/frontend/src/web/Scripts/
var _ = require('lodash');
_.mixin({
mixinLoaded function () { console.log("lodash mixins are loaded");}
});
module.exports = _;
Overview Folder Structure (simplified)
project/frontend/src/web
...frontend.web.csproj
...angular-cli.json
project/frontend/src/web/Scripts/
...lodash-mixins.js
project/frontend/src/web/app/
...app.module.ts
I've manually added my "lodash-mixins.js" to the "angular-cli.json"
"apps": [
{
"scripts": [
"../node_modules/jquery/dist/jquery.min.js",
etc
"../node_modules/lodash/lodash.min.js",
"../Scripts/lodash-mixins.js", // <<<<< not picking up
"../Scripts/global-error-handler.js",
],
Test by changing existing reference in one of my test.service.ts
from:
"import * as _ from 'lodash';"
to:
"import * as _ from 'lodash-mixins';"
I've rebuilt my c# solution for good measure.
Run in CLI: $ng build --watch
ERROR in project/frontend/src/web/app/test/services/test.service.ts
Module not found: Error: Can't resolve 'lodash-mixins
Any ideas?
You're confusing two different things here.
1) The "scripts" config for Angular CLI tells WebPack to include those JavaScrip files in the output bundle. It doesn't add those as importable modules. They get loaded as if you added <script src="..."> tags to your HTML file (not exactly accurate, but gives the idea).
2) When you import using TypeScript it searches for the module. The reason it's giving the error is because the file isn't in one of the search paths. Had it actually found the file. It would have loaded it twice. Since you've already added it to the "scripts" config option.
JQuery, Lodash, etc.. etc.. can be loaded using modules or just plain global variables. When you add it to the "scripts" config, then I think this tells WebPack to load it in the global browser space.
When you use "import _ from 'lodash'" in TypeScript. You're actually resolving to the "#types/lodash" module which people often install so that TypeScript knows about the interface for lodash. When WebPack bundles everything for the browser it swaps out the #types for the real reference to the lodash instance.
So you have a couple of options.
1) Continue with what you've done. Add TypeScript definition file in the import path for your new module named "lodash-mixin". That module just defines the new interface with the new methods. The import will find that file and use it to compile the TypeScript, but the WebPack bundle will load your JS file in it's place.
2) Remove your "lodash-mixin" from the "scripts" config, then import using a relative path import _ from '../Scripts/lodash-mixins'. This is what I usually do. Note: You might have to add the file extension ".js"
3) Add your "Scripts" folder to your tsconfig.json as one of the type roots. This allows you to just use import _ from 'lodash-mixins'.
4) There is a way (and I forget exactly how), but you can tell TypeScript to alias lodash to your lodash-mixin so that all imports use that type instead. I don't recommend this approach.

Is there a correct way to use a JavaScript module in a TypeScript project?

I really hope this isn't an opinion question, and I don't think it is...
Is there a correct way to include a JS module in a TS project? If I don't do one of the 2 steps below, my IDE (linter, wahtever) gives me TS2307: Cannot find module when I use the line import * as myPackage from 'myPackage'.
The steps I use are
npm i thePackage --save
typings i -g thePackage --save // assuming it has a typings
If the module doesn't have a typings, all you do is
declare let myPackage:any
Is that all you have to do in order to use an external package in a TS project? Or am I missing a vital step?
I know I could create a .d.ts file, but for now, I'd like to get the hang of TS without spending all my time writing those files.
I've also been reading about DefinitelyTyped and #types/myPackage, but I don't know much about it...
If the package has declaration files
In TypeScript 2.0+, for a package the-package
npm install --save #types/the-package
If the package doesn't have declaration files
If the package doesn't have declaration files for it, create a file named externals.d.ts with the following:
// This file should contain no top-level imports or exports.
declare module "the-package";
Note: If there's more than one thing you can import from the-package, you can use a wildcard as well:
declare module "the-package/*";
At this point, you can do basically whatever you want with the package when you import it - it comes in as any.
Strongly typing the package
If you want to add some type safety, we'll start defining the module in its own file in a folder called externals.
So we'll write out ./externals/the-package/index.d.ts.
export function foo(): void;
export function bar(x: string): number;
And now add the following to your tsconfig.json's compiler options.
{
"compilerOptions": {
"baseUrl": "./",
"paths": {
"*": ["externals/*"]
}
}
}
Now any modules should be looked up in externals first before being looked up in #types & node_modules.
Note: This assumes externals is in the same directory as tsconfig.json. Adjust appropriately.
Once your module is fully written out, you can send a PR for this package to DefinitelyTyped if you'd like to help others out.

Categories