Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

module.name_mapper not working #1068

Open
alebiavati opened this issue Nov 10, 2015 · 34 comments
Open

module.name_mapper not working #1068

alebiavati opened this issue Nov 10, 2015 · 34 comments
Labels

Comments

@alebiavati
Copy link

I can't get module.name_mapper to work on the example in the documentation:
http://flowtype.org/docs/advanced-configuration.html#options

Flow version: 0.18.1

Folder structure:

.
├── interfaces/
│   └── ImageStub.js
├── .flowconfig
├── app.js
└── foo.jpg

Contents of .flowconfig:

[libs]
.*/interfaces/*

[options]
module.name_mapper='^image![a-zA-Z0-9$_]+$'->'ImageStub'

Contents of ImageStub.js:

declare module ImageStub {
  declare var exports: { [key: string]: string };
}

Contents of app.js:

/* @flow */

require('image!foo.jpg');

Here is the output when doing flow check:

app.js:3
  3: require('image!foo.jpg');
     ^^^^^^^^^^^^^^^^^^^^^^^^ image!foo.jpg. Required module not found

Found 1 error

To make sure that the regex pattern wasn't the problem I tried to dumb it down and just do the following:

Contents of .flowconfig:

[libs]
.*/interfaces/*

[options]
module.name_mapper='image'->'ImageStub'

Contents of ImageStub.js:

declare module ImageStub {
  declare var exports: { [key: string]: string };
}

Contents of app.js:

/* @flow */

require('image');

and again, this is the output of flow check:

app.js:3
  3: require('image');
     ^^^^^^^^^^^^^^^^ image. Required module not found

Found 1 error

Any ideas?

@alebiavati alebiavati changed the title module.name_mapper not working module.name_mapper not working Nov 10, 2015
@samwgoldman
Copy link
Member

This feature is covered by automated tests, which are still passing, so it's unlikely that the feature is wholesale not working.

One thing that is suspicious about the code you've pasted here is the [libs] section. You have this configured as a regex (.*/interfaces/*), but I don't think that's correct. Can you try with this:

[libs]
interfaces/

@alebiavati
Copy link
Author

I was surprised too!
Anyway, I just tried with interfaces/ and it doesn't work.

What else can I provide to debug this? maybe I should try cloning the source and running the unit tests on my machine?

@alebiavati
Copy link
Author

Ok, so I checked out the project and built it on my machine. All tests pass, but when I looked at the test sources, there are no tests for module.name_mapper used to map images or css imports.

One of the tests that gets run is for the <PROJECT_ROOT> tag:

module.name_mapper='^\(.*\)' -> '<PROJECT_ROOT>/src/\1'

I tried copying the code for that test to run it within my test app and sure enough flow finds the module in the src/ directory, but it still shows the error for the image.

I also verified that interfaces/ are working by including another test module interface in app.js.

Here is the new source of my test app:

app.js:

/* @flow */

import 'testmodule';
import 'TestModuleInterface';
import 'image!foo.jpg';

.flowconfig:

[libs]
interfaces/

[options]
module.name_mapper='^image![a-zA-Z0-9$_]+$' -> 'ImageStub'
module.name_mapper='^\(.*\)' -> '<PROJECT_ROOT>/src/\1'

src/testmodule.js:

// @flow

export const test = 42;

interfaces/ImageStub.js:

declare module ImageStub {
  declare var exports: { [key: string]: string };
}

interfaces/TestModuleInterface.js:

declare module TestModuleInterface {
  declare var exports: { [key: string]: string };
}

And here is the output of flow check:

app.js:5
  5: import 'image!foo.jpg';
            ^^^^^^^^^^^^^^^ image!foo.jpg. Required module not found

Found 1 error

@jeffmo
Copy link
Contributor

jeffmo commented Nov 10, 2015

Your regexp doesn't include '.' in the character class

@alebiavati
Copy link
Author

Tried fixing that too, it still didn't work:

module.name_mapper='^image!.*' -> 'ImageStub'

BUT, it worked when I added this line:

module.system=haste

Still, I think somebody should update the documentation because there are a few things here:

  1. the regex pattern on the documentation is wrong.
  2. the example provided for importing foo.jpg doesn't work unless module.system=haste is set.

