use_require.js 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. #!/usr/bin/env node
  2. const path = require('path');
  3. const program = require('commander');
  4. const fs = require('fs');
  5. const fse = require('fs-extra');
  6. const babel = require('@babel/core');
  7. program
  8. .option('-m, --with-source-maps [type]', 'output source maps when not generating a bundled app (type may be empty for external source maps, inline for inline source maps, or both) ')
  9. .option('--clean', 'clear the lib folder before building')
  10. .parse(process.argv);
  11. // the various important paths
  12. const paths = {
  13. main: path.resolve(__dirname, '..'),
  14. core: path.resolve(__dirname, '..', 'core'),
  15. vendor: path.resolve(__dirname, '..', 'vendor'),
  16. libDirBase: path.resolve(__dirname, '..', 'lib'),
  17. };
  18. // util.promisify requires Node.js 8.x, so we have our own
  19. function promisify(original) {
  20. return function promiseWrap() {
  21. const args = Array.prototype.slice.call(arguments);
  22. return new Promise((resolve, reject) => {
  23. original.apply(this, args.concat((err, value) => {
  24. if (err) return reject(err);
  25. resolve(value);
  26. }));
  27. });
  28. };
  29. }
  30. const writeFile = promisify(fs.writeFile);
  31. const readdir = promisify(fs.readdir);
  32. const lstat = promisify(fs.lstat);
  33. const ensureDir = promisify(fse.ensureDir);
  34. const babelTransformFile = promisify(babel.transformFile);
  35. // walkDir *recursively* walks directories trees,
  36. // calling the callback for all normal files found.
  37. function walkDir(basePath, cb, filter) {
  38. return readdir(basePath)
  39. .then((files) => {
  40. const paths = files.map(filename => path.join(basePath, filename));
  41. return Promise.all(paths.map(filepath => lstat(filepath)
  42. .then((stats) => {
  43. if (filter !== undefined && !filter(filepath, stats)) return;
  44. if (stats.isSymbolicLink()) return;
  45. if (stats.isFile()) return cb(filepath);
  46. if (stats.isDirectory()) return walkDir(filepath, cb, filter);
  47. })));
  48. });
  49. }
  50. function makeLibFiles(sourceMaps) {
  51. // NB: we need to make a copy of babelOpts, since babel sets some defaults on it
  52. const babelOpts = () => ({
  53. plugins: [],
  54. presets: [
  55. [ '@babel/preset-env',
  56. { modules: 'commonjs' } ]
  57. ],
  58. ast: false,
  59. sourceMaps: sourceMaps,
  60. });
  61. fse.ensureDirSync(paths.libDirBase);
  62. const outFiles = [];
  63. const handleDir = (vendorRewrite, inPathBase, filename) => Promise.resolve()
  64. .then(() => {
  65. const outPath = path.join(paths.libDirBase, path.relative(inPathBase, filename));
  66. if (path.extname(filename) !== '.js') {
  67. return; // skip non-javascript files
  68. }
  69. return Promise.resolve()
  70. .then(() => ensureDir(path.dirname(outPath)))
  71. .then(() => {
  72. const opts = babelOpts();
  73. // Adjust for the fact that we move the core files relative
  74. // to the vendor directory
  75. if (vendorRewrite) {
  76. opts.plugins.push(["import-redirect",
  77. {"root": paths.libDirBase,
  78. "redirect": { "vendor/(.+)": "./vendor/$1"}}]);
  79. }
  80. return babelTransformFile(filename, opts)
  81. .then((res) => {
  82. console.log(`Writing ${outPath}`);
  83. const {map} = res;
  84. let {code} = res;
  85. if (sourceMaps === true) {
  86. // append URL for external source map
  87. code += `\n//# sourceMappingURL=${path.basename(outPath)}.map\n`;
  88. }
  89. outFiles.push(`${outPath}`);
  90. return writeFile(outPath, code)
  91. .then(() => {
  92. if (sourceMaps === true || sourceMaps === 'both') {
  93. console.log(` and ${outPath}.map`);
  94. outFiles.push(`${outPath}.map`);
  95. return writeFile(`${outPath}.map`, JSON.stringify(map));
  96. }
  97. });
  98. });
  99. });
  100. });
  101. Promise.resolve()
  102. .then(() => {
  103. const handler = handleDir.bind(null, false, paths.main);
  104. return walkDir(paths.vendor, handler);
  105. })
  106. .then(() => {
  107. const handler = handleDir.bind(null, true, paths.core);
  108. return walkDir(paths.core, handler);
  109. })
  110. .catch((err) => {
  111. console.error(`Failure converting modules: ${err}`);
  112. process.exit(1);
  113. });
  114. }
  115. let options = program.opts();
  116. if (options.clean) {
  117. console.log(`Removing ${paths.libDirBase}`);
  118. fse.removeSync(paths.libDirBase);
  119. }
  120. makeLibFiles(options.withSourceMaps);