reload.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. /*!
  2. * Cluster - reload
  3. * Copyright (c) 2011 LearnBoost <dev@learnboost.com>
  4. * MIT Licensed
  5. */
  6. /**
  7. * Module dependencies.
  8. */
  9. var fs = require('fs')
  10. , basename = require('path').basename
  11. , extname = require('path').extname;
  12. /**
  13. * Restart the server the given js `files` have changed.
  14. * `files` may be several directories, filenames, etc,
  15. * defaulting to the server's root directory.
  16. *
  17. * Options:
  18. *
  19. * - `signal` Signal defaulting to __SIGTERM__
  20. * - `interval` Watcher interval, defaulting to `100`
  21. * - `extensions` File extensions to watch, defaults to ['.js']
  22. *
  23. * Examples:
  24. *
  25. * cluster(server)
  26. * .use(cluster.reload())
  27. * .listen(3000);
  28. *
  29. * cluster(server)
  30. * .use(cluster.reload('lib'))
  31. * .listen(3000);
  32. *
  33. * cluster(server)
  34. * .use(cluster.reload(['lib', 'tests', 'index.js']))
  35. * .listen(3000);
  36. *
  37. * cluster(server)
  38. * .use(cluster.reload('lib', { interval: 60000 }))
  39. * .listen(3000);
  40. *
  41. * cluster(server)
  42. * .use(cluster.reload('lib', { extensions: ['.js', '.coffee'] }))
  43. * .listen(3000);
  44. *
  45. * Ignore Directories:
  46. *
  47. * By default `reload()` will ignore the following directories:
  48. *
  49. * - node_modules
  50. * - support
  51. * - examples
  52. * - test
  53. * - bin
  54. *
  55. * Alter with `reload.ignoreDirectories`
  56. *
  57. * cluster.reload.ignoreDirectories.push('src');
  58. *
  59. * @param {String|Array} files
  60. * @param {Options} options
  61. * @return {Function}
  62. * @api public
  63. */
  64. exports = module.exports = function(files, options){
  65. options = options || {};
  66. // defaults
  67. var interval = options.interval || 100
  68. , extensions = options.extensions || ['.js']
  69. , signal = options.signal || 'SIGTERM';
  70. return function(master){
  71. if (!files) files = master.dir;
  72. if (!Array.isArray(files)) files = [files];
  73. files.forEach(traverse);
  74. // traverse file if it is a directory
  75. // otherwise setup the watcher
  76. function traverse(file) {
  77. file = master.resolve(file);
  78. fs.stat(file, function(err, stat){
  79. if (!err) {
  80. if (stat.isDirectory()) {
  81. if (~exports.ignoreDirectories.indexOf(basename(file))) return;
  82. fs.readdir(file, function(err, files){
  83. files.map(function(f){
  84. return file + '/' + f;
  85. }).forEach(traverse);
  86. });
  87. } else {
  88. watch(file);
  89. }
  90. }
  91. });
  92. }
  93. // watch file for changes
  94. function watch(file) {
  95. if (!~extensions.indexOf(extname(file))) return;
  96. fs.watchFile(file, { interval: interval }, function(curr, prev){
  97. if (curr.mtime > prev.mtime) {
  98. console.log(' \033[36mchanged\033[0m \033[90m- %s\033[0m', file);
  99. master.restartWorkers(signal);
  100. }
  101. });
  102. }
  103. }
  104. };
  105. /**
  106. * Directories to ignore.
  107. */
  108. exports.ignoreDirectories = ['node_modules', 'support', 'test', 'bin'];