]>
git.immae.eu Git - github/fretlink/purs-loader.git/blob - src/to-javascript.js
3 const Promise
= require('bluebird');
5 const fs
= Promise
.promisifyAll(require('fs'));
7 const path
= require('path');
9 const jsStringEscape
= require('js-string-escape');
11 const difference
= require('lodash.difference');
13 const debug
= require('debug')('purs-loader');
15 const PsModuleMap
= require('./PsModuleMap');
17 function updatePsModuleMap(psModule
) {
18 const options
= psModule
.options
;
20 const cache
= psModule
.cache
;
22 const filePurs
= psModule
.srcPath
;
24 if (!cache
.psModuleMap
) {
25 debug('module mapping does not exist');
27 return PsModuleMap
.makeMap(options
.src
).then(map
=> {
28 cache
.psModuleMap
= map
;
29 return cache
.psModuleMap
;
33 return PsModuleMap
.makeMapEntry(filePurs
).then(result
=> {
34 const map
= Object
.assign(cache
.psModuleMap
, result
);
36 cache
.psModuleMap
= map
;
38 return cache
.psModuleMap
;
43 // Reference the bundle.
44 function makeBundleJS(psModule
) {
45 const bundleOutput
= psMoudle
.options
.bundleOutput
;
47 const name
= psModule
.name
;
49 const srcDir
= psModule
.srcDir
;
51 const escaped
= jsStringEscape(path
.relative(srcDir
, bundleOutput
));
53 const result
= `module.exports = require("${escaped}")["${name}"]`;
58 // Replace require paths to output files generated by psc with paths
59 // to purescript sources, which are then also run through this loader.
60 // Additionally, the imports replaced are tracked so that in the event
61 // the compiler fails to compile the PureScript source, we can tack on
62 // any new imports in order to allow webpack to watch the new files
63 // before they have been successfully compiled.
64 function makeJS(psModule
, psModuleMap
, js
) {
65 const requireRE
= /require\(['"]\.\.\/([\w\.]+)['"]\)/g;
67 const foreignRE
= /require\(['"]\.\/foreign['"]\)/g;
69 const name
= psModule
.name
;
71 const imports
= psModuleMap
[name
].imports
;
73 var replacedImports
= [];
76 .replace(requireRE
, (m
, p1
) => {
77 const escapedPath
= jsStringEscape(psModuleMap
[p1
].src
);
79 replacedImports
.push(p1
);
81 return `require("${escapedPath}")`;
83 .replace(foreignRE
, () => {
84 const escapedPath
= jsStringEscape(psModuleMap
[name
].ffi
);
86 return `require("${escapedPath}")`;
90 debug('imports %o', imports
);
92 debug('replaced imports %o', replacedImports
);
94 const additionalImports
= difference(imports
, replacedImports
);
96 debug('additional imports for %s: %o', name
, additionalImports
);
98 const additionalImportsResult
= additionalImports
.map(import_
=> {
99 const escapedPath
= jsStringEscape(psModuleMap
[import_
].src
);
101 return `var ${import_.replace(/\./g, '_')} = require("${escapedPath}")`;
104 const result_
= result
+ (additionalImports
.length
? '\n' + additionalImportsResult : '');
109 module
.exports
= function toJavaScript(psModule
) {
110 const options
= psModule
.options
;
112 const cache
= psModule
.cache
;
114 const bundlePath
= path
.resolve(options
.bundleOutput
);
116 const jsPath
= cache
.bundle
? bundlePath : psModule
.jsPath
;
118 const js
= fs
.readFileAsync(jsPath
, 'utf8').catch(() => '');
120 const psModuleMap
= updatePsModuleMap(psModule
);
122 debug('loading JavaScript for %s', psModule
.name
);
124 return Promise
.props({js: js
, psModuleMap: psModuleMap
}).then(result
=>
126 makeBundleJS(psModule
) :
127 makeJS(psModule
, result
.psModuleMap
, result
.js
)