PS: another way to do this without using module.system=haste is to install the empty npm package and then use the following in your .flowconfig:

module.name_mapper='^image!.*' -> 'empty/object'

@alebiavati
Copy link
Author

@samwgoldman
Copy link
Member

Hypothesis: the name resolution works for modules found under node_modules, but not for lib files.

@alebiavati
Copy link
Author

It might be that.
It works using the haste module system, but I'm not sure I understand the difference between node and haste. Does node mean that flow resolves only names that are in the node_modules folder?

@girvo
Copy link

girvo commented Jan 14, 2016

I'm still running into this; I'm attempting to map this: '.*\.scss' -> 'empty/object' but no matter what I try it simply doesn't seem to want to work. Any ideas?

[ignore]

[include]

[libs]

[options]
module.name_mapper='.*\.scss' -> 'empty/object'

This is with Flow v0.20.1

@girvo
Copy link

girvo commented Jan 14, 2016

Ah, I worked it out. Turns out, it was working, but because npm install empty had been executed in the incorrect directory, it didn't exist. However: the error message was that the scss file didn't exist, not the rewritten module!

@simnalamburt
Copy link

+1 For this. I have same problem.

@MoOx
Copy link

MoOx commented May 17, 2016

I am also having issue with local png file

[ignore]
.*/node_modules/.*
.*/lib/.*
.*/.nyc_output/.*
.*/__tests__/.*

[libs]
node_modules/flow-interfaces/interfaces
node_modules/iflow-material-ui/index.js.flow
node_modules/iflow-color/index.js.flow
flow-interfaces

[options]
esproposal.class_instance_fields=enable
esproposal.class_static_fields=enable

module.name_mapper='.*\.(svg|png|jpg|gif)$' -> 'string'

and this code

// @flow 
import logoSVG from "./logo.png"

.png are string, per webpack config (url-loader)

@MoOx
Copy link

MoOx commented May 17, 2016

Related: #1801 (comment)

@MoOx
Copy link

MoOx commented May 18, 2016

@jeffmo give some pretty good explanation here #1801 (comment)

tl;dr: module.name_mapper allows you to make a replacement, so the name you map to need to be a real node module or an real file. The file needs to be a JS file, not a flow declaration.

So this issue is just a bad usage.
I have created a gist and an answer on stackoverflow

I guess this issue can be closed now that there is enough material for people to understand this.

@casertap
Copy link

casertap commented Aug 7, 2016

Still not working in my case.

[version]
0.30.0

[ignore]
.*/bin/.*
.*/build/.*
.*/config/.*
.*/coverage/.*
.*/node_modules/.*
.*/src/styles/.*

[include]
./node_modules/

[libs]
./node_modules/flow-interfaces/interfaces/react-redux.d.js
./node_modules/flow-interfaces/interfaces/CSSModule.d.js
./flow-typed/npm/
./interfaces/

[options]
module.system=haste
esproposal.class_static_fields=enable
esproposal.class_instance_fields=enable
esproposal.decorators=ignore

module.name_mapper.extension='scss' -> 'CSSModule'
module.name_mapper='^inject!(.*)' ->  'empty/object'
module.name_mapper='.*\.\(jpg\|jpeg\|gif\|svg\|png\)$' -> 'Image'
module.name_mapper='^components$' -> '<PROJECT_ROOT>/src/components'
module.name_mapper='^containers$' -> '<PROJECT_ROOT>/src/containers'
module.name_mapper='^redux\/\(.*\)$' -> '<PROJECT_ROOT>/src/redux/\1'
module.name_mapper='^routes$' -> '<PROJECT_ROOT>/src/routes'
module.name_mapper='^utils\/\(.*\)$' -> '<PROJECT_ROOT>/src/utils/\1'
module.name_mapper='^interfaces\/\(.*\)$' -> '<PROJECT_ROOT>/src/interfaces/\1'
module.name_mapper='^tests\/\(.*\)$' -> '<PROJECT_ROOT>/src/tests/\1'

munge_underscores=true

suppress_type=$FlowIssue
suppress_type=$FlowFixMe
suppress_type=$FixMe

suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(1[0-6]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*www[a-z,_]*\\)?)\\)
suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(1[0-6]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*www[a-z,_]*\\)?)\\)? #[0-9]+
suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy

I get

src/tests/unit/redux/modules/search-spec.js:371
[0] 371:       const module = require('inject!redux/modules/search')({
[0]                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ inject!redux/modules/search. Required module not found
[0]
[0] src/tests/unit/redux/modules/suggestions-spec.js:132
[0] 132:       const module = require('inject!redux/modules/suggestions')({
[0]                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ inject!redux/modules/suggestions. Required module not found

@maksimsemenov
Copy link

I have the same issue:

[ignore]
<PROJECT_ROOT>/node_modules/fbjs/.*

[options]
module.name_mapper='^components\/(.*)$' -> '<PROJECT_ROOT>/src/components/\1'
module.name_mapper='^constants\/(.*)$' -> '<PROJECT_ROOT>/src/constants/\1'
module.name_mapper='^actions\/(.*)$' -> '<PROJECT_ROOT>/src/actions/\1'
module.name_mapper='^reducers\/(.*)$' -> '<PROJECT_ROOT>/src/reducers/\1'
module.name_mapper='^types\/(.*)$' -> '<PROJECT_ROOT>/src/types/\1'
import type { DataFieldT } from 'types/DataFieldT'

import * as fieldTypes from 'constants/fieldTypes'
import * as relTypes from 'constants/relationshipTypes'
import * as DFN from 'constants/dataFieldNames'

I get:

types/DataFieldT Required module not found
constants/fieldTypes Required module not found
constants/relationshipTypes Required module not found
constants/dataFieldNames Required module not found

Any suggestions?

@averyvery
Copy link

Seeing something similar here, after just installing Flow today and starting to play around with it. I'm trying to use name_mapper to resolve some imports that are usually handled by webpack's modulesDirectories.

Project structure:

/apps
- /shared
- /roomDashboard

.flowconfig:

.*/node_modules/.*

[options]
module.name_mapper='^shared\/(.*)$' -> '<PROJECT_ROOT>/apps/shared/\1'

Error:

  2: import wrapWithPolyfills from 'shared/lib/wrapWithPolyfills';
                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ shared/lib/wrapWithPolyfills. Required module not found

Is this the same issue as the ones above? Any ideas?

@averyvery
Copy link

I was able to get around my issue with...

module.system.node.resolve_dirname=node_modules
module.system.node.resolve_dirname=apps

...which mimics my modulesDirectories setup. Now Flow is running fine!

@prewk
Copy link

prewk commented Jan 21, 2017

This kind of config still doesn't work for me: module.name_mapper='^components\/(.*)$' -> '<PROJECT_ROOT>/components/\1'

I'm not sure how to do it with resolve_dirname instead, module.system.node.resolve_dirname=<PROJECT_ROOT> doesn't work (and would resolve way too much stuff anyway)

I've resorted to creating symbolic links inside of node_modules to make Flow and Mocha work, but they are in the way most of the time so I'd rather not have them.

@Freezystem
Copy link

Using flowtype 0.39.0 I encountered a similar problem with lodash imports on a basic create-react-app project.

I'm doing:

import isEmpty from 'lodash/isEmpty';

and I get this error: [flow] lodash/isEmpty (Required module not found) so I tried:

module.name_mapper='^lodash/.+$' -> 'lodash'
(* and *)
module.name_mapper='^lodash/\(.+\)$' -> '<PROJECT_ROOT>/node_modules/lodash/\1'

but I always get the same error. Am I doing it wrong ?

As I can't figured out what was wrong I just fallback to:

import { isEmpty } from 'lodash';

@nodkz
Copy link
Contributor

nodkz commented May 5, 2017

My working solution for module resolving in 0.45:

[options]
- module.name_mapper='^app\/(.*)$' -> '<PROJECT_ROOT>/app/\1' # does not work
+ module.name_mapper='^app\/\(.*\)$' -> '<PROJECT_ROOT>/app/\1' # works as expected
module.name_mapper='^i18n\/\(.*\)$' -> '<PROJECT_ROOT>/i18n/\1'
module.name_mapper='^lib\/\(.*\)$' -> '<PROJECT_ROOT>/lib/\1'
module.name_mapper='^mailer\/\(.*\)$' -> '<PROJECT_ROOT>/mailer/\1'
module.name_mapper='^schema\/\(.*\)$' -> '<PROJECT_ROOT>/schema/\1'
module.name_mapper='^mongoose-elasticsearch-xp\(.*\)$' -> '<PROJECT_ROOT>/lib/mongoose-elasticsearch-xp\1'

Be careful with escaping characters in regexp

Write this comment cause module.name_mapper works in some cases. And further googlers should not give up playing with this option.

@sarkistlt
Copy link

sarkistlt commented May 14, 2017

the same issue works fine with module.system=haste it was reported almost 2 year ago, when will this be fixed?

@alex35mil
Copy link

One more case:

// module
import coverImage from './images/cover.jpg?preset=cover';

// .flowconfig
module.name_mapper='^\(.*\)\.\(png\|jpe?g\)\?preset=cover$' -> 'CoverImageModule'

// app/declarations/CoverImageModule.js.flow
declare module CoverImageModule {
  declare var exports: {|
    srcset: string,
    fallback: string,
  |};
}

Works w/ module.system=haste, doesn't work w/ module.system=node.

Repo to reproduce: https://github.com/alexfedoseev/blog

@nicotroia
Copy link

module.system=haste worked for me

@mikeLspohn
Copy link

@Freezystem I'm having that same issue. Did you get is solved with resorting to importing just lodash?

@Freezystem
Copy link

I used the fallback method by importing lodash directly but it was on an old project I no longer maintain, maybe the bug is fixed now.

@guiguan
Copy link

guiguan commented Sep 11, 2017

Same here. node doesn't work, but haste works. Can someone please fix this?

@mikeaustin
Copy link

I can't seem to get name_mapper working either. I use webpack resolve.alias instead of using symbolic links (might have to use them?) to refer to a parent project.

module.name_mapper='^react-native$' -> '<PROJECT_ROOT>/../react-evitan/src/components/index.js'

I tried multiple ways with exact js, absolute paths, etc. If I substitute a known module, it does work. So to MoOx's point, is looking for modules only? Using ../ in an import works fine, so I would assume name_mapper would also.

@jamietre
Copy link

@mikeaustin coincidentally, I am trying to do exactly the same thing. I don't think you can use .. in the replacement string to traverse above <PROJECT_ROOT>, since in my experimenting the regex I'm using works fine with a different target that is within the project root. I'm not sure how you would resolve a folder above the project root other than with a symlink.

@mikeaustin
Copy link

@jamietre Interesting. I guess I could use symlinks, but I don't think they work on Windows? Also, using webpack aliases allows all our imported components to see the alias. With symlinks, I'd need to add one in each module's node_modules.

@STRML
Copy link
Contributor

STRML commented Feb 7, 2018

@jamietre Ensure ../folder_name is in your [include].

@pronebird
Copy link

I can't get this to work even with basic

module.name_mapper='^some-module$' -> '<PROJECT_ROOT>/empty.js'`

Flow 0.50

@MoOx
Copy link

MoOx commented Feb 9, 2018

Try module.name_mapper='^some-module\/\(.*\)$' -> '<PROJECT_ROOT>/empty.js'

@CaelanStewart
Copy link

As already mentioned by many, adding a separate name_mapper for each and every directory under src is tedious and prone to error.

It is not a good solution at all.

Is there no simple way whatsoever for us to be able to specify a ROOT directory where our code is and leave it at that?

This is clearly an ongoing problem and nothing seems to have been done about.

I'm having no luck with resolve_dirname.

Tried every permutation in this thread, haste or node.

There are just so many damn variables, and so many explanations that have too many knowledge dependencies to be able to understand. Nobody seems to have given a clear answer that overcomes to the burden of knowledge.

Please just add a mechanism where I can say: this is my root directory, just use this damn directory.

Considering it is build by Facebook, one should think there would be ample time and resources to improve it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests