server.js 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. import Promise from 'bluebird';
  2. import browserify from 'browserify';
  3. import budo from 'budo';
  4. import fs from 'fs';
  5. import glob from 'glob';
  6. import mkdirp from 'mkdirp';
  7. import path from 'path';
  8. /* eslint no-console: 0 */
  9. const pkg = require(path.join(__dirname, '../package.json'));
  10. // Replace "%s" tokens with the plugin name in a string.
  11. const nameify = (str) =>
  12. str.replace(/%s/g, pkg.name.split('/').reverse()[0]);
  13. const srces = {
  14. js: 'src/index.js',
  15. tests: glob.sync('test/**/*.test.js')
  16. };
  17. const dests = {
  18. js: nameify('dist/%s.js'),
  19. tests: 'test/dist/bundle.js'
  20. };
  21. const bundlers = {
  22. js: browserify({
  23. debug: true,
  24. entries: [srces.js],
  25. standalone: nameify('%s'),
  26. transform: [
  27. 'babelify',
  28. ['browserify-shim', {global: true}]
  29. ]
  30. }),
  31. tests: browserify({
  32. debug: true,
  33. entries: srces.tests,
  34. transform: [
  35. 'babelify',
  36. ['browserify-shim', {global: true}]
  37. ]
  38. })
  39. };
  40. const bundle = (name) => {
  41. return new Promise((resolve, reject) => {
  42. bundlers[name]
  43. .bundle()
  44. .pipe(fs.createWriteStream(dests[name]))
  45. .on('finish', resolve)
  46. .on('error', reject);
  47. });
  48. };
  49. mkdirp.sync('dist');
  50. // Start the server _after_ the initial bundling is done.
  51. Promise.all([bundle('js'), bundle('tests')]).then(() => {
  52. const server = budo({
  53. port: 9999,
  54. stream: process.stdout
  55. }).on('reload', (f) => console.log('reloading %s', f || 'everything'));
  56. /**
  57. * A collection of functions which are mapped to strings that are used to
  58. * generate RegExp objects. If a filepath matches the RegExp, the function
  59. * will be used to handle that watched file.
  60. *
  61. * @type {Object}
  62. */
  63. const handlers = {
  64. /**
  65. * Handler for JavaScript source.
  66. *
  67. * @param {String} event
  68. * @param {String} file
  69. */
  70. '^src/.+\.js$'(event, file) {
  71. console.log('re-bundling javascript and tests');
  72. Promise.all([bundle('js'), bundle('tests')]).then(() => server.reload());
  73. },
  74. /**
  75. * Handler for JavaScript tests.
  76. *
  77. * @param {String} event
  78. * @param {String} file
  79. */
  80. '^test/.+\.test\.js$'(event, file) {
  81. console.log('re-bundling tests');
  82. bundle('tests').then(() => server.reload());
  83. }
  84. };
  85. /**
  86. * Finds the first handler function for the file that matches a RegExp
  87. * derived from the keys.
  88. *
  89. * @param {String} file
  90. * @return {Function|Undefined}
  91. */
  92. const findHandler = (file) => {
  93. const keys = Object.keys(handlers);
  94. for (let i = 0; i < keys.length; i++) {
  95. const regex = new RegExp(keys[i]);
  96. if (regex.test(file)) {
  97. return handlers[keys[i]];
  98. }
  99. }
  100. };
  101. server
  102. .live()
  103. .watch([
  104. 'index.html',
  105. 'src/**/*.js',
  106. 'test/**/*.test.js',
  107. 'test/index.html'
  108. ])
  109. .on('watch', (event, file) => {
  110. const handler = findHandler(file);
  111. console.log(`detected a "${event}" event in "${file}"`);
  112. if (handler) {
  113. handler(event, file);
  114. } else {
  115. server.reload();
  116. }
  117. });
  118. });