1 | var _ = require('lodash');
|
2 | var fs = require('fs-extra');
|
3 | var path = require('path');
|
4 | var denodeify = require("pdenodeify");
|
5 | var eachGraph = require("../graph/each_dependencies");
|
6 | var transformImport = require("../build/transform");
|
7 | var helpers = require('./helpers/helpers');
|
8 | var winston = require('winston');
|
9 | var logging = require("../logger");
|
10 |
|
11 | var mergeModules = function(items, modules){
|
12 | var i = 0,
|
13 | item;
|
14 | while(i < items.length) {
|
15 | item = items[i];
|
16 | if(typeof item === "object" && !(item instanceof RegExp) ) {
|
17 | var moduleNames = _.map( _.filter(modules, item), "moduleName");
|
18 | items.splice.apply(items,[i,1].concat(moduleNames));
|
19 | i = i + moduleNames.length;
|
20 | } else {
|
21 | i++;
|
22 | }
|
23 | }
|
24 | };
|
25 |
|
26 | var addDefaults = function(name, obj, defaults){
|
27 | var helpers = [];
|
28 |
|
29 | name.replace(/\+([\w-]+)/g,function(whole, part){
|
30 | var defs = defaults[part];
|
31 | if(defs) {
|
32 | if(typeof defs === "function") {
|
33 | defs = defs(obj);
|
34 | _.assign(obj, defs);
|
35 | } else {
|
36 | _.defaults(obj, defs);
|
37 | }
|
38 | helpers.push(part);
|
39 | }
|
40 |
|
41 | });
|
42 |
|
43 | if(helpers.length) {
|
44 | winston.debug(" added helpers: "+helpers.join(","));
|
45 | }
|
46 | };
|
47 |
|
48 |
|
49 |
|
50 |
|
51 |
|
52 |
|
53 |
|
54 | function normalize(loader, mods) {
|
55 | var modNames = (mods && !Array.isArray(mods)) ? [mods] : mods;
|
56 |
|
57 | return (modNames || []).map(function(moduleName) {
|
58 | return !_.isString(moduleName) ?
|
59 | Promise.resolve(moduleName) :
|
60 | loader.normalize(moduleName);
|
61 | });
|
62 | }
|
63 |
|
64 | function writeFile(filename, data, config) {
|
65 | var code = data.code;
|
66 | var map = data.map;
|
67 | var mkdir = denodeify(fs.mkdirs);
|
68 | var writeFile = denodeify(fs.writeFile);
|
69 |
|
70 | return mkdir(path.dirname(filename))
|
71 | .then(function() {
|
72 | return writeFile(filename, code);
|
73 | })
|
74 | .then(function() {
|
75 | var sourceMaps = map && config.options &&
|
76 | config.options.sourceMaps;
|
77 |
|
78 | if (sourceMaps) {
|
79 | return writeFile(filename + ".map", map+"");
|
80 | }
|
81 | });
|
82 | }
|
83 |
|
84 |
|
85 | module.exports = function(config, defaults, modules){
|
86 | logging.setup(config.options || {}, config.steal || {});
|
87 |
|
88 |
|
89 | var defaultHelpers = _.assign(_.clone(helpers), defaults);
|
90 |
|
91 |
|
92 | config.outputs = _.map(
|
93 | config.outputs || config.transforms,
|
94 | function(output, name) {
|
95 | addDefaults(name, output, defaultHelpers || {}, config.options || {});
|
96 |
|
97 |
|
98 | mergeModules(output.modules || [], modules);
|
99 | mergeModules(output.eachModule || [], modules);
|
100 | mergeModules(output.graphs || [], modules);
|
101 | mergeModules(output.ignore || [], modules);
|
102 |
|
103 | return {
|
104 | name: name,
|
105 | output: output
|
106 | };
|
107 | }
|
108 | );
|
109 |
|
110 | var transformAndWriteOut = function(transform, moduleNames, out, outputOptions) {
|
111 | var modulesMap = _.keyBy(modules, "moduleName");
|
112 |
|
113 | var options = _.assign({}, outputOptions, out.output, {
|
114 | ignore: outputOptions.ignore || out.output.ignore
|
115 | });
|
116 |
|
117 | return transform(moduleNames, options)
|
118 | .then(function(result){
|
119 | var filePath;
|
120 |
|
121 | if (_.isUndefined(out.output.dest)) {
|
122 | return Promise.reject(new Error(
|
123 | "Attribute 'dest' is required\n" +
|
124 | "Add 'dest' to the ExportOutput object.\n" +
|
125 | "See http://stealjs.com/docs/steal-tools.export.output.html#dest for more details."
|
126 | ));
|
127 | }
|
128 | else if (_.isString(out.output.dest)) {
|
129 | filePath = out.output.dest;
|
130 | }
|
131 | else if (_.isFunction(out.output.dest)) {
|
132 |
|
133 | var loads = (_.isString(moduleNames) ?
|
134 | transform.graph[moduleNames].load :
|
135 | moduleNames.map(function(moduleName){
|
136 | return transform.graph[moduleName].load;
|
137 | }));
|
138 |
|
139 | filePath = out.output.dest(moduleNames,
|
140 | modulesMap[moduleNames], loads, transform.loader);
|
141 | }
|
142 |
|
143 | winston.info("> " + filePath);
|
144 | return writeFile(filePath, result, config);
|
145 | });
|
146 | };
|
147 |
|
148 | var processOutput = function(transform, out) {
|
149 | winston.info("OUTPUT: " + out.name);
|
150 |
|
151 | var modsPromise;
|
152 | var doTransform;
|
153 | var loader = transform.loader;
|
154 |
|
155 |
|
156 | if(out.output.eachModule) {
|
157 | if (Array.isArray(out.output.eachModule)) {
|
158 | modsPromise = normalize(loader, out.output.eachModule);
|
159 | }
|
160 | else {
|
161 | modsPromise = normalize(loader, _.map(
|
162 | _.filter(modules, out.output.eachModule),
|
163 | "moduleName"
|
164 | ));
|
165 | }
|
166 |
|
167 | doTransform = function(mods, ignores){
|
168 | return Promise.all(mods.map(function(mod) {
|
169 | return transformAndWriteOut(transform, mod, out, {
|
170 | ignore: ignores
|
171 | });
|
172 | }));
|
173 | };
|
174 |
|
175 | } else if(out.output.graphs){
|
176 | if (typeof out.output.graphs === "function") {
|
177 | modsPromise = normalize(loader, out.output.graphs(loader));
|
178 | }
|
179 | else {
|
180 | modsPromise = normalize(loader, out.output.graphs);
|
181 | }
|
182 |
|
183 | doTransform = function(mods, ignores) {
|
184 | var promises = [];
|
185 |
|
186 | eachGraph(transform.graph, mods, function(name, node) {
|
187 | if(node && !transformImport.matches(ignores, name, node.load)) {
|
188 | var promise = transformAndWriteOut(transform, name, out, {
|
189 | ignoreAllDependencies: true
|
190 | });
|
191 | promises.push(promise);
|
192 | }
|
193 | });
|
194 |
|
195 | return Promise.all(promises);
|
196 | };
|
197 |
|
198 | } else {
|
199 | if(Array.isArray( out.output.modules) ) {
|
200 | modsPromise = normalize(loader, out.output.modules);
|
201 | } else if(typeof out.output.modules === "function"){
|
202 | modsPromise = normalize(loader, out.output.modules(loader));
|
203 | } else if(out.output.modules) {
|
204 | modsPromise = normalize(loader, [out.output.modules]);
|
205 | }
|
206 | doTransform = function(mods, ignores){
|
207 | return transformAndWriteOut(transform, mods, out, {
|
208 | ignore: ignores
|
209 | });
|
210 | };
|
211 | }
|
212 |
|
213 | var normalized;
|
214 | return Promise.all(modsPromise)
|
215 | .then(function(mods) {
|
216 | normalized = mods;
|
217 | var ignore = out.output.ignore || [];
|
218 |
|
219 | return Promise.all(normalize(loader, ignore));
|
220 | })
|
221 | .then(function(outputIgnore){
|
222 | var ignores = transformImport
|
223 | .getAllIgnores(outputIgnore, transform.graph);
|
224 |
|
225 | return doTransform(normalized, ignores);
|
226 | });
|
227 | };
|
228 |
|
229 | if (!config.steal) {
|
230 | var message;
|
231 | if(config.system) {
|
232 | message = "The 'system' option was removed in 1.0, use 'steal' instead: http://stealjs.com/docs/steal-tools.export.object.html";
|
233 | } else {
|
234 | message = "A 'steal' option is required.";
|
235 | }
|
236 | return Promise.reject(new Error(message));
|
237 | }
|
238 |
|
239 | return transformImport(config.steal, config.options)
|
240 | .then(function(configPluginify){
|
241 | var buildResult = configPluginify.data;
|
242 | return Promise.all(config.outputs.map(function(out) {
|
243 | return processOutput(configPluginify, out);
|
244 | }))
|
245 | .then(function(){
|
246 | return buildResult;
|
247 | });
|
248 | });
|
249 | };
|