]>
git.immae.eu Git - github/fretlink/purs-loader.git/blob - lib/to-javascript.js
3 var Promise
= require('bluebird');
5 var fs
= Promise
.promisifyAll(require('fs'));
7 var path
= require('path');
9 var jsStringEscape
= require('js-string-escape');
11 var difference
= require('lodash.difference');
13 var debug_
= require('debug');
15 var debug
= debug_('purs-loader');
17 var debugVerbose
= debug_('purs-loader:verbose');
19 var PsModuleMap
= require('./purs-module-map');
21 function updatePsModuleMap(psModule
) {
22 var options
= psModule
.options
;
24 var cache
= psModule
.cache
;
26 var filePurs
= psModule
.srcPath
;
28 if (!cache
.psModuleMap
) {
29 debugVerbose('module mapping does not exist - making a new module map');
31 cache
.psModuleMap
= PsModuleMap
.makeMap(options
.src
);
33 return cache
.psModuleMap
;
35 debugVerbose('module mapping exists - updating module map for %s', filePurs
);
37 cache
.psModuleMap
= cache
.psModuleMap
.then(function (psModuleMap
) {
38 return PsModuleMap
.makeMapEntry(filePurs
).then(function (result
) {
39 var map
= Object
.assign(psModuleMap
, result
);
45 return cache
.psModuleMap
;
49 // Reference the bundle.
50 function makeBundleJS(psModule
) {
51 var bundleOutput
= psModule
.options
.bundleOutput
;
53 var name
= psModule
.name
;
55 var srcDir
= psModule
.srcDir
;
57 var escaped
= jsStringEscape(path
.relative(srcDir
, bundleOutput
));
59 var result
= 'module.exports = require("' + escaped
+ '")["' + name
+ '"]';
61 return Promise
.resolve(result
);
64 // Replace require paths to output files generated by psc with paths
65 // to purescript sources, which are then also run through this loader.
66 // Additionally, the imports replaced are tracked so that in the event
67 // the compiler fails to compile the PureScript source, we can tack on
68 // any new imports in order to allow webpack to watch the new files
69 // before they have been successfully compiled.
70 function makeJS(psModule
, psModuleMap
, js
) {
71 var requireRE
= /require\(['"]\.\.\/([\w\.]+)(?:\/index\.js)?['"]\)/g;
73 var foreignRE
= /require\(['"]\.\/foreign(?:\.js)?['"]\)/g;
75 var name
= psModule
.name
;
77 var imports
= psModuleMap
[name
].imports
;
79 var replacedImports
= [];
81 var result
= js
.replace(requireRE
, function (m
, p1
) {
82 var moduleValue
= psModuleMap
[p1
];
85 debug('module %s was not found in the map, replacing require with null', p1
);
89 var escapedPath
= jsStringEscape(moduleValue
.src
);
91 replacedImports
.push(p1
);
93 return 'require("' + escapedPath
+ '")';
95 }).replace(foreignRE
, function () {
96 var escapedPath
= jsStringEscape(psModuleMap
[name
].ffi
);
98 return 'require("' + escapedPath
+ '")';
101 var additionalImports
= difference(imports
, replacedImports
);
103 if (!additionalImports
.length
) {
104 return Promise
.resolve(result
);
106 debug('rebuilding module map due to additional imports for %s: %o', name
, additionalImports
);
108 psModule
.cache
.psModuleMap
= null;
110 return updatePsModuleMap(psModule
).then(function (updatedPsModuleMap
) {
111 var additionalImportsResult
= additionalImports
.map(function (import_
) {
112 var moduleValue
= updatedPsModuleMap
[import_
];
115 debug('module %s was not found in the map, skipping require', import_
);
119 var escapedPath
= jsStringEscape(moduleValue
.src
);
121 return 'var ' + import_
.replace(/\./g, '_') + ' = require("' + escapedPath
+ '")';
123 }).filter(function (a
) {
127 return result
+ '\n' + additionalImportsResult
;
132 module
.exports
= function toJavaScript(psModule
) {
133 var options
= psModule
.options
;
135 var cache
= psModule
.cache
;
137 var bundlePath
= path
.resolve(options
.bundleOutput
);
139 var jsPath
= options
.bundle
? bundlePath : psModule
.jsPath
;
141 var js
= fs
.readFileAsync(jsPath
, 'utf8').catch(function () {
145 var psModuleMap
= updatePsModuleMap(psModule
);
147 debugVerbose('loading JavaScript for %s', psModule
.name
);
149 return Promise
.props({ js: js
, psModuleMap: psModuleMap
}).then(function (result
) {
150 return options
.bundle
? makeBundleJS(psModule
) : makeJS(psModule
, result
.psModuleMap
, result
.js
);