forked from rescript-lang/rescript
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbsb_package_specs.ml
177 lines (150 loc) · 5.82 KB
/
bsb_package_specs.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
(* Copyright (C) 2017 Authors of BuckleScript
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* In addition to the permissions granted to you by the LGPL, you may combine
* or link a "work that uses the Library" with a publicly distributed version
* of this file to produce a combined library or application, then distribute
* that combined work under the terms of your choosing, with no requirement
* to comply with the obligations normally placed on you by section 4 of the
* LGPL version 3 (or the corresponding section of a later version of the LGPL
* should you choose to use a later version).
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *)
let (//) = Ext_path.combine
(* TODO: sync up with {!Js_packages_info.module_system} *)
type format =
| NodeJS | Es6 | Es6_global
type spec = {
format : format;
in_source : bool
}
module Spec_set = Set.Make( struct type t = spec
let compare = Pervasives.compare
end)
type t = Spec_set.t
let bad_module_format_message_exn ~loc format =
Bsb_exception.errorf ~loc "package-specs: `%s` isn't a valid output module format. It has to be one of: %s, %s or %s"
format
Literals.commonjs
Literals.es6
Literals.es6_global
let supported_format (x : string) loc =
if x = Literals.commonjs then NodeJS
else if x = Literals.es6 then Es6
else if x = Literals.es6_global then Es6_global
else bad_module_format_message_exn ~loc x
let string_of_format (x : format) =
match x with
| NodeJS -> Literals.commonjs
| Es6 -> Literals.es6
| Es6_global -> Literals.es6_global
let prefix_of_format (x : format) =
(match x with
| NodeJS -> Bsb_config.lib_js
| Es6 -> Bsb_config.lib_es6
| Es6_global -> Bsb_config.lib_es6_global )
let rec from_array (arr : Ext_json_types.t array) : Spec_set.t =
let spec = ref Spec_set.empty in
let has_in_source = ref false in
Ext_array.iter arr (fun x ->
let result = from_json_single x in
if result.in_source then
(
if not !has_in_source then
has_in_source:= true
else
Bsb_exception.errorf
~loc:(Ext_json.loc_of x)
"package-specs: we've detected two module formats that are both configured to be in-source."
);
spec := Spec_set.add result !spec
);
!spec
(* TODO: FIXME: better API without mutating *)
and from_json_single (x : Ext_json_types.t) : spec =
match x with
| Str {str = format; loc } ->
{format = supported_format format loc ; in_source = false }
| Obj {map; loc} ->
begin match String_map.find_exn map "module" with
| Str {str = format} ->
let in_source =
match String_map.find_opt map Bsb_build_schemas.in_source with
| Some (True _) -> true
| Some _
| None -> false
in
{format = supported_format format loc ; in_source }
| Arr _ ->
Bsb_exception.errorf ~loc
"package-specs: when the configuration is an object, `module` field should be a string, not an array. If you want to pass multiple module specs, try turning package-specs into an array of objects (or strings) instead."
| _ ->
Bsb_exception.errorf ~loc
"package-specs: the `module` field of the configuration object should be a string."
| exception _ ->
Bsb_exception.errorf ~loc
"package-specs: when the configuration is an object, the `module` field is mandatory."
end
| _ -> Bsb_exception.errorf ~loc:(Ext_json.loc_of x)
"package-specs: we expect either a string or an object."
let from_json (x : Ext_json_types.t) : Spec_set.t =
match x with
| Arr {content ; _} -> from_array content
| _ -> Spec_set.singleton (from_json_single x )
let bs_package_output = "-bs-package-output"
(** Assume input is valid
{[ -bs-package-output commonjs:lib/js/jscomp/test ]}
*)
let package_flag ({format; in_source } : spec) dir =
Ext_string.inter2
bs_package_output
(Ext_string.concat3
(string_of_format format)
Ext_string.single_colon
(if in_source then dir else
prefix_of_format format // dir))
let package_flag_of_package_specs (package_specs : t)
(dirname : string ) : string =
Spec_set.fold (fun format acc ->
Ext_string.inter2 acc (package_flag format dirname )
) package_specs Ext_string.empty
let default_package_specs =
Spec_set.singleton
{ format = NodeJS ; in_source = false }
(**
[get_list_of_output_js specs "src/hi/hello"]
*)
let get_list_of_output_js
(package_specs : Spec_set.t)
(bs_suffix : bool)
(output_file_sans_extension : string)
=
Spec_set.fold
(fun (spec : spec) acc ->
let basename = Ext_namespace.change_ext_ns_suffix
output_file_sans_extension
(if bs_suffix then Literals.suffix_bs_js else Literals.suffix_js)
in
(Bsb_config.proj_rel @@ (if spec.in_source then basename
else prefix_of_format spec.format // basename))
:: acc
) package_specs []
let list_dirs_by
(package_specs : Spec_set.t)
(f : string -> unit)
=
Spec_set.iter (fun (spec : spec) ->
if not spec.in_source then
f (prefix_of_format spec.format)
) package_specs