fsevents.js 3.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  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 path = require('path');
  10. var binary = require('node-pre-gyp');
  11. var Native = require(binary.find(path.join(__dirname, 'package.json')));
  12. var EventEmitter = require('events').EventEmitter;
  13. var fs = require('fs');
  14. var inherits = require('util').inherits;
  15. function FSEvents(path, handler) {
  16. EventEmitter.call(this);
  17. Object.defineProperty(this, '_impl', {
  18. value: new Native.FSEvents(String(path || ''), handler),
  19. enumerable: false,
  20. writable: false
  21. });
  22. }
  23. inherits(FSEvents, EventEmitter);
  24. proxies(FSEvents, Native.FSEvents);
  25. module.exports = watch;
  26. module.exports.getInfo = getInfo;
  27. module.exports.FSEvents = Native.FSEvents;
  28. module.exports.Constants = Native.Constants;
  29. var defer = global.setImmediate || process.nextTick;
  30. function watch(path) {
  31. var fse = new FSEvents(String(path || ''), handler);
  32. EventEmitter.call(fse);
  33. return fse;
  34. function handler(path, flags, id) {
  35. defer(function() {
  36. fse.emit('fsevent', path, flags, id);
  37. var info = getInfo(path, flags);
  38. info.id = id;
  39. if (info.event === 'moved') {
  40. fs.stat(info.path, function(err, stat) {
  41. info.event = (err || !stat) ? 'moved-out' : 'moved-in';
  42. fse.emit('change', path, info);
  43. fse.emit(info.event, path, info);
  44. });
  45. } else {
  46. fse.emit('change', path, info);
  47. fse.emit(info.event, path, info);
  48. }
  49. });
  50. }
  51. }
  52. function proxies(ctor, target) {
  53. Object.keys(target.prototype).filter(function(key) {
  54. return typeof target.prototype[key] === 'function';
  55. }).forEach(function(key) {
  56. ctor.prototype[key] = function() {
  57. this._impl[key].apply(this._impl, arguments);
  58. return this;
  59. }
  60. });
  61. }
  62. function getFileType(flags) {
  63. if (Native.Constants.kFSEventStreamEventFlagItemIsFile & flags) return 'file';
  64. if (Native.Constants.kFSEventStreamEventFlagItemIsDir & flags) return 'directory';
  65. if (Native.Constants.kFSEventStreamEventFlagItemIsSymlink & flags) return 'symlink';
  66. }
  67. function getEventType(flags) {
  68. if (Native.Constants.kFSEventStreamEventFlagItemRemoved & flags) return 'deleted';
  69. if (Native.Constants.kFSEventStreamEventFlagItemRenamed & flags) return 'moved';
  70. if (Native.Constants.kFSEventStreamEventFlagItemCreated & flags) return 'created';
  71. if (Native.Constants.kFSEventStreamEventFlagItemModified & flags) return 'modified';
  72. if (Native.Constants.kFSEventStreamEventFlagRootChanged & flags) return 'root-changed';
  73. return 'unknown';
  74. }
  75. function getFileChanges(flags) {
  76. return {
  77. inode: !! (Native.Constants.kFSEventStreamEventFlagItemInodeMetaMod & flags),
  78. finder: !! (Native.Constants.kFSEventStreamEventFlagItemFinderInfoMod & flags),
  79. access: !! (Native.Constants.kFSEventStreamEventFlagItemChangeOwner & flags),
  80. xattrs: !! (Native.Constants.kFSEventStreamEventFlagItemXattrMod & flags)
  81. };
  82. }
  83. function getInfo(path, flags) {
  84. return {
  85. path: path,
  86. event: getEventType(flags),
  87. type: getFileType(flags),
  88. changes: getFileChanges(flags),
  89. flags: flags
  90. };
  91. }