What is the real meaning of transformIgnorePatterns in Jest configuration? - javascript

In Jest we can configure transformIgnorePatterns to ignore files to be transpiled, which defaults to "/node_modules/". However, if a dependency is not translated when it is published, such as /node_modules/atest, according to the instructions on the official website, it should be configured to transformIgnorePatterns, which feels contrary to the "ignored" meaning of this configuration.
I want to know which files are translated and which files are ignored and not translated by pressing the configuration file below.
module.exports = {
// ...
transformIgnorePatterns: ['/node_modules/atest']
// ...
}
Possible answer 1: Dependencies in node_modules except atest are transpiled
Possible answer 2: Only atest in node_modules is transpiled, the rest of the dependencies are not transpiled

From the doc, the transformIgnorePatterns option has default value: ["/node_modules/", "\\.pnp\\.[^\\\/]+$"]
It means:
If the file path matches any of the patterns, it will not be transformed.
So, the packages inside the node_modules directory will NOT be transformed by default.
Now, you have a package named atest which is not a pre-compiled package, you need to transform it using babel and don't transform other packages inside node_modules. So the configuration should be:
{
"transformIgnorePatterns": ["/node_modules/(?!(atest)/)"]
}
Test paths:
/node_modules/atest/index.js
/node_modules/react/index.js
/node_modules/lodash/index.js
/node_modules/dayjs/index.js
The /node_modules/atest will be excluded from transformIgnorePatterns configuration which means it will be transformed.
See the regexp test

Related

Grunt and ES6 modules in node - incompatible without the use of .mjs?

So, I'm dabbling a bit with Typescript and Grunt at the moment to see if it's worth it for me. The thing is: Typescript does not compile to *.mjs files but only regular *.js files. Node does support ES6 Modules but only if you either mark them as '*.jsm' files or by setting "type": "module". Setting this top-level field in package.json however has global scope for any *.js file in the same directory and any following ones.
This breaks the Gruntfile.js file as it seems since it uses CommonJS modules, see my very basic Gruntfile as example:
module.exports = function (grunt) {
grunt.initConfig({
ts: {
default: {tsconfig: "./tsconfig.json"}
}
})
grunt.loadNpmTasks("grunt-ts");
grunt.registerTask("default", ["ts"]);
}
Without expecting much success I naively changed the export syntax from module.exports = to export default which expectedly did no work since it didn't make much sense.
Questions
Is there any option to use Grunt with ES6 modules enabled in node?
Is there a proper way to tell TypeScript to compile to *.mjs files?
If you set "type": "module" in your package.json, you need to rename Gruntfile.js to Gruntfile.cjs, and run it with grunt --gruntfile Gruntfile.cjs.
The suggested approach with Babel running before Grunt makes Grunt a bit redundant. Since TypeScript does not yet support exporting ES6 modules to *.mjs files (and you have to use the *.mjs suffix in your import when node should still be running with its CommonJS system) and will probably never fully (see Design Meeting Notes 11/22/2019) I have to conclude that ES6 modules still have serious implications and issues. Changing the file extension is not enough since the extension-less imports fail with node. You'd need to go through every compiled file and change the import to specifically load *.mjs files.
However, the TypeScript Compiler can be set up in a way that it does understand ES6 module syntax and to compile to CommonJS (see TS handbook).
{
"compilerOptions": {
"module": "CommonJS",
// [...]
},
}
This way the TypeScript code be written with ES6 module syntax and the output can be CommonJS compatible without braking other code. As a bonus you can skip the Babel approach and grunt can run TS compiler.
You can using babel-node to compile first. Which will resolve ES6 export and import problem.
npm install --save-dev #babel/core #babel/node
npx babel-node server.js

Configure Babel to include sibling modules referenced by alias into compilation

I have the following file structure:
application1
|pacakge.json
|src
||file1.ts
widget-lib
|package.json
|src
||file2.ts
||index.ts
.\widget-lib\src\index.ts bundles and reexports everything in widget-lib package.
export * from '.\file2'
.\application1\src\file1.ts and other files refence widget-lib by alias
import { foo } from 'widget-lib';
I'm compiling .\application1\src\ with Babel into .\application1\build-test\, how do I instruct Babel to also include widget-lib into this particular compilation? My goal is to produce a folder with all JS files needed to debug unit tests in modern node with esm package - just strip down TS types and put resulting JS files into proper place, like this:
application1
|build-test
||application1
|||src
||||file1.js
||widget-lib
|||src
||||index.js
||||file2.js
I'm using https://github.com/tleunen/babel-plugin-module-resolver to rewrite alias paths like 'widget-lib' to expected relative paths, I just need to instruct babel to also include the actual files from widget-lib into .\build-test\widget-lib folder. I tried passing both .\application1\src and .\widget-lib\src together to Babel, but than it outputs content of both .\src folders into one.
I ended up running several babel process in parallel, spawning them with a node script as described here Execute a command line binary with Node.js and using the script to analyze their output and emit additional information.

Does ts-node support '#' style import? If so, how to set it up?

