closure-util
Advanced tools
@@ -87,21 +87,19 @@ var EventEmitter = require('events').EventEmitter; | ||
var self = this; | ||
/** | ||
* The manager is closed. | ||
* @type {boolean} | ||
*/ | ||
this._closed = false; | ||
var paths = lib.concat(main); | ||
if (options.closure !== false) { | ||
var closure = getDependency('library', config.get('library_url')); | ||
paths = paths.concat([ | ||
path.join(closure, 'closure', 'goog', '**', '*.js'), | ||
path.join(closure, 'third_party', 'closure', 'goog', '**', '*.js') | ||
]); | ||
} | ||
process.nextTick(function() { | ||
self._processPaths(lib, function(err) { | ||
if (err) { | ||
return self._afterProcessPaths(err); | ||
} | ||
var more = main; | ||
if (options.closure) { | ||
var closure = getDependency('library', config.get('library_url')); | ||
more = more.concat([ | ||
path.join(closure, 'closure', 'goog', '**', '*.js'), | ||
path.join(closure, 'third_party', 'closure', 'goog', '**', '*.js') | ||
]); | ||
} | ||
self._afterProcessPaths(null, function() { | ||
self._processPaths(more, self._afterProcessPaths.bind(self)); | ||
}); | ||
}, true); | ||
}); | ||
this._processPaths(paths); | ||
}.bind(this)); | ||
@@ -113,22 +111,2 @@ }; | ||
/** | ||
* Called after processing all paths. | ||
* @param {Error} err Any error during processing. | ||
* @param {function=} opt_more Additional function to call. | ||
*/ | ||
Manager.prototype._afterProcessPaths = function(err, opt_more) { | ||
if (err) { | ||
log.verbose('manager', err); | ||
this.emit('error', err); | ||
} else { | ||
if (opt_more) { | ||
opt_more(); | ||
} else { | ||
this._startWatch(); | ||
this.emit('ready'); | ||
} | ||
} | ||
}; | ||
/** | ||
* Add a script to the manager. | ||
@@ -257,6 +235,4 @@ * @param {Script} script Script to add. | ||
* @param {Array.<string>} paths Paths patterns to process. | ||
* @param {function(Error)} done Callback. | ||
* @param {boolean=} opt_lib Library scripts. | ||
*/ | ||
Manager.prototype._processPaths = function(paths, done, opt_lib) { | ||
Manager.prototype._processPaths = function(paths) { | ||
var self = this; | ||
@@ -282,3 +258,11 @@ async.waterfall([ | ||
} | ||
], done); | ||
], function(err) { | ||
if (err) { | ||
log.verbose('manager', err); | ||
self.emit('error', err); | ||
} else { | ||
self.emit('beforewatch'); | ||
self._startWatch(); | ||
} | ||
}); | ||
}; | ||
@@ -291,2 +275,5 @@ | ||
Manager.prototype._startWatch = function() { | ||
if (this._closed) { | ||
return; | ||
} | ||
var paths = this._lib.concat(this._main); | ||
@@ -303,2 +290,3 @@ var gaze = new Gaze(paths); | ||
this._gaze = gaze; | ||
this.emit('ready'); | ||
}; | ||
@@ -349,4 +337,8 @@ | ||
this._gaze.close(); | ||
delete this._gaze; | ||
} | ||
this.emit('close'); | ||
if (!this._closed) { | ||
this._closed = true; | ||
this.emit('close'); | ||
} | ||
}; |
@@ -142,6 +142,6 @@ var fs = require('fs'); | ||
var pathname = parts.pathname; | ||
var match = this.useLoader_(req); | ||
var match = this._useLoader(req); | ||
if (match) { | ||
// managed script | ||
var name = this.getPath_(req, match); | ||
var name = this._getPath(req, match); | ||
if (!name) { | ||
@@ -178,3 +178,3 @@ // request for loader | ||
.root(this._root) | ||
.on('error', this.handleStaticError_.bind(this, req, res)) | ||
.on('error', this._handleStaticError.bind(this, req, res)) | ||
.pipe(res); | ||
@@ -190,5 +190,4 @@ } | ||
* @return {boolean|string} This request should be handled by the loader. | ||
* @private | ||
*/ | ||
Server.prototype.useLoader_ = function(req) { | ||
Server.prototype._useLoader = function(req) { | ||
var match = false; | ||
@@ -210,5 +209,4 @@ if (typeof this._loader === 'string') { | ||
* @return {string} Script path. | ||
* @private | ||
*/ | ||
Server.prototype.getPath_ = function(req, loader) { | ||
Server.prototype._getPath = function(req, loader) { | ||
return url.parse(req.url).pathname.substring(loader.length); | ||
@@ -282,5 +280,4 @@ }; | ||
* @param {Error} err Error. | ||
* @private | ||
*/ | ||
Server.prototype.handleStaticError_ = function(req, res, err) { | ||
Server.prototype._handleStaticError = function(req, res, err) { | ||
var self = this; | ||
@@ -287,0 +284,0 @@ if (err.status === 404 && req.url.slice(-1) === '/') { |
{ | ||
"name": "closure-util", | ||
"version": "0.9.0", | ||
"version": "0.10.0", | ||
"description": "Utilities for Closure Library based projects.", | ||
"main": "index.js", | ||
"main": "lib/index.js", | ||
"homepage": "https://github.com/openlayers/closure-util", | ||
@@ -51,4 +51,4 @@ "author": { | ||
"test": "grunt test", | ||
"start": "grunt watch" | ||
"start": "grunt test watch" | ||
} | ||
} |
@@ -5,36 +5,34 @@ # Closure Util | ||
## Currently | ||
## API | ||
See the [tests](test/spec) for details about what works. Currently, the package exports a `Manager` for resolving script dependencies and a `Server` for providing a development server. | ||
### <a id="manager">`new Manager(config)`</a> | ||
Create a manager for dealing with script dependencies. | ||
A script manager parses scripts for dependencies and watches those scripts for changes, updating dependencies as scripts are added, modified, or deleted. A manager is used in conjunction with a [server](#server) for providing a debug loader during development. | ||
```js | ||
var Manager = require('closure-util').Manager; | ||
* **config.lib** - `string|Array.<string>` A list of [path patterns](https://github.com/isaacs/minimatch) for your library scripts (e.g. `'lib/**/*.js'`). Note that path delimters in these patterns should always be forward slashes (even on Windows). | ||
* **config.main** - `string|Array.<string>` Patterns for your main script(s). | ||
var manager = new Manager({ | ||
paths: ['path/to/one/lib/**/*.js', 'path/to/another/lib/**/*.js', 'main.js'] | ||
}); | ||
manager.on('ready', function() { | ||
var dependencies = manager.getDependencies('main.js'); | ||
// now you've got a list of scripts in dependency order | ||
}); | ||
``` | ||
The manager is an [event emitter](http://nodejs.org/api/events.html#events_class_events_eventemitter) that emits the following events: | ||
* **ready** - The manager is ready (all scripts parsed and dependencies resolved). | ||
* **error** - Listeners will be called with an `Error` instance representing what went wrong. | ||
### <a id="server">`new Server(config)`</a> | ||
Create a development server providing a script loader and static assets. | ||
* **config.manager** - `Manager` A script manager. | ||
* **config.root** - `string` Path to root directory for scripts and static assets (default is `process.cwd()`). | ||
* **config.loader** - `string` URL path for script loader. | ||
```js | ||
var Manager = require('closure-util').Manager; | ||
var Server = require('closure-util').Server; | ||
var closure = require('closure-util'); | ||
var manager = new Manager({ | ||
closure: true, | ||
paths: [ | ||
'path/to/app/src/**/*.js', | ||
'path/to/app/examples/*.js' | ||
] | ||
var manager = new closure.Manager({ | ||
lib: ['path/to/app/src/**/*.js'] | ||
main: 'path/to/app/examples/*.js' | ||
}); | ||
manager.on('error', function(e) {throw e}); | ||
manager.on('ready', function() { | ||
var server = new Server({ | ||
var server = new closure.Server({ | ||
manager: manager, | ||
@@ -52,2 +50,16 @@ root: 'path/to/app', // static resources will be served from here | ||
### <a id="getdependencies">`getDependencies(config, callback)`</a> | ||
The `getDependencies` function generates a list of script paths in dependency order. | ||
* **config** - `Object` A configuration object of the same form as the [manager config](#manager-config). | ||
* **callback** - `function(Error, Array.<string>)` Called with a list of script paths in dependency order (or a parsing error). | ||
### <a id="compile">`compile(options, callback)`</a> | ||
The `compile` function drives the Closure Compiler. | ||
* **options** - `Object` [Options](compiler-options.txt) for the compiler (without the `--` prefix). E.g. the `--output_wrapper` option could be specified with `{output_wrapper: '(function(){%output%})();'}`. For options that can be specified multiple times, provide an array of values (e.g. `{js: ['one.js', 'two.js']}`). For options that are flags (no value), provide a boolean (e.g. `{use_types_for_optimization: true}`). | ||
* **callback** - `function(Error, string)` Called with the compiler output (or any compilation error). | ||
## Configuration | ||
@@ -54,0 +66,0 @@ |
@@ -18,3 +18,3 @@ var path = require('path'); | ||
it('creates a Manager instance', function() { | ||
var manager = new Manager(); | ||
var manager = new Manager({closure: false}); | ||
@@ -25,2 +25,69 @@ assert.instanceOf(manager, Manager); | ||
describe('"ready" event', function() { | ||
it('is fired after scripts are parsed', function(done) { | ||
var manager = new Manager({ | ||
closure: false, | ||
cwd: fixtures, | ||
lib: 'dependencies/**/*.js' | ||
}); | ||
manager.on('error', done); | ||
manager.on('ready', function() { | ||
done(); | ||
}); | ||
}); | ||
}); | ||
describe('"error" event', function() { | ||
it('is fired on initial parsing error', function(done) { | ||
var manager = new Manager({ | ||
closure: false, | ||
cwd: fixtures, | ||
lib: 'errors/**/*.js' | ||
}); | ||
manager.on('error', function(err) { | ||
assert.instanceOf(err, SyntaxError); | ||
done(); | ||
}); | ||
manager.on('ready', function() { | ||
done(new Error('Expected error event')); | ||
}); | ||
}); | ||
}); | ||
describe('"beforewatch" event', function() { | ||
it('is fired before ready event', function(done) { | ||
var manager = new Manager({ | ||
closure: false, | ||
cwd: fixtures, | ||
lib: 'dependencies/**/*.js' | ||
}); | ||
var before = false; | ||
manager.on('error', done); | ||
manager.on('beforewatch', function() { | ||
before = true; | ||
}); | ||
manager.on('ready', function() { | ||
assert.isTrue(before); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
describe('"close" event', function() { | ||
it('is fired after calling close', function(done) { | ||
var manager = new Manager({ | ||
closure: false, | ||
cwd: fixtures, | ||
lib: 'dependencies/**/*.js' | ||
}); | ||
manager.on('error', done); | ||
manager.on('beforewatch', function() { | ||
manager.close(); | ||
}); | ||
manager.on('close', function() { | ||
done(); | ||
}); | ||
}); | ||
}); | ||
describe('#getDependencies()', function() { | ||
@@ -30,2 +97,3 @@ | ||
var manager = new Manager({ | ||
closure: false, | ||
cwd: fixtures, | ||
@@ -48,2 +116,3 @@ lib: 'dependencies/**/*.js' | ||
var manager = new Manager({ | ||
closure: false, | ||
cwd: fixtures, | ||
@@ -68,2 +137,3 @@ lib: 'dependencies-main/+(lib|goog)/**/*.js', | ||
var manager = new Manager({ | ||
closure: false, | ||
cwd: fixtures, | ||
@@ -88,2 +158,3 @@ lib: 'dependencies-main/+(lib|goog)/**/*.js', | ||
var manager = new Manager({ | ||
closure: false, | ||
cwd: fixtures, | ||
@@ -112,2 +183,3 @@ lib: 'dependencies-main/+(lib|goog)/**/*.js', | ||
var manager = new Manager({ | ||
closure: false, | ||
cwd: fixtures, | ||
@@ -114,0 +186,0 @@ lib: 'dependencies-extra/**/*.js' |
77557
7.53%45
4.65%1739
9.1%94
14.63%3
50%