/**
 * Provides a Query constructor with chainable capability. For example:
 * var Query = require("./query").Query;
 * query = Query();
 * query.executor = function(query){
 *    require("./js-array").query(query, params, data); // if we want to operate on an array
 * };
 * query.eq("a", 3).le("b", 4).forEach(function(object){
 *   // for each object that matches the query 
 * });  
 */
var parseQuery = require("./parser").parseQuery;

try{
	var when = require("promised-io/promise").when;
}catch(e){
	when = function(value, callback){callback(value)};
}

exports.knownOperators = ["and", "or", "eq", "ne", "le", "lt", "gt", "ge", "sort", "in", "select", "contains"];
exports.arrayMethods = ["forEach", "reduce", "map", "filter", "indexOf", "some", "every"];
exports.Query = function(seed, params){
	if (typeof seed === 'string')
		return parseQuery(seed, params);
	var q = new Query();
	if (seed && seed.name && seed.args)
		q.name = seed.name, q.args = seed.args;
	return q;
};
function Query(name){
	this.name = name || "and";
	this.args = [];
}
exports.Query.prototype = Query.prototype;
Query.prototype.toString = function(){
	return this.name === "and" ?
		this.args.map(queryToString).join("&") :
		queryToString(this);
};
exports.updateQueryMethods = function(){
	exports.knownOperators.forEach(function(name){
		Query.prototype[name] = function(){
			var newQuery = new Query();
			newQuery.executor = this.executor;
			var newTerm = new Query(name);
			newTerm.args = Array.prototype.slice.call(arguments);
			newQuery.args = this.args.concat([newTerm]);
			return newQuery;
		};
	});
	exports.arrayMethods.forEach(function(name){
		Query.prototype[name] = function(){
			var args = arguments;
			return when(this.executor(this), function(results){
				return results[name].apply(results, args);
			});
		};
	});

};
exports.updateQueryMethods();

@@ -387,57 +387,8 @@
 %0A */
-%0Avar parseQuery = require(%22./parser%22).parseQuery;
 %0A%0Atr
@@ -614,16 +614,153 @@
 ontains%22
+,%22values%22,%22aggregate%22,%22distinct%22,%22limit%22,%22recurse%22%5D;%0Aexports.knownScalarOperators = %5B%22mean%22, %22sum%22, %22min%22, %22max%22, %22count%22, %22first%22, %22one%22
 %5D;%0Aexpor
@@ -1066,16 +1066,17 @@
 n q;%0A%7D;%0A
+%0A
 function
@@ -1313,24 +1313,490 @@
 g(this);%0A%7D;%0A
+%0Afunction queryToString(part) %7B%0A    if (part instanceof Array) %7B%0A        return part.map(function(arg) %7B%0A            return queryToString(arg);%0A        %7D).join(%22,%22);%0A    %7D%0A    if (part && part.name && part.args) %7B%0A        return %5B%0A            part.name,%0A            %22(%22,%0A            part.args.map(function(arg) %7B%0A                return queryToString(arg);%0A            %7D).join(%22,%22),%0A            %22)%22%0A        %5D.join(%22%22);%0A    %7D%0A    return exports.encodeValue(part);%0A%7D;%0A%0A
 exports.upda
@@ -2148,16 +2148,365 @@
 %7D;%0A%09%7D);%0A
+%09exports.knownScalarOperators.forEach(function(name)%7B%0A%09%09Query.prototype%5Bname%5D = function()%7B%0A%09%09%09var newQuery = new Query();%0A%09%09%09newQuery.executor = this.executor;%0A%09%09%09var newTerm = new Query(name);%0A%09%09%09newTerm.args = Array.prototype.slice.call(arguments);%0A%09%09%09newQuery.args = this.args.concat(%5BnewTerm%5D);%0A%09%09%09return newQuery.executor(newQuery);%0A%09%09%7D;%0A%09%7D);%0A
 %09exports
@@ -2729,16 +2729,17 @@
 %7D);%0A%0A%7D;%0A
+%0A
 exports.
@@ -2756,12 +2756,61 @@
 yMethods();%0A
+var parseQuery = require(%22./parser%22).parseQuery;%0A

Support scalar operators