I'm creating a command-line script, using classes from the main express app.
Script resides in the folder:
bin/utils/
├── sync-buyers.ts
└── tsconfig.json
The main express app is in /app use uses import '#/foo/bar/thing.
This is set up in the tsconfig.json of the main app, as follows:
"paths": {
"#/*": ["*"],
"*": [
"node_modules/*",
"app/typings/*"
]
}
},
"include": ["app/**/*", "test/**/*"],
"exclude": ["app/**/*.test.ts", "/__tests__/", "/__mocks__/", "/__snapshots__/", "app/**/__mocks__/"],
"files": ["typings/global.d.ts"]
Script Execution
I'm testing to see if I can import from the main app, so I created a sayHello() function.
#!/usr/bin/env ts-node
/* tslint:disable */
import { sayHello } from '../../app/services/v2/oapp';
sayHello();
When I run it:
TSError: ⨯ Unable to compile TypeScript:
../../app/services/v2/oapp.ts(9,19): error TS2307: Cannot find module
'#/helpers/fetch'.
../../app/services/v2/oapp.ts(10,31): error TS2307: Cannot find module
'#/services/v2/buyer'.
../../app/services/v2/oapp.ts(11,51): error TS2307: Cannot find module
'#/http/HttpHeader'.
Summary:
Does ts-node support '#' style of import? If so, how do I set it up?
So the TypeScript paths configuration only applies to TypeScript's type resolution and checking, meaning that it will allow TypeScript to understand those imports for the purposes of type-checking only, but the code it generates won't automatically rewrite those imports to the correct locations.
There's two common approaches for solving this:
Update the Node resolver to understand the TypeScript paths config. The generated files will still refer to those paths by their #-name.
Most commonly, the tsconfig-paths module is used for this. You can require that module from the node command directly:
node -r tsconfig-paths/register main.js
Rewrite the generated files so that the #-names get replaced with the "real" local relative path locations.
There's a standalone module for this, tspath - you simply run tspath after compiling your TypeScript, and it updates the generated files with the correct paths.
If you're using Webpack, you can also use tsconfig-paths-webpack-plugin, which will take care of configuring Webpack's resolver to correctly locate those #-name paths.
And finally if you're using Babel, you might be interested in babel-plugin-module-resolver which does a similar thing for the Babel toolchain, however the downside here is it doesn't read the paths config from tsconfig.json, so you essentially have to duplicate your paths config in the alias config of this plugin.
Personally I'd recommend tsconfig-paths if this is a Node script or server that's compiled with tsc directly and tsconfig-paths-webpack-plugin if this is a frontend Webpack build.

How to make Webpack use project's "node_modules" in js scripts located outside the project folder?

I have Node.js project and the following structure of folders:
lib
awesome-formatter.js
FrontEndApp
prettify.js
node_modules
awesome-parser
BackEndApp
...
I use awesome-parser module and awesome-formatter.js library in prettify.js script like this:
require('awesome-parser')
require('../lib/awesome-formatter.js')
awesome-formatter.js, in turns, should use awesome-parser too:
require('awesome-parser')
My FrontEndApp has been configured to use Webpack, and I'm trying to run it in dev mode using npm run dev command. However, I got the following error:
ERROR Failed to compile with 1 errors
These dependencies were not found:
* awesome-parser in /home/user/dev/lib/awesome-formatter.js
I don't want to move awesome-formatter.js inside the FrontEndApp because I also use it in BackEndApp project (and probably in some other projects) and I don't want to create separate "node_modules" in "lib" for it just not to duplicate installed modules on disk.
So, my question is, how to make Webpack use project's "node_modules" in js scripts located outside the project folder?
P.S. Of course there are workarounds like symlinks or making a full-featured module (with package.json etc.) from lib/awesome-fromatter and installing it into FrontEndApp/node_modules, but is there a direct way to solve this problem?
I've found a solution: resolve.modules sould be added to Webpack configuration file.
module.exports = {
...
resolve: {
...
modules: [
'node_modules',
resolve('node_modules')
]
},
...
}
This means that Webpack is searching modules in 'node_modules' as a relative subfolder (and it's the usual behavior), and at the absolute path to the project's 'node_modules' as well: resolve('node_modules'), so that scripts in folders outside the project (like lib in my structure) can find and use it.

Compiling typescript path aliases to relative paths for NPM publishing?

I have a typescript project that uses paths for imports. For example:
"paths": {
"#example/*": ["./src/*"],
}
Thus the project can import files directly from using statement like:
import { foo } from "#example/boo/foo";
For publishing to NPM I have I'm compiling the typescript files and then copying the result to a dist folder. Thus all the *.d.ts and corresponding *.js files are in the dist folder. I also copy package.json to the dist folder.
I now test this by generation a new typescript project and then run npm i -S ../example/dist, in order to install the project and attempt to run some of the compiled typescript code.
However the relative imports no longer work. For example if boo.ts depends on foo.ts it will say that it can't resolve foo.ts.
When I look at the *.d.ts files they contain the same paths that were used the source code before it was compiled. Is it possible to turn these into relative paths?
Update
I looks as if generating relative paths for Node is something Typescript does not perform automatically. If you would like this feature, as I would, please provide feedback on this bug report.
As a brief follow-up to arhnee's suggestion, it seems that as of Aug 2020, Microsoft still refuses to implement custom transformers for whatever reason, so these modules remain relevant.
So to future readers, here's how you can actually compile TS path aliases to relative paths. ttypescript is merely a transformer framework that requires a "path transformer" in order to actually convert the TS path aliases. Thus you will need to install both ttypescript and typescript-transform-paths.
npm i --save ttypescript typescript-transform-paths
Then, it's easy as just specifying usage by adding the following property to the compilerOptions object in tsconfig.json:
"plugins": [
{ "transform": "typescript-transform-paths" }
]
And finally, run ttsc instead of tsc.
There is a project called ttypescript that you can use for this. If you use it with the module typescript-transform-paths I beleive it will acheive what you want.

Categories

Resources