batman-rails-flo 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/README.md +29 -0
- data/Rakefile +2 -0
- data/lib/batman-rails-flo.rb +5 -0
- data/lib/batman_rails_flo/railtie.rb +9 -0
- data/lib/batman_rails_flo/tasks.rake +14 -0
- data/lib/batman_rails_flo/version.rb +3 -0
- data/vendor/assets/javascripts/batman_rails_flo/flo_server.js +67 -0
- data/vendor/assets/javascripts/batman_rails_flo/live_reload.js.coffee +129 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/CNAME +1 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/CONTRIBUTING.md +9 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/LICENSE +22 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/README +50 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/bin/cake +7 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/bin/coffee +7 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/lib/coffee-script/browser.js +134 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/lib/coffee-script/cake.js +112 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/lib/coffee-script/coffee-script.js +335 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/lib/coffee-script/command.js +569 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/lib/coffee-script/grammar.js +631 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/lib/coffee-script/helpers.js +252 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/lib/coffee-script/index.js +11 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/lib/coffee-script/lexer.js +926 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/lib/coffee-script/nodes.js +3158 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/lib/coffee-script/optparse.js +139 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/lib/coffee-script/parser.js +724 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/lib/coffee-script/register.js +66 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/lib/coffee-script/repl.js +163 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/lib/coffee-script/rewriter.js +475 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/lib/coffee-script/scope.js +146 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/lib/coffee-script/sourcemap.js +161 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/node_modules/mkdirp/LICENSE +21 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/node_modules/mkdirp/examples/pow.js +6 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/node_modules/mkdirp/index.js +82 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/node_modules/mkdirp/package.json +34 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/node_modules/mkdirp/readme.markdown +63 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/node_modules/mkdirp/test/chmod.js +38 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/node_modules/mkdirp/test/clobber.js +37 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/node_modules/mkdirp/test/mkdirp.js +28 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/node_modules/mkdirp/test/perm.js +32 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/node_modules/mkdirp/test/perm_sync.js +39 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/node_modules/mkdirp/test/race.js +41 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/node_modules/mkdirp/test/rel.js +32 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/node_modules/mkdirp/test/return.js +25 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/node_modules/mkdirp/test/return_sync.js +24 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/node_modules/mkdirp/test/root.js +18 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/node_modules/mkdirp/test/sync.js +32 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/node_modules/mkdirp/test/umask.js +28 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/node_modules/mkdirp/test/umask_sync.js +32 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/package.json +50 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/register.js +1 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/LICENSE +30 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/PATENTS +23 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/README.md +124 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/bin/flo +26 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/client/configure/configure.html +57 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/client/configure/configure.js +205 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/client/configure/style.css +334 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/client/connection.js +235 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/client/devtools.html +12 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/client/index.js +323 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/client/logger.js +42 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/client/logo.png +0 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/client/manifest.json +13 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/client/session.js +305 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/index.js +10 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/lib/flo.js +226 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/lib/server.js +94 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/README.md +66 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/index.js +437 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/minimatch/LICENSE +23 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/minimatch/README.md +218 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/minimatch/minimatch.js +1055 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/minimatch/node_modules/lru-cache/CONTRIBUTORS +14 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/minimatch/node_modules/lru-cache/LICENSE +23 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/minimatch/node_modules/lru-cache/README.md +97 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/minimatch/node_modules/lru-cache/lib/lru-cache.js +252 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/minimatch/node_modules/lru-cache/package.json +33 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/minimatch/node_modules/lru-cache/test/basic.js +369 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/minimatch/node_modules/lru-cache/test/foreach.js +52 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/minimatch/node_modules/lru-cache/test/memory-leak.js +50 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/minimatch/node_modules/sigmund/LICENSE +27 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/minimatch/node_modules/sigmund/README.md +53 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/minimatch/node_modules/sigmund/bench.js +283 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/minimatch/node_modules/sigmund/package.json +42 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/minimatch/node_modules/sigmund/sigmund.js +39 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/minimatch/node_modules/sigmund/test/basic.js +24 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/minimatch/package.json +40 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/minimatch/test/basic.js +399 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/minimatch/test/brace-expand.js +33 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/minimatch/test/caching.js +14 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/minimatch/test/defaults.js +274 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/minimatch/test/extglob-ending-with-state-char.js +8 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/walker/lib/walker.js +111 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/walker/license +13 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/walker/node_modules/makeerror/lib/makeerror.js +87 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/walker/node_modules/makeerror/node_modules/tmpl/lib/tmpl.js +17 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/walker/node_modules/makeerror/node_modules/tmpl/package.json +31 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/walker/node_modules/makeerror/node_modules/tmpl/readme.md +10 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/walker/node_modules/makeerror/package.json +34 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/walker/node_modules/makeerror/readme.md +77 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/walker/package.json +36 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/walker/readme.md +52 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/watch/LICENSE +55 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/watch/main.js +128 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/watch/package.json +34 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/watch/readme.mkd +72 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/watch/test/d/d/t +0 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/watch/test/d/t +0 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/watch/test/test_monitor.js +31 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/watch/test/test_monitorRootDirectory.js +28 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/watch/test/test_watchTree.js +20 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/package.json +45 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/test/test.js +243 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/CHANGELOG.md +81 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/LICENSE +177 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/Makefile +11 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/README.md +245 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/binding.gyp +14 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/build/Makefile +355 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/build/Release/linker.lock +0 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/build/Release/obj.target/validation/src/validation.o +0 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/build/Release/obj.target/xor/src/xor.o +0 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/build/Release/validation.node +0 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/build/Release/xor.node +0 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/build/binding.Makefile +6 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/build/config.gypi +115 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/build/gyp-mac-tool +512 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/build/validation.target.mk +154 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/build/xor.target.mk +154 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/index.js +1 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/install.js +31 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/lib/Constants.js +23 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/lib/Deprecation.js +38 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/lib/Validation.fallback.js +12 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/lib/Validation.js +18 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/lib/WebSocketClient.js +359 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/lib/WebSocketConnection.js +717 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/lib/WebSocketFrame.js +282 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/lib/WebSocketRequest.js +478 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/lib/WebSocketRouter.js +154 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/lib/WebSocketRouterRequest.js +59 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/lib/WebSocketServer.js +216 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/lib/utils.js +7 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/lib/websocket.js +11 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/lib/xor.fallback.js +13 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/lib/xor.js +18 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/package.json +43 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/src/validation.cc +144 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/src/xor.cpp +86 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/vendor/FastBufferList.js +192 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/vendor/node-ctype/LICENSE +18 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/vendor/node-ctype/ctio-faster.js +1126 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/package.json +25 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/test/client/browser_websocket.js +63 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/test/client/connection_test.js +57 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/test/client/logger_mock.js +15 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/test/client/session_test.js +194 -0
- data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/test/server/flo_test.js +211 -0
- data/vendor/assets/javascripts/batman_rails_flo/package.json +15 -0
- data/vendor/assets/javascripts/batman_rails_flo/reload_event_handler.js.coffee +56 -0
- metadata +232 -0
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2014, Facebook, Inc.
|
|
3
|
+
* All rights reserved.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the BSD-style license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree. An additional grant
|
|
7
|
+
* of patent rights can be found in the PATENTS file in the same directory.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
module.exports = require('./lib/flo');
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2014, Facebook, Inc.
|
|
3
|
+
* All rights reserved.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the BSD-style license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree. An additional grant
|
|
7
|
+
* of patent rights can be found in the PATENTS file in the same directory.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
'use strict';
|
|
11
|
+
|
|
12
|
+
var fs = require('fs');
|
|
13
|
+
var path = require('path');
|
|
14
|
+
var sane = require('sane');
|
|
15
|
+
var assert = require('assert');
|
|
16
|
+
var Server = require('./server');
|
|
17
|
+
var EventEmitter = require('events').EventEmitter;
|
|
18
|
+
|
|
19
|
+
module.exports = flo;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Top-level API for flo. Defaults params and instantiates `Flo`.
|
|
23
|
+
*
|
|
24
|
+
* @param {string} dir
|
|
25
|
+
* @param {object} options
|
|
26
|
+
* @param {function} callback
|
|
27
|
+
* @return {Flo}
|
|
28
|
+
* @public
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
function flo(dir, options, callback) {
|
|
32
|
+
if (typeof options === 'function') {
|
|
33
|
+
callback = options;
|
|
34
|
+
options = null;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
dir = path.resolve(dir);
|
|
38
|
+
|
|
39
|
+
options = options || {};
|
|
40
|
+
options = {
|
|
41
|
+
port: options.port || 8888,
|
|
42
|
+
host: options.host || 'localhost',
|
|
43
|
+
verbose: options.verbose || false,
|
|
44
|
+
glob: options.glob || [],
|
|
45
|
+
useFilePolling: options.useFilePolling || false,
|
|
46
|
+
pollingInterval: options.pollingInterval
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
callback = callback || noBuildCallback(dir);
|
|
50
|
+
|
|
51
|
+
return new Flo(dir, options, callback);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Time before we emit the ready event.
|
|
56
|
+
*/
|
|
57
|
+
|
|
58
|
+
var DELAY = 200;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Starts the server and the watcher and handles the piping between both and the
|
|
62
|
+
* resolver callback.
|
|
63
|
+
*
|
|
64
|
+
* @param {string} dir
|
|
65
|
+
* @param {object} options
|
|
66
|
+
* @param {function} callback
|
|
67
|
+
* @class Flo
|
|
68
|
+
* @private
|
|
69
|
+
*/
|
|
70
|
+
|
|
71
|
+
function Flo(dir, options, callback) {
|
|
72
|
+
this.log = logger(options.verbose, 'Flo');
|
|
73
|
+
this.dir = dir;
|
|
74
|
+
this.realpathdir = fs.realpathSync(dir);
|
|
75
|
+
this.resolver = callback;
|
|
76
|
+
this.server = new Server({
|
|
77
|
+
port: options.port,
|
|
78
|
+
host: options.host,
|
|
79
|
+
log: logger(options.verbose, 'Server')
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
this.watcher = new sane.Watcher(dir, {
|
|
83
|
+
glob: options.glob,
|
|
84
|
+
poll: options.useFilePolling,
|
|
85
|
+
pollingInterval: options.pollingInterval
|
|
86
|
+
});
|
|
87
|
+
this.watcher.on('change', this.onFileChange.bind(this));
|
|
88
|
+
this.watcher.on(
|
|
89
|
+
'ready',
|
|
90
|
+
this.emit.bind(this, 'ready')
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
Flo.prototype.__proto__ = EventEmitter.prototype;
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Handles file changes.
|
|
98
|
+
*
|
|
99
|
+
* @param {string} filepath
|
|
100
|
+
* @private
|
|
101
|
+
*/
|
|
102
|
+
|
|
103
|
+
Flo.prototype.onFileChange = function(filepath) {
|
|
104
|
+
this.log('File changed', filepath);
|
|
105
|
+
var server = this.server;
|
|
106
|
+
this.resolver(filepath, function(resource) {
|
|
107
|
+
resource = normalizeResource(resource);
|
|
108
|
+
server.broadcast(resource);
|
|
109
|
+
});
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Closes the server and the watcher.
|
|
114
|
+
*
|
|
115
|
+
* @public
|
|
116
|
+
*/
|
|
117
|
+
|
|
118
|
+
Flo.prototype.close = function() {
|
|
119
|
+
this.log('Shutting down flo');
|
|
120
|
+
this.watcher.close();
|
|
121
|
+
this.server.close();
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Creates a logger for a given module.
|
|
126
|
+
*
|
|
127
|
+
* @param {boolean} verbose
|
|
128
|
+
* @param {string} moduleName
|
|
129
|
+
* @private
|
|
130
|
+
*/
|
|
131
|
+
|
|
132
|
+
function logger(verbose, moduleName) {
|
|
133
|
+
var slice = [].slice;
|
|
134
|
+
return function() {
|
|
135
|
+
var args = slice.call(arguments);
|
|
136
|
+
args[0] = '[' + moduleName + '] ' + args[0];
|
|
137
|
+
if (verbose) {
|
|
138
|
+
console.log.apply(console, args);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Check if an object is of type RegExp.
|
|
145
|
+
*
|
|
146
|
+
* @param {*} o
|
|
147
|
+
* @return {boolean}
|
|
148
|
+
* @private
|
|
149
|
+
*/
|
|
150
|
+
|
|
151
|
+
function isRegExp(o) {
|
|
152
|
+
return o && typeof o === 'object' &&
|
|
153
|
+
Object.prototype.toString.call(o) === '[object RegExp]';
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Given a resource, enforce type checks, default params, and prepare for
|
|
158
|
+
* serialization.
|
|
159
|
+
*
|
|
160
|
+
* @param {*} o
|
|
161
|
+
* @return {boolean}
|
|
162
|
+
* @private
|
|
163
|
+
*/
|
|
164
|
+
|
|
165
|
+
function normalizeResource(resource) {
|
|
166
|
+
if (resource.reload) {
|
|
167
|
+
return resource;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
assert(resource.resourceURL, 'expecting resourceURL');
|
|
171
|
+
assert(resource.contents != null, 'expecting contents');
|
|
172
|
+
|
|
173
|
+
var ret = {};
|
|
174
|
+
|
|
175
|
+
ret.match = resource.match || 'indexOf';
|
|
176
|
+
ret.contents = resource.contents.toString();
|
|
177
|
+
ret.resourceURL = resource.resourceURL;
|
|
178
|
+
|
|
179
|
+
if (path.sep === '\\') {
|
|
180
|
+
ret.resourceURL = ret.resourceURL.replace(/\\/g, '/');
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
assert.ok(
|
|
184
|
+
isRegExp(ret.match) ||
|
|
185
|
+
['indexOf', 'equal'].indexOf(ret.match) > -1,
|
|
186
|
+
'resource.match must be of type function, or regexp, ' +
|
|
187
|
+
'or a string either "indexOf" or "equal'
|
|
188
|
+
);
|
|
189
|
+
|
|
190
|
+
if (isRegExp(ret.match)) {
|
|
191
|
+
var r = ret.match;
|
|
192
|
+
ret.match = {
|
|
193
|
+
type: 'regexp',
|
|
194
|
+
source: r.source,
|
|
195
|
+
global: r.global,
|
|
196
|
+
multiline: r.multiline,
|
|
197
|
+
ignoreCase: r.ignoreCase
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
return ret;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Default resolver callback that will simply read the file and pass back the
|
|
206
|
+
* filename relative to the watched dir as the url.
|
|
207
|
+
*
|
|
208
|
+
* @param {string} dir
|
|
209
|
+
* @return {function}
|
|
210
|
+
* @private
|
|
211
|
+
*/
|
|
212
|
+
|
|
213
|
+
function noBuildCallback(dir) {
|
|
214
|
+
return function(filepath, callback) {
|
|
215
|
+
fs.readFile(path.join(dir, filepath), function(err, data) {
|
|
216
|
+
// Todo better error handling.
|
|
217
|
+
if (err) {
|
|
218
|
+
throw err;
|
|
219
|
+
}
|
|
220
|
+
callback({
|
|
221
|
+
resourceURL: filepath,
|
|
222
|
+
contents: data.toString()
|
|
223
|
+
});
|
|
224
|
+
});
|
|
225
|
+
};
|
|
226
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2014, Facebook, Inc.
|
|
3
|
+
* All rights reserved.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the BSD-style license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree. An additional grant
|
|
7
|
+
* of patent rights can be found in the PATENTS file in the same directory.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
'use strict';
|
|
11
|
+
|
|
12
|
+
var http = require('http');
|
|
13
|
+
var WSS = require('websocket').server;
|
|
14
|
+
|
|
15
|
+
module.exports = Server;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Starts an http server with the given options and attaches a websocket server
|
|
19
|
+
* to it.
|
|
20
|
+
*
|
|
21
|
+
* @class Server
|
|
22
|
+
* @param {object} options
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
function Server(options) {
|
|
26
|
+
this.log = options.log || function() {};
|
|
27
|
+
this.httpServer = http.createServer(function(req, res) {
|
|
28
|
+
res.writeHead(404);
|
|
29
|
+
res.end();
|
|
30
|
+
});
|
|
31
|
+
this.httpServer.listen(options.port);
|
|
32
|
+
this.wsServer = new WSS({
|
|
33
|
+
httpServer: this.httpServer,
|
|
34
|
+
autoAcceptConnections: false
|
|
35
|
+
});
|
|
36
|
+
this.wsServer.on('request', this.onRequest.bind(this));
|
|
37
|
+
this.connections = [];
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Request handler.
|
|
42
|
+
*
|
|
43
|
+
* @param {object} req
|
|
44
|
+
* @private
|
|
45
|
+
*/
|
|
46
|
+
|
|
47
|
+
Server.prototype.onRequest = function(req) {
|
|
48
|
+
this.log('Client connected', req.socket.address());
|
|
49
|
+
var ws = req.accept();
|
|
50
|
+
this.connections.push(ws);
|
|
51
|
+
ws.on('close', this.onClose.bind(this, ws));
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Websocket connection close handler.
|
|
56
|
+
*
|
|
57
|
+
* @param {object} ws
|
|
58
|
+
* @private
|
|
59
|
+
*/
|
|
60
|
+
|
|
61
|
+
Server.prototype.onClose = function(ws) {
|
|
62
|
+
this.log('Client disconnected', ws.remoteAddress);
|
|
63
|
+
if (this.connections) {
|
|
64
|
+
this.connections.splice(this.connections.indexOf(ws), 1);
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Message handler.
|
|
70
|
+
*
|
|
71
|
+
* @param {object} msg
|
|
72
|
+
* @public
|
|
73
|
+
*/
|
|
74
|
+
|
|
75
|
+
Server.prototype.broadcast = function(msg) {
|
|
76
|
+
this.log('Broadcasting', msg);
|
|
77
|
+
msg = JSON.stringify(msg);
|
|
78
|
+
this.connections.forEach(function(ws) {
|
|
79
|
+
ws.send(msg);
|
|
80
|
+
});
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Close the server.
|
|
85
|
+
*
|
|
86
|
+
* @public
|
|
87
|
+
*/
|
|
88
|
+
|
|
89
|
+
Server.prototype.close = function() {
|
|
90
|
+
this.log('Shutting down WebSocket server');
|
|
91
|
+
this.connections = null;
|
|
92
|
+
this.wsServer.shutDown();
|
|
93
|
+
this.httpServer.close();
|
|
94
|
+
};
|
data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/README.md
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
sane
|
|
2
|
+
----
|
|
3
|
+
|
|
4
|
+
I've been driven to insanity by node filesystem watcher wrappers.
|
|
5
|
+
Sane aims to be fast, small, and reliable file system watcher. It does that by:
|
|
6
|
+
|
|
7
|
+
* Always use fs.watch (unless polling is forced) and sensibly workaround the various issues with it
|
|
8
|
+
* Sane is all JavaScript, no native components
|
|
9
|
+
* Stay away from polling because it's very slow and cpu intensive
|
|
10
|
+
* Support polling for environments like Vagrant shared directory where there are no native filesystem events
|
|
11
|
+
|
|
12
|
+
## Install
|
|
13
|
+
|
|
14
|
+
Requires node >= v0.10.0.
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
$ npm install sane
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## API
|
|
21
|
+
|
|
22
|
+
### sane(dir, globs, options)
|
|
23
|
+
|
|
24
|
+
Watches a directory and all it's descendant directorys for changes, deletions, and additions on files and directories.
|
|
25
|
+
Shortcut for `new sane.Watcher(dir, {glob: globs, ..options})`.
|
|
26
|
+
|
|
27
|
+
```js
|
|
28
|
+
var watcher = sane('path/to/dir', ['**/*.js, '**/*.css']);
|
|
29
|
+
watcher.on('ready', function () { console.log('ready') });
|
|
30
|
+
watcher.on('change', function (filepath) { console.log('file changed', filepath); });
|
|
31
|
+
watcher.on('add', function (filepath) { console.log('file added', filepath); });
|
|
32
|
+
watcher.on('delete', function (filepath) { console.log('file deleted', filepath); });
|
|
33
|
+
// close
|
|
34
|
+
watcher.close();
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
For `options` see `sane.Watcher`.
|
|
38
|
+
|
|
39
|
+
### sane.Watcher(dir, options)
|
|
40
|
+
|
|
41
|
+
options:
|
|
42
|
+
|
|
43
|
+
* `persistent`: boolean indicating that the process shouldn't die while we're watching files.
|
|
44
|
+
* `glob`: a single string glob pattern or an array of them.
|
|
45
|
+
* `poll`: puts the watcher in polling mode. Under the hood that means `fs.watchFile`.
|
|
46
|
+
* `interval`: indicates how often the files should be polled. (passed to `fs.watchFile`)
|
|
47
|
+
|
|
48
|
+
For the glob pattern documentation, see [minimatch](https://github.com/isaacs/minimatch).
|
|
49
|
+
|
|
50
|
+
### sane.Watcher#close
|
|
51
|
+
|
|
52
|
+
Stops watching.
|
|
53
|
+
|
|
54
|
+
### sane.Watcher events
|
|
55
|
+
|
|
56
|
+
Emits the following events:
|
|
57
|
+
|
|
58
|
+
All events are passed the file/dir path relative to the root directory
|
|
59
|
+
* `ready` when the program is ready to detect events in the directory
|
|
60
|
+
* `change` when a file changes
|
|
61
|
+
* `add` when a file or directory has been added
|
|
62
|
+
* `delete` when a file or directory has been deleted
|
|
63
|
+
|
|
64
|
+
## License
|
|
65
|
+
|
|
66
|
+
MIT
|
data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/index.js
ADDED
|
@@ -0,0 +1,437 @@
|
|
|
1
|
+
var fs = require('fs');
|
|
2
|
+
var path = require('path');
|
|
3
|
+
var watch = require('watch');
|
|
4
|
+
var walker = require('walker');
|
|
5
|
+
var platform = require('os').platform();
|
|
6
|
+
var minimatch = require('minimatch');
|
|
7
|
+
var EventEmitter = require('events').EventEmitter;
|
|
8
|
+
|
|
9
|
+
module.exports = sane;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Sugar for creating a watcher.
|
|
13
|
+
*
|
|
14
|
+
* @param {String} dir
|
|
15
|
+
* @param {Array<String>} glob
|
|
16
|
+
* @param {Object} opts
|
|
17
|
+
* @return {Watcher}
|
|
18
|
+
* @public
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
function sane(dir, glob, opts) {
|
|
22
|
+
opts = opts || {};
|
|
23
|
+
opts.glob = glob;
|
|
24
|
+
return new Watcher(dir, opts);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Export `Watcher` class.
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
sane.Watcher = Watcher;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Watches `dir`.
|
|
35
|
+
*
|
|
36
|
+
* @class Watcher
|
|
37
|
+
* @param String dir
|
|
38
|
+
* @param {Object} opts
|
|
39
|
+
* @public
|
|
40
|
+
*/
|
|
41
|
+
|
|
42
|
+
function Watcher(dir, opts) {
|
|
43
|
+
opts = opts || {};
|
|
44
|
+
this.persistent = opts.persistent != null
|
|
45
|
+
? opts.persistent
|
|
46
|
+
: true;
|
|
47
|
+
this.globs = opts.glob || [];
|
|
48
|
+
if (!Array.isArray(this.globs)) this.globs = [this.globs];
|
|
49
|
+
this.watched = Object.create(null);
|
|
50
|
+
this.changeTimers = Object.create(null);
|
|
51
|
+
this.dirRegistery = Object.create(null);
|
|
52
|
+
this.root = path.resolve(dir);
|
|
53
|
+
this.watchdir = this.watchdir.bind(this);
|
|
54
|
+
this.register = this.register.bind(this);
|
|
55
|
+
this.stopWatching = this.stopWatching.bind(this);
|
|
56
|
+
this.filter = this.filter.bind(this);
|
|
57
|
+
|
|
58
|
+
if (opts.poll) {
|
|
59
|
+
this.polling = true;
|
|
60
|
+
watch.createMonitor(
|
|
61
|
+
dir,
|
|
62
|
+
{ interval: opts.interval || DEFAULT_DELAY , filter: this.filter },
|
|
63
|
+
this.initPoller.bind(this)
|
|
64
|
+
);
|
|
65
|
+
} else {
|
|
66
|
+
this.watchdir(dir);
|
|
67
|
+
recReaddir(
|
|
68
|
+
dir,
|
|
69
|
+
this.watchdir,
|
|
70
|
+
this.register,
|
|
71
|
+
this.emit.bind(this, 'ready')
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
Watcher.prototype.__proto__ = EventEmitter.prototype;
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Checks a file relative path against the globs array.
|
|
80
|
+
*
|
|
81
|
+
* @param {string} relativePath
|
|
82
|
+
* @return {boolean}
|
|
83
|
+
* @private
|
|
84
|
+
*/
|
|
85
|
+
|
|
86
|
+
Watcher.prototype.isFileIncluded = function(relativePath) {
|
|
87
|
+
var globs = this.globs;
|
|
88
|
+
var matched;
|
|
89
|
+
if (globs.length) {
|
|
90
|
+
for (var i = 0; i < globs.length; i++) {
|
|
91
|
+
if (minimatch(relativePath, globs[i])) {
|
|
92
|
+
matched = true;
|
|
93
|
+
break;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
} else {
|
|
97
|
+
matched = true;
|
|
98
|
+
}
|
|
99
|
+
return matched;
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Register files that matches our globs to know what to type of event to
|
|
104
|
+
* emit in the future.
|
|
105
|
+
*
|
|
106
|
+
* Registery looks like the following:
|
|
107
|
+
*
|
|
108
|
+
* dirRegister => Map {
|
|
109
|
+
* dirpath => Map {
|
|
110
|
+
* filename => true
|
|
111
|
+
* }
|
|
112
|
+
* }
|
|
113
|
+
*
|
|
114
|
+
* @param {string} filepath
|
|
115
|
+
* @return {boolean} whether or not we have registered the file.
|
|
116
|
+
* @private
|
|
117
|
+
*/
|
|
118
|
+
|
|
119
|
+
Watcher.prototype.register = function(filepath) {
|
|
120
|
+
var relativePath = path.relative(this.root, filepath);
|
|
121
|
+
if (!this.isFileIncluded(relativePath)) {
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
var dir = path.dirname(filepath);
|
|
126
|
+
if (!this.dirRegistery[dir]) {
|
|
127
|
+
this.dirRegistery[dir] = Object.create(null);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
var filename = path.basename(filepath);
|
|
131
|
+
this.dirRegistery[dir][filename] = true;
|
|
132
|
+
|
|
133
|
+
return true;
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Removes a file from the registery.
|
|
138
|
+
*
|
|
139
|
+
* @param {string} filepath
|
|
140
|
+
* @private
|
|
141
|
+
*/
|
|
142
|
+
|
|
143
|
+
Watcher.prototype.unregister = function(filepath) {
|
|
144
|
+
var dir = path.dirname(filepath);
|
|
145
|
+
if (this.dirRegistery[dir]) {
|
|
146
|
+
var filename = path.basename(filepath);
|
|
147
|
+
delete this.dirRegistery[dir][filename];
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Removes a dir from the registery.
|
|
153
|
+
*
|
|
154
|
+
* @param {string} dirpath
|
|
155
|
+
* @private
|
|
156
|
+
*/
|
|
157
|
+
|
|
158
|
+
Watcher.prototype.unregisterDir = function(dirpath) {
|
|
159
|
+
if (this.dirRegistery[dirpath]) {
|
|
160
|
+
delete this.dirRegistery[dirpath];
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Checks if a file or directory exists in the registery.
|
|
166
|
+
*
|
|
167
|
+
* @param {string} fullpath
|
|
168
|
+
* @return {boolean}
|
|
169
|
+
* @private
|
|
170
|
+
*/
|
|
171
|
+
|
|
172
|
+
Watcher.prototype.registered = function(fullpath) {
|
|
173
|
+
var dir = path.dirname(fullpath);
|
|
174
|
+
return this.dirRegistery[fullpath] ||
|
|
175
|
+
this.dirRegistery[dir] && this.dirRegistery[dir][path.basename(fullpath)];
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Watch a directory.
|
|
180
|
+
*
|
|
181
|
+
* @param {string} dir
|
|
182
|
+
* @private
|
|
183
|
+
*/
|
|
184
|
+
|
|
185
|
+
Watcher.prototype.watchdir = function(dir) {
|
|
186
|
+
if (this.watched[dir]) return;
|
|
187
|
+
var watcher = fs.watch(
|
|
188
|
+
dir,
|
|
189
|
+
{ persistent: this.persistent },
|
|
190
|
+
this.normalizeChange.bind(this, dir)
|
|
191
|
+
);
|
|
192
|
+
this.watched[dir] = watcher;
|
|
193
|
+
|
|
194
|
+
// Workaround Windows node issue #4337.
|
|
195
|
+
if (platform === 'win32') {
|
|
196
|
+
watcher.on('error', function(error) {
|
|
197
|
+
if (error.code !== 'EPERM') throw error;
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
if (this.root !== dir) {
|
|
202
|
+
this.register(dir);
|
|
203
|
+
}
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* In polling mode stop watching files and directories, in normal mode, stop
|
|
208
|
+
* watching files.
|
|
209
|
+
*
|
|
210
|
+
* @param {string} filepath
|
|
211
|
+
* @private
|
|
212
|
+
*/
|
|
213
|
+
|
|
214
|
+
Watcher.prototype.stopWatching = function(filepath) {
|
|
215
|
+
if (this.polling) {
|
|
216
|
+
fs.unwatchFile(filepath);
|
|
217
|
+
} else if (this.watched[filepath]) {
|
|
218
|
+
this.watched[filepath].close();
|
|
219
|
+
delete this.watched[filepath];
|
|
220
|
+
}
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* End watching.
|
|
225
|
+
*
|
|
226
|
+
* @public
|
|
227
|
+
*/
|
|
228
|
+
|
|
229
|
+
Watcher.prototype.close = function() {
|
|
230
|
+
Object.keys(this.watched).forEach(this.stopWatching);
|
|
231
|
+
this.removeAllListeners();
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* On some platforms, as pointed out on the fs docs (most likely just win32)
|
|
236
|
+
* the file argument might be missing from the fs event. Try to detect what
|
|
237
|
+
* change by detecting if something was deleted or the most recent file change.
|
|
238
|
+
*
|
|
239
|
+
* @param {string} dir
|
|
240
|
+
* @param {string} event
|
|
241
|
+
* @param {string} file
|
|
242
|
+
* @public
|
|
243
|
+
*/
|
|
244
|
+
|
|
245
|
+
Watcher.prototype.detectChangedFile = function(dir, event, callback) {
|
|
246
|
+
var found = false;
|
|
247
|
+
var closest = {mtime: 0};
|
|
248
|
+
var c = 0;
|
|
249
|
+
Object.keys(this.dirRegistery[dir]).forEach(function(file, i, arr) {
|
|
250
|
+
fs.stat(path.join(dir, file), function(error, stat) {
|
|
251
|
+
if (found) return;
|
|
252
|
+
if (error) {
|
|
253
|
+
if (error.code === 'ENOENT') {
|
|
254
|
+
found = true;
|
|
255
|
+
callback(file);
|
|
256
|
+
} else {
|
|
257
|
+
this.emit('error', error);
|
|
258
|
+
}
|
|
259
|
+
} else {
|
|
260
|
+
if (stat.mtime > closest.mtime) {
|
|
261
|
+
stat.file = file;
|
|
262
|
+
closest = stat;
|
|
263
|
+
}
|
|
264
|
+
if (arr.length === ++c) {
|
|
265
|
+
callback(closest.file);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}.bind(this));
|
|
269
|
+
}, this);
|
|
270
|
+
};
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* Normalize fs events and pass it on to be processed.
|
|
274
|
+
*
|
|
275
|
+
* @param {string} dir
|
|
276
|
+
* @param {string} event
|
|
277
|
+
* @param {string} file
|
|
278
|
+
* @public
|
|
279
|
+
*/
|
|
280
|
+
|
|
281
|
+
Watcher.prototype.normalizeChange = function(dir, event, file) {
|
|
282
|
+
if (!file) {
|
|
283
|
+
this.detectChangedFile(dir, event, function(actualFile) {
|
|
284
|
+
if (actualFile) {
|
|
285
|
+
this.processChange(dir, event, actualFile);
|
|
286
|
+
}
|
|
287
|
+
}.bind(this));
|
|
288
|
+
} else {
|
|
289
|
+
this.processChange(dir, event, path.normalize(file));
|
|
290
|
+
}
|
|
291
|
+
};
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* Process changes.
|
|
295
|
+
*
|
|
296
|
+
* @param {string} dir
|
|
297
|
+
* @param {string} event
|
|
298
|
+
* @param {string} file
|
|
299
|
+
* @public
|
|
300
|
+
*/
|
|
301
|
+
|
|
302
|
+
Watcher.prototype.processChange = function(dir, event, file) {
|
|
303
|
+
var fullPath = path.join(dir, file);
|
|
304
|
+
var relativePath = path.join(path.relative(this.root, dir), file);
|
|
305
|
+
fs.stat(fullPath, function(error, stat) {
|
|
306
|
+
if (error && error.code !== 'ENOENT') {
|
|
307
|
+
this.emit('error', error);
|
|
308
|
+
} else if (!error && stat.isDirectory()) {
|
|
309
|
+
// win32 emits usless change events on dirs.
|
|
310
|
+
if (event !== 'change') {
|
|
311
|
+
this.watchdir(fullPath);
|
|
312
|
+
this.emitEvent(ADD_EVENT, relativePath);
|
|
313
|
+
}
|
|
314
|
+
} else {
|
|
315
|
+
var registered = this.registered(fullPath);
|
|
316
|
+
if (error && error.code === 'ENOENT') {
|
|
317
|
+
this.unregister(fullPath);
|
|
318
|
+
this.stopWatching(fullPath);
|
|
319
|
+
this.unregisterDir(fullPath);
|
|
320
|
+
if (registered) {
|
|
321
|
+
this.emitEvent(DELETE_EVENT, relativePath);
|
|
322
|
+
}
|
|
323
|
+
} else if (registered) {
|
|
324
|
+
this.emitEvent(CHANGE_EVENT, relativePath);
|
|
325
|
+
} else {
|
|
326
|
+
if (this.register(fullPath)) {
|
|
327
|
+
this.emitEvent(ADD_EVENT, relativePath);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
}.bind(this));
|
|
332
|
+
};
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* Triggers a 'change' event after debounding it to take care of duplicate
|
|
336
|
+
* events on os x.
|
|
337
|
+
*
|
|
338
|
+
* @private
|
|
339
|
+
*/
|
|
340
|
+
|
|
341
|
+
Watcher.prototype.emitEvent = function(type, file) {
|
|
342
|
+
var key = type + '-' + file;
|
|
343
|
+
clearTimeout(this.changeTimers[key]);
|
|
344
|
+
this.changeTimers[key] = setTimeout(function() {
|
|
345
|
+
delete this.changeTimers[key];
|
|
346
|
+
this.emit(type, file);
|
|
347
|
+
}.bind(this), DEFAULT_DELAY);
|
|
348
|
+
};
|
|
349
|
+
|
|
350
|
+
/**
|
|
351
|
+
* Initiate the polling file watcher with the event emitter passed from
|
|
352
|
+
* `watch.watchTree`.
|
|
353
|
+
*
|
|
354
|
+
* @param {EventEmitter} monitor
|
|
355
|
+
* @public
|
|
356
|
+
*/
|
|
357
|
+
|
|
358
|
+
Watcher.prototype.initPoller = function(monitor) {
|
|
359
|
+
this.watched = monitor.files;
|
|
360
|
+
monitor.on('changed', this.pollerEmit.bind(this, CHANGE_EVENT));
|
|
361
|
+
monitor.on('removed', this.pollerEmit.bind(this, DELETE_EVENT));
|
|
362
|
+
monitor.on('created', this.pollerEmit.bind(this, ADD_EVENT));
|
|
363
|
+
// 1 second wait because mtime is second-based.
|
|
364
|
+
setTimeout(this.emit.bind(this, 'ready'), 1000);
|
|
365
|
+
};
|
|
366
|
+
|
|
367
|
+
/**
|
|
368
|
+
* Transform and emit an event comming from the poller.
|
|
369
|
+
*
|
|
370
|
+
* @param {EventEmitter} monitor
|
|
371
|
+
* @public
|
|
372
|
+
*/
|
|
373
|
+
|
|
374
|
+
Watcher.prototype.pollerEmit = function(type, file) {
|
|
375
|
+
file = path.relative(this.root, file);
|
|
376
|
+
this.emit(type, file);
|
|
377
|
+
};
|
|
378
|
+
|
|
379
|
+
/**
|
|
380
|
+
* Given a fullpath of a file or directory check if we need to watch it.
|
|
381
|
+
*
|
|
382
|
+
* @param {string} filepath
|
|
383
|
+
* @param {object} stat
|
|
384
|
+
* @public
|
|
385
|
+
*/
|
|
386
|
+
|
|
387
|
+
Watcher.prototype.filter = function(filepath, stat) {
|
|
388
|
+
return stat.isDirectory() || this.isFileIncluded(
|
|
389
|
+
path.relative(this.root, filepath)
|
|
390
|
+
);
|
|
391
|
+
};
|
|
392
|
+
|
|
393
|
+
/**
|
|
394
|
+
* Constants
|
|
395
|
+
*/
|
|
396
|
+
|
|
397
|
+
var DEFAULT_DELAY = 100;
|
|
398
|
+
var CHANGE_EVENT = 'change';
|
|
399
|
+
var DELETE_EVENT = 'delete';
|
|
400
|
+
var ADD_EVENT = 'add';
|
|
401
|
+
|
|
402
|
+
/**
|
|
403
|
+
* Traverse a directory recursively calling `callback` on every directory.
|
|
404
|
+
*
|
|
405
|
+
* @param {string} dir
|
|
406
|
+
* @param {function} callback
|
|
407
|
+
* @param {function} endCallback
|
|
408
|
+
* @private
|
|
409
|
+
*/
|
|
410
|
+
|
|
411
|
+
function recReaddir(dir, dirCallback, fileCallback, endCallback) {
|
|
412
|
+
walker(dir)
|
|
413
|
+
.on('dir', normalizeProxy(dirCallback))
|
|
414
|
+
.on('file', normalizeProxy(fileCallback))
|
|
415
|
+
.on('end', function() {
|
|
416
|
+
if (platform === 'win32') {
|
|
417
|
+
setTimeout(endCallback, 1000);
|
|
418
|
+
} else {
|
|
419
|
+
endCallback();
|
|
420
|
+
}
|
|
421
|
+
});
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
/**
|
|
425
|
+
* Returns a callback that when called will normalize a path and call the
|
|
426
|
+
* original callback
|
|
427
|
+
*
|
|
428
|
+
* @param {function} callback
|
|
429
|
+
* @return {function}
|
|
430
|
+
* @private
|
|
431
|
+
*/
|
|
432
|
+
|
|
433
|
+
function normalizeProxy(callback) {
|
|
434
|
+
return function(filepath) {
|
|
435
|
+
return callback(path.normalize(filepath));
|
|
436
|
+
}
|
|
437
|
+
}
|