fsevents.js 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. /*
  2. ** © 2014 by Philipp Dunkel <pip@pipobscure.com>
  3. ** Licensed under MIT License.
  4. */
  5. /* jshint node:true */
  6. 'use strict';
  7. if (process.platform !== 'darwin')
  8. throw new Error('Module \'fsevents\' is not compatible with platform \'' + process.platform + '\'');
  9. var Native = require("bindings")("fse");
  10. var EventEmitter = require('events').EventEmitter;
  11. var fs = require('fs');
  12. var inherits = require('util').inherits;
  13. function FSEvents(path, handler) {
  14. EventEmitter.call(this);
  15. Object.defineProperty(this, '_impl', {
  16. value: new Native.FSEvents(String(path || ''), handler),
  17. enumerable: false,
  18. writable: false
  19. });
  20. }
  21. inherits(FSEvents, EventEmitter);
  22. proxies(FSEvents, Native.FSEvents);
  23. module.exports = watch;
  24. module.exports.getInfo = getInfo;
  25. module.exports.FSEvents = Native.FSEvents;
  26. module.exports.Constants = Native.Constants;
  27. var defer = global.setImmediate || process.nextTick;
  28. function watch(path) {
  29. var fse = new FSEvents(String(path || ''), handler);
  30. EventEmitter.call(fse);
  31. return fse;
  32. function handler(path, flags, id) {
  33. defer(function() {
  34. fse.emit('fsevent', path, flags, id);
  35. var info = getInfo(path, flags);
  36. info.id = id;
  37. if (info.event === 'moved') {
  38. fs.stat(info.path, function(err, stat) {
  39. info.event = (err || !stat) ? 'moved-out' : 'moved-in';
  40. fse.emit('change', path, info);
  41. fse.emit(info.event, path, info);
  42. });
  43. } else {
  44. fse.emit('change', path, info);
  45. fse.emit(info.event, path, info);
  46. }
  47. });
  48. }
  49. }
  50. function proxies(ctor, target) {
  51. Object.keys(target.prototype).filter(function(key) {
  52. return typeof target.prototype[key] === 'function';
  53. }).forEach(function(key) {
  54. ctor.prototype[key] = function() {
  55. this._impl[key].apply(this._impl, arguments);
  56. return this;
  57. }
  58. });
  59. }
  60. function getFileType(flags) {
  61. if (Native.Constants.kFSEventStreamEventFlagItemIsFile & flags) return 'file';
  62. if (Native.Constants.kFSEventStreamEventFlagItemIsDir & flags) return 'directory';
  63. if (Native.Constants.kFSEventStreamEventFlagItemIsSymlink & flags) return 'symlink';
  64. }
  65. function getEventType(flags) {
  66. if (Native.Constants.kFSEventStreamEventFlagItemRemoved & flags) return 'deleted';
  67. if (Native.Constants.kFSEventStreamEventFlagItemRenamed & flags) return 'moved';
  68. if (Native.Constants.kFSEventStreamEventFlagItemCreated & flags) return 'created';
  69. if (Native.Constants.kFSEventStreamEventFlagItemModified & flags) return 'modified';
  70. if (Native.Constants.kFSEventStreamEventFlagRootChanged & flags) return 'root-changed';
  71. return 'unknown';
  72. }
  73. function getFileChanges(flags) {
  74. return {
  75. inode: !! (Native.Constants.kFSEventStreamEventFlagItemInodeMetaMod & flags),
  76. finder: !! (Native.Constants.kFSEventStreamEventFlagItemFinderInfoMod & flags),
  77. access: !! (Native.Constants.kFSEventStreamEventFlagItemChangeOwner & flags),
  78. xattrs: !! (Native.Constants.kFSEventStreamEventFlagItemXattrMod & flags)
  79. };
  80. }
  81. function getInfo(path, flags) {
  82. return {
  83. path: path,
  84. event: getEventType(flags),
  85. type: getFileType(flags),
  86. changes: getFileChanges(flags),
  87. flags: flags
  88. };
  89. }