Skip to content

Commit

Permalink
Config option to change the default "node_modules" dirname
Browse files Browse the repository at this point in the history
Summary: tldr: [Webpack has something similar to this option](https://webpack.github.io/docs/configuration.html#resolve-modulesdirectories) and some users find it useful.

This is a feature request from here: #915

Reviewed By: @gabelevi

Differential Revision: D2532941

fb-gh-sync-id: a7ae5f278345849b344863a68ecbc2baabc026d6
  • Loading branch information
jeffmo authored and facebook-github-bot-8 committed Oct 13, 2015
1 parent 0346e71 commit e1e301c
Show file tree
Hide file tree
Showing 12 changed files with 78 additions and 24 deletions.
14 changes: 14 additions & 0 deletions src/common/flowConfig.ml
Expand Up @@ -43,6 +43,7 @@ module Opts = struct
experimental_decorators: experimental_feature_mode;
moduleSystem: moduleSystem;
module_name_mappers: (Str.regexp * string) list;
node_resolver_dirnames: string list;
munge_underscores: bool;
module_file_exts: string list;
suppress_comments: Str.regexp list;
Expand Down Expand Up @@ -100,6 +101,7 @@ module Opts = struct
experimental_decorators = EXPERIMENTAL_WARN;
moduleSystem = Node;
module_name_mappers = [];
node_resolver_dirnames = ["node_modules"];
munge_underscores = false;
module_file_exts = [".js"; ".jsx";];
suppress_comments = [];
Expand Down Expand Up @@ -530,6 +532,18 @@ let parse_options config lines = Opts.(
});
})

|> Opts.define_opt "module.system.node.resolve_dirname" Opts.({
_initializer = INIT_FN (fun opts -> {
opts with node_resolver_dirnames = [];
});
flags = [ALLOW_DUPLICATE];
optparser = optparse_string;
setter = (fun opts v ->
let node_resolver_dirnames = v :: opts.node_resolver_dirnames in
{opts with node_resolver_dirnames;}
);
})

|> Opts.define_opt "munge_underscores" Opts.({
_initializer = USE_DEFAULT;
flags = [];
Expand Down
1 change: 1 addition & 0 deletions src/common/flowConfig.mli
Expand Up @@ -18,6 +18,7 @@ module Opts : sig
experimental_decorators: experimental_feature_mode;
moduleSystem: moduleSystem;
module_name_mappers: (Str.regexp * string) list;
node_resolver_dirnames: string list;
munge_underscores: bool;
module_file_exts: string list;
suppress_comments: Str.regexp list;
Expand Down
47 changes: 23 additions & 24 deletions src/typing/module_js.ml
Expand Up @@ -309,31 +309,30 @@ module Node = struct
let opts = get_config_options () in
if Files_js.is_flow_file path
then path_if_exists path
else
seq
(fun () ->
seqf
(fun ext -> path_if_exists (path ^ ext))
opts.FlowConfig.Opts.module_file_exts
)
(fun () ->
seq
(fun () ->
let package = Filename.concat path "package.json" in
parse_main package)
(fun () ->
let path = Filename.concat path "index.js" in
path_if_exists path
)
)
else seq
(fun () -> seqf
(fun ext -> path_if_exists (path ^ ext))
opts.FlowConfig.Opts.module_file_exts
)
(fun () -> seq
(fun () -> parse_main (Filename.concat path "package.json"))
(fun () -> path_if_exists (Filename.concat path "index.js"))
)

let rec node_module dir r = seq
(fun () -> resolve_relative dir (spf "node_modules%s%s" Filename.dir_sep r))
(fun () ->
let parent_dir = Filename.dirname dir in
if dir = parent_dir then None
else node_module (Filename.dirname dir) r
)
let rec node_module dir r =
let opts = get_config_options () in
seq
(fun () -> seqf
(resolve_relative dir)
(opts.FlowConfig.Opts.node_resolver_dirnames |> List.map (fun dirname ->
spf "%s%s%s" dirname Filename.dir_sep r
))
)
(fun () ->
let parent_dir = Filename.dirname dir in
if dir = parent_dir then None
else node_module (Filename.dirname dir) r
)

let relative r =
Str.string_match Files_js.dir_sep r 0
Expand Down
3 changes: 3 additions & 0 deletions tests/config_module_system_node_resolve_dirname/.flowconfig
@@ -0,0 +1,3 @@
[options]
module.system.node.resolve_dirname=node_modules
module.system.node.resolve_dirname=custom_resolve_dir
@@ -0,0 +1,10 @@

subdir/sublevel.js:5:2,5: string literal `subdir/custom_resolve_dir/testproj2`
Expected string literal `node_modules/testproj2`, got `subdir/custom_resolve_dir/testproj2` instead
subdir/sublevel.js:5:8,31: string literal `node_modules/testproj2`

toplevel.js:6:2,5: string literal `node_modules/testproj`
Expected string literal `custom_resolve_dir/testproj`, got `node_modules/testproj` instead
toplevel.js:6:8,36: string literal `custom_resolve_dir/testproj`

Found 2 errors
@@ -0,0 +1,3 @@
// @flow

export var name: "otherdir/testproj" = "otherdir/testproj";
@@ -0,0 +1,3 @@
// @flow

export var name: "otherdir/testproj2" = "otherdir/testproj2";

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

@@ -0,0 +1,3 @@
// @flow

export var name: "subdir/custom_resolve_dir/testproj2" = "subdir/custom_resolve_dir/testproj2";
@@ -0,0 +1,6 @@
// @flow

import {name} from "testproj2";

(name: "node_modules/testproj2"); // Error: Resolve from sibling 'custom_resolve_dir' first!
(name: "subdir/custom_resolve_dir/testproj2");
6 changes: 6 additions & 0 deletions tests/config_module_system_node_resolve_dirname/toplevel.js
@@ -0,0 +1,6 @@
// @flow

import {name} from "testproj";

(name: "node_modules/testproj");
(name: "custom_resolve_dir/testproj"); // Error: Resolve from node_modules first!

0 comments on commit e1e301c

Please sign in to comment.