)]}'
{"version":3,"sources":["mongo/local_collection_driver.js","mongo/collection.js"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,qC;AACA,kB;AACA,8B;AACA,E;;AAEA,qD;AACA,6B;AACA,kD;AACA,2B;AACA,E;;AAEA,2C;AACA,+B;AACA,oB;AACA,c;AACA,iC;AACA,iB;AACA,4D;AACA,K;AACA,2C;AACA,4C;AACA,6E;AACA,6C;AACA,oE;AACA,G;AACA,G;;AAEA,Y;AACA,kD;;;;;;;;;;;;;;;;;;;AC5BA,sE;AACA,iE;;AAEA,G;AACA,+C;AACA,a;AACA,G;AACA,W;;AAEA,G;AACA,wC;AACA,kB;AACA,2B;AACA,S;AACA,qH;AACA,4B;AACA,oV;AACA,wI;;AAEA,iC;AACA,qE;;AAEA,kD;AACA,uX;AACA,G;AACA,6C;AACA,kB;AACA,2C;AACA,iE;;AAEA,iC;AACA,6E;AACA,6E;AACA,oE;AACA,gB;AACA,G;;AAEA,kD;AACA,oB;AACA,yE;AACA,G;;AAEA,mC;AACA,yE;AACA,sF;AACA,e;AACA,4B;AACA,oC;AACA,G;AACA,uE;AACA,0D;AACA,yC;AACA,G;AACA,sB;AACA,0B;AACA,2B;AACA,oB;AACA,uB;AACA,8B;AACA,c;;AAEA,iC;AACA,e;AACA,mC;AACA,wE;AACA,mD;AACA,M;AACA,U;AACA,gB;AACA,U;AACA,mC;AACA,wE;AACA,sB;AACA,M;AACA,U;AACA,G;;AAEA,qE;;AAEA,4C;AACA,yD;AACA,4B;AACA,8B;AACA,0C;AACA,2B;AACA,yC;AACA,M;AACA,qC;;AAEA,yB;AACA,6E;AACA,4E;AACA,mE;AACA,wB;AACA,qD;AACA,gD;AACA,uD;AACA,uE;AACA,Y;AACA,8C;AACA,K;AACA,G;;AAEA,kE;AACA,oB;AACA,iC;;AAEA,2D;AACA,6D;AACA,qE;AACA,oC;AACA,mD;AACA,+E;AACA,mC;AACA,Q;AACA,+E;AACA,wE;AACA,0E;AACA,0E;AACA,+E;AACA,6E;AACA,yC;AACA,gD;AACA,2E;AACA,0E;AACA,gF;AACA,gF;AACA,gB;AACA,mC;AACA,4C;;AAEA,kB;AACA,sC;AACA,Q;;AAEA,yB;AACA,4E;AACA,8B;AACA,uD;AACA,oD;;AAEA,+E;AACA,2E;AACA,sC;AACA,oC;AACA,oC;AACA,yB;AACA,oB;AACA,+C;AACA,4B;AACA,6C;AACA,kB;AACA,kD;AACA,sD;AACA,W;AACA,iB;AACA,yC;AACA,oB;AACA,0F;AACA,W;AACA,wE;AACA,2C;AACA,mB;AACA,uF;AACA,2C;AACA,2C;AACA,mB;AACA,qE;AACA,uC;AACA,8B;AACA,sD;AACA,wC;AACA,qC;AACA,uC;AACA,yC;AACA,sB;AACA,mC;AACA,qC;AACA,2C;AACA,e;AACA,e;AACA,uD;AACA,W;AACA,gB;AACA,wE;AACA,S;;AAEA,Q;;AAEA,iD;AACA,8B;AACA,2C;AACA,Q;;AAEA,+E;AACA,+B;AACA,kC;AACA,yC;AACA,Q;AACA,sC;AACA,oD;AACA,O;AACA,O;;AAEA,Y;AACA,4E;AACA,G;;AAEA,gC;;AAEA,gB;AACA,6E;AACA,oC;AACA,gD;AACA,yB;AACA,wB;AACA,G;AACA,E;;AAEA,G;AACA,uB;AACA,G;;;AAGA,sC;;AAEA,qC;AACA,yB;AACA,gB;AACA,Q;AACA,qB;AACA,I;;AAEA,oC;AACA,oB;AACA,0B;AACA,4C;AACA,Y;AACA,2D;AACA,+D;AACA,oE;AACA,8D;AACA,4D;AACA,U;;AAEA,uB;AACA,kC;AACA,kB;AACA,K;AACA,I;;AAEA,K;AACA,yE;AACA,oB;AACA,iB;AACA,+B;AACA,c;AACA,+E;AACA,8B;AACA,iF;AACA,4E;AACA,sE;AACA,2F;AACA,uG;AACA,4J;AACA,4B;AACA,K;AACA,4C;AACA,8D;AACA,8D;AACA,6C;AACA,oB;AACA,wC;AACA,iE;AACA,iE;AACA,I;;AAEA,K;AACA,sG;AACA,oB;AACA,oB;AACA,+B;AACA,c;AACA,+E;AACA,8B;AACA,iF;AACA,4E;AACA,2F;AACA,mG;AACA,2J;AACA,sB;AACA,K;AACA,+C;AACA,oB;AACA,wC;AACA,oE;AACA,oE;AACA,G;;AAEA,G;;AAEA,sE;AACA,6C;AACA,kC;AACA,wC;AACA,M;AACA,oC;AACA,0C;AACA,M;AACA,4B;AACA,kC;AACA,K;AACA,K;;AAEA,6E;AACA,kE;;AAEA,wD;AACA,kD;AACA,E;;AAEA,0E;AACA,+E;AACA,wE;AACA,sB;AACA,yD;AACA,mC;AACA,8C;AACA,+B;;AAEA,0D;AACA,2B;AACA,8B;;AAEA,e;AACA,0C;AACA,sE;AACA,kC;AACA,qD;AACA,yD;AACA,4D;AACA,iE;AACA,yC;AACA,uC;AACA,2C;AACA,K;AACA,sD;AACA,gD;AACA,4C;AACA,oD;AACA,S;AACA,Y;AACA,uB;AACA,K;AACA,K;AACA,a;AACA,E;;AAEA,qE;AACA,W;AACA,sD;AACA,uC;;AAEA,yC;AACA,wB;AACA,sE;AACA,oE;AACA,wB;AACA,wB;AACA,uB;AACA,wB;AACA,mB;AACA,qC;;AAEA,kB;AACA,E;;AAEA,8D;AACA,gE;AACA,2B;AACA,mE;AACA,6B;AACA,G;AACA,E;;AAEA,gE;AACA,0E;AACA,0E;AACA,gE;AACA,8E;AACA,iC;AACA,E;AACA,qE;AACA,6D;AACA,qE;AACA,oE;AACA,gF;AACA,gF;AACA,8E;AACA,gE;AACA,E;AACA,0D;AACA,6D;AACA,uB;AACA,E;AACA,gE;AACA,qE;AACA,iB;AACA,E;AACA,mE;AACA,oE;AACA,8D;AACA,kE;AACA,O;;AAEA,G;AACA,yE;AACA,kB;AACA,kB;AACA,6B;AACA,Y;AACA,iI;AACA,iJ;AACA,G;;AAEA,G;AACA,qG;AACA,kB;AACA,iB;AACA,6B;AACA,Y;AACA,sE;AACA,wE;AACA,4B;AACA,0I;AACA,gG;AACA,0K;AACA,G;;AAEA,G;AACA,gD;AACA,kB;AACA,iB;AACA,6B;AACA,Y;AACA,sE;AACA,mG;AACA,G;;AAEA,wD;AACA,iE;AACA,oB;AACA,oC;AACA,iB;AACA,iB;AACA,Y;;AAEA,8E;AACA,gD;AACA,sB;AACA,+C;AACA,sD;AACA,4B;AACA,K;;AAEA,4B;AACA,uB;AACA,uD;AACA,qD;AACA,sC;AACA,6B;AACA,+B;AACA,uD;AACA,qD;AACA,sG;AACA,c;AACA,8B;AACA,6E;AACA,4E;AACA,qC;AACA,qE;AACA,uD;AACA,2B;AACA,+B;AACA,W;AACA,S;AACA,yB;AACA,qD;AACA,S;AACA,O;AACA,Y;AACA,2D;;AAEA,8B;AACA,2E;AACA,+E;AACA,2E;AACA,wB;AACA,uD;AACA,yE;AACA,6E;AACA,mC;AACA,wD;AACA,mE;AACA,uE;AACA,qC;AACA,mD;AACA,W;AACA,S;AACA,O;AACA,K;;AAEA,uE;AACA,8D;AACA,mE;AACA,8B;AACA,kC;AACA,4B;AACA,S;AACA,wB;AACA,c;AACA,sB;AACA,O;AACA,M;;AAEA,wB;AACA,mB;AACA,kD;AACA,kF;AACA,Q;AACA,K;;AAEA,gC;AACA,iE;AACA,mE;AACA,mB;;AAEA,mD;AACA,oE;;AAEA,yE;AACA,sE;AACA,qE;AACA,kE;AACA,uE;AACA,gB;AACA,+E;AACA,+E;AACA,gC;AACA,0C;AACA,kB;AACA,0E;AACA,U;AACA,O;;AAEA,sD;AACA,8E;AACA,6E;AACA,4E;AACA,8C;AACA,O;;AAEA,kD;AACA,mG;AACA,Q;;AAEA,Y;AACA,gE;AACA,qC;AACA,iC;AACA,W;AACA,6E;AACA,6E;AACA,gE;AACA,4E;AACA,8D;AACA,mB;AACA,uB;AACA,sB;AACA,sB;AACA,S;AACA,gB;AACA,O;AACA,K;;AAEA,oE;AACA,+E;AACA,uD;AACA,e;AACA,I;AACA,G;;AAEA,G;AACA,4Q;AACA,kB;AACA,sE;AACA,wE;AACA,4B;AACA,0I;AACA,0K;AACA,G;AACA,iE;AACA,mE;AACA,kB;AACA,oD;AACA,uB;AACA,iB;AACA,G;AACA,wC;AACA,2E;AACA,wB;AACA,E;;AAEA,6E;AACA,oC;AACA,qE;AACA,kB;AACA,qC;AACA,wE;AACA,gD;AACA,E;AACA,0D;AACA,kB;AACA,mC;AACA,sE;AACA,qC;AACA,E;AACA,0D;AACA,kB;AACA,uC;AACA,2E;AACA,oC;AACA,E;AACA,wF;AACA,kB;AACA,gD;AACA,mF;AACA,mE;AACA,E;;AAEA,wD;AACA,kB;AACA,yC;AACA,yE;AACA,G;AACA,0C;AACA,E;;AAEA,sD;AACA,kB;AACA,wD;AACA,uE;AACA,G;AACA,+B;AACA,E;;;AAGA,G;AACA,qK;AACA,kB;AACA,S;AACA,uG;AACA,G;AACA,2C;;AAEA,G;AACA,0G;AACA,S;AACA,uB;AACA,G;AACA,sC;;AAEA,G;AACA,uB;AACA,G;AACA,uC;;AAEA,G;AACA,uB;AACA,G;AACA,2C;;AAEA,G;AACA,sC;AACA,G;;AAEA,uE;AACA,gB;AACA,E;AACA,yC;AACA,mD;AACA,E;AACA,4D;AACA,wD;AACA,qE;AACA,E;AACA,0C;AACA,uD;AACA,E;AACA,wB;AACA,uE;AACA,0D;AACA,E;AACA,kE;AACA,wB;AACA,qE;AACA,oE;AACA,uB;AACA,2E;AACA,6E;AACA,sC;AACA,E;AACA,8E;AACA,6E;AACA,mC;;AAEA,c;AACA,qD;AACA,oB;AACA,0E;AACA,4C;AACA,uC;AACA,+D;AACA,O;;AAEA,oB;AACA,4B;;AAEA,4D;AACA,0B;AACA,mD;AACA,yF;AACA,S;;AAEA,6E;AACA,uE;AACA,sB;AACA,8C;AACA,wE;AACA,gB;AACA,kE;AACA,+B;AACA,S;;AAEA,gE;AACA,O;AACA,O;;AAEA,sE;AACA,0E;AACA,6B;AACA,4D;AACA,+D;AACA,8E;AACA,O;AACA,uC;AACA,K;AACA,I;;AAEA,K;AACA,mH;AACA,kB;AACA,4B;AACA,2J;AACA,uL;AACA,4I;AACA,K;AACA,wD;AACA,8C;AACA,I;;AAEA,K;AACA,qC;AACA,kB;AACA,4B;AACA,0M;AACA,uL;AACA,4I;AACA,K;AACA,uD;AACA,6C;AACA,I;AACA,K;;;AAGA,gE;AACA,kB;;AAEA,qE;AACA,iE;AACA,2B;;AAEA,8E;AACA,4E;AACA,+E;AACA,uB;AACA,6B;;AAEA,sB;AACA,kC;AACA,kC;AACA,kC;AACA,oE;AACA,c;AACA,yB;AACA,I;;AAEA,kB;AACA,mC;;AAEA,gE;AACA,gC;AACA,wC;;AAEA,qB;AACA,yB;AACA,e;;AAEA,8D;AACA,uD;AACA,6E;AACA,sC;AACA,wC;AACA,a;AACA,6E;AACA,gF;AACA,+E;AACA,uE;AACA,2E;AACA,yE;AACA,Y;AACA,4E;AACA,yE;AACA,qE;AACA,qD;AACA,iC;AACA,8D;AACA,4C;AACA,W;;AAEA,kC;AACA,2E;AACA,iC;AACA,qC;AACA,wC;AACA,kD;AACA,sC;AACA,W;;AAEA,wE;;AAEA,kF;AACA,iC;AACA,kC;AACA,oD;;AAEA,iC;AACA,6D;AACA,8D;AACA,qC;AACA,8E;AACA,6D;AACA,a;;AAEA,qC;AACA,kF;AACA,sC;AACA,0D;AACA,+D;AACA,0C;AACA,qC;AACA,wC;AACA,6E;AACA,8E;AACA,+E;AACA,4E;AACA,2E;AACA,6E;AACA,uE;AACA,+E;AACA,+E;AACA,4E;AACA,+C;AACA,0E;AACA,kB;AACA,+E;AACA,4B;AACA,yD;AACA,W;AACA,qB;AACA,uE;AACA,sD;AACA,kB;AACA,oB;AACA,W;AACA,S;AACA,Q;AACA,O;AACA,iE;AACA,sD;AACA,oE;AACA,gC;AACA,8D;AACA,kC;AACA,G;AACA,E;;;AAGA,6D;AACA,kB;;AAEA,yC;AACA,iB;AACA,uE;AACA,Y;AACA,6C;AACA,oE;AACA,oC;AACA,K;AACA,G;AACA,E;;AAEA,sD;AACA,kB;AACA,mC;AACA,8B;AACA,wB;AACA,E;;AAEA,4D;AACA,gB;AACA,4B;AACA,2B;AACA,gF;AACA,2E;AACA,+E;AACA,mD;AACA,yD;AACA,+B;AACA,4B;AACA,K;AACA,mC;AACA,G;AACA,a;AACA,E;;AAEA,oE;AACA,uE;AACA,kB;;AAEA,0B;AACA,wC;AACA,+D;AACA,yE;AACA,O;AACA,iD;AACA,G;AACA,wE;AACA,gE;AACA,0E;AACA,O;AACA,iD;AACA,G;;AAEA,0E;AACA,+B;AACA,2B;AACA,0B;;AAEA,sD;AACA,E;;AAEA,8C;AACA,0B;AACA,oC;AACA,a;AACA,E;;AAEA,uE;AACA,mE;AACA,kE;AACA,2C;AACA,uD;AACA,yC;AACA,kB;;AAEA,yB;;AAEA,mC;;AAEA,8D;AACA,iE;;AAEA,2E;AACA,W;AACA,qB;AACA,+D;AACA,kE;;AAEA,iF;AACA,mF;AACA,qB;;AAEA,4B;AACA,kB;AACA,2B;AACA,gD;AACA,G;AACA,yC;AACA,+B;AACA,kD;AACA,uD;AACA,6B;AACA,2F;AACA,Y;AACA,+C;AACA,6D;AACA,yB;AACA,sC;AACA,yD;;AAEA,mD;AACA,uC;AACA,6B;AACA,S;AACA,K;AACA,K;;AAEA,sC;AACA,yC;AACA,4B;AACA,wD;AACA,wC;AACA,O;AACA,G;;AAEA,4D;AACA,+B;AACA,a;;AAEA,0B;AACA,wC;AACA,+D;AACA,oD;AACA,4B;AACA,kC;AACA,4B;AACA,8B;AACA,O;AACA,iD;AACA,G;AACA,wE;AACA,gE;AACA,oD;AACA,6B;AACA,mC;AACA,6B;AACA,+B;AACA,O;AACA,iD;AACA,G;;AAEA,gC;;AAEA,4E;AACA,6E;AACA,+E;AACA,4B;;AAEA,sC;AACA,kD;AACA,E;;AAEA,iE;AACA,8D;AACA,oE;AACA,8D;AACA,uE;AACA,6D;AACA,iC;AACA,qE;AACA,6B;AACA,E;;AAEA,sE;AACA,8B;AACA,0E;AACA,kB;;AAEA,sC;AACA,yC;AACA,4B;AACA,wD;AACA,wC;AACA,O;AACA,G;;AAEA,4D;AACA,W;AACA,a;;AAEA,0B;AACA,wC;AACA,+D;AACA,2D;AACA,O;AACA,iD;AACA,G;AACA,wE;AACA,gE;AACA,4D;AACA,O;AACA,iD;AACA,G;;AAEA,4E;AACA,gF;AACA,8E;AACA,sC;;AAEA,kE;AACA,E;;AAEA,G;AACA,uB;AACA,G;AACA,qC","file":"/packages/mongo.js","sourcesContent":["LocalCollectionDriver = function () {\n  var self = this;\n  self.noConnCollections = {};\n};\n\nvar ensureCollection = function (name, collections) {\n  if (!(name in collections))\n    collections[name] = new LocalCollection(name);\n  return collections[name];\n};\n\n_.extend(LocalCollectionDriver.prototype, {\n  open: function (name, conn) {\n    var self = this;\n    if (!name)\n      return new LocalCollection;\n    if (! conn) {\n      return ensureCollection(name, self.noConnCollections);\n    }\n    if (! conn._mongo_livedata_collections)\n      conn._mongo_livedata_collections = {};\n    // XXX is there a way to keep track of a connection's collections without\n    // dangling it off the connection object?\n    return ensureCollection(name, conn._mongo_livedata_collections);\n  }\n});\n\n// singleton\nLocalCollectionDriver = new LocalCollectionDriver;\n","// options.connection, if given, is a LivedataClient or LivedataServer\n// XXX presently there is no way to destroy/clean up a Collection\n\n/**\n * @summary Namespace for MongoDB-related items\n * @namespace\n */\nMongo = {};\n\n/**\n * @summary Constructor for a Collection\n * @locus Anywhere\n * @instancename collection\n * @class\n * @param {String} name The name of the collection.  If null, creates an unmanaged (unsynchronized) local collection.\n * @param {Object} [options]\n * @param {Object} options.connection The server connection that will manage this collection. Uses the default connection if not specified.  Pass the return value of calling [`DDP.connect`](#ddp_connect) to specify a different server. Pass `null` to specify no connection. Unmanaged (`name` is null) collections cannot specify a connection.\n * @param {String} options.idGeneration The method of generating the `_id` fields of new documents in this collection.  Possible values:\n\n - **`'STRING'`**: random strings\n - **`'MONGO'`**:  random [`Mongo.ObjectID`](#mongo_object_id) values\n\nThe default id generation technique is `'STRING'`.\n * @param {Function} options.transform An optional transformation function. Documents will be passed through this function before being returned from `fetch` or `findOne`, and before being passed to callbacks of `observe`, `map`, `forEach`, `allow`, and `deny`. Transforms are *not* applied for the callbacks of `observeChanges` or to cursors returned from publish functions.\n */\nMongo.Collection = function (name, options) {\n  var self = this;\n  if (! (self instanceof Mongo.Collection))\n    throw new Error('use \"new\" to construct a Mongo.Collection');\n\n  if (!name && (name !== null)) {\n    Meteor._debug(\"Warning: creating anonymous collection. It will not be \" +\n                  \"saved or synchronized over the network. (Pass null for \" +\n                  \"the collection name to turn off this warning.)\");\n    name = null;\n  }\n\n  if (name !== null && typeof name !== \"string\") {\n    throw new Error(\n      \"First argument to new Mongo.Collection must be a string or null\");\n  }\n\n  if (options && options.methods) {\n    // Backwards compatibility hack with original signature (which passed\n    // \"connection\" directly instead of in options. (Connections must have a \"methods\"\n    // method.)\n    // XXX remove before 1.0\n    options = {connection: options};\n  }\n  // Backwards compatibility: \"connection\" used to be called \"manager\".\n  if (options && options.manager && !options.connection) {\n    options.connection = options.manager;\n  }\n  options = _.extend({\n    connection: undefined,\n    idGeneration: 'STRING',\n    transform: null,\n    _driver: undefined,\n    _preventAutopublish: false\n  }, options);\n\n  switch (options.idGeneration) {\n  case 'MONGO':\n    self._makeNewID = function () {\n      var src = name ? DDP.randomStream('/collection/' + name) : Random;\n      return new Mongo.ObjectID(src.hexString(24));\n    };\n    break;\n  case 'STRING':\n  default:\n    self._makeNewID = function () {\n      var src = name ? DDP.randomStream('/collection/' + name) : Random;\n      return src.id();\n    };\n    break;\n  }\n\n  self._transform = LocalCollection.wrapTransform(options.transform);\n\n  if (! name || options.connection === null)\n    // note: nameless collections never have a connection\n    self._connection = null;\n  else if (options.connection)\n    self._connection = options.connection;\n  else if (Meteor.isClient)\n    self._connection = Meteor.connection;\n  else\n    self._connection = Meteor.server;\n\n  if (!options._driver) {\n    // XXX This check assumes that webapp is loaded so that Meteor.server !==\n    // null. We should fully support the case of \"want to use a Mongo-backed\n    // collection from Node code without webapp\", but we don't yet.\n    // #MeteorServerNull\n    if (name && self._connection === Meteor.server &&\n        typeof MongoInternals !== \"undefined\" &&\n        MongoInternals.defaultRemoteCollectionDriver) {\n      options._driver = MongoInternals.defaultRemoteCollectionDriver();\n    } else {\n      options._driver = LocalCollectionDriver;\n    }\n  }\n\n  self._collection = options._driver.open(name, self._connection);\n  self._name = name;\n  self._driver = options._driver;\n\n  if (self._connection && self._connection.registerStore) {\n    // OK, we're going to be a slave, replicating some remote\n    // database, except possibly with some temporary divergence while\n    // we have unacknowledged RPC's.\n    var ok = self._connection.registerStore(name, {\n      // Called at the beginning of a batch of updates. batchSize is the number\n      // of update calls to expect.\n      //\n      // XXX This interface is pretty janky. reset probably ought to go back to\n      // being its own function, and callers shouldn't have to calculate\n      // batchSize. The optimization of not calling pause/remove should be\n      // delayed until later: the first call to update() should buffer its\n      // message, and then we can either directly apply it at endUpdate time if\n      // it was the only update, or do pauseObservers/apply/apply at the next\n      // update() if there's another one.\n      beginUpdate: function (batchSize, reset) {\n        // pause observers so users don't see flicker when updating several\n        // objects at once (including the post-reconnect reset-and-reapply\n        // stage), and so that a re-sorting of a query can take advantage of the\n        // full _diffQuery moved calculation instead of applying change one at a\n        // time.\n        if (batchSize > 1 || reset)\n          self._collection.pauseObservers();\n\n        if (reset)\n          self._collection.remove({});\n      },\n\n      // Apply an update.\n      // XXX better specify this interface (not in terms of a wire message)?\n      update: function (msg) {\n        var mongoId = LocalCollection._idParse(msg.id);\n        var doc = self._collection.findOne(mongoId);\n\n        // Is this a \"replace the whole doc\" message coming from the quiescence\n        // of method writes to an object? (Note that 'undefined' is a valid\n        // value meaning \"remove it\".)\n        if (msg.msg === 'replace') {\n          var replace = msg.replace;\n          if (!replace) {\n            if (doc)\n              self._collection.remove(mongoId);\n          } else if (!doc) {\n            self._collection.insert(replace);\n          } else {\n            // XXX check that replace has no $ ops\n            self._collection.update(mongoId, replace);\n          }\n          return;\n        } else if (msg.msg === 'added') {\n          if (doc) {\n            throw new Error(\"Expected not to find a document already present for an add\");\n          }\n          self._collection.insert(_.extend({_id: mongoId}, msg.fields));\n        } else if (msg.msg === 'removed') {\n          if (!doc)\n            throw new Error(\"Expected to find a document already present for removed\");\n          self._collection.remove(mongoId);\n        } else if (msg.msg === 'changed') {\n          if (!doc)\n            throw new Error(\"Expected to find a document to change\");\n          if (!_.isEmpty(msg.fields)) {\n            var modifier = {};\n            _.each(msg.fields, function (value, key) {\n              if (value === undefined) {\n                if (!modifier.$unset)\n                  modifier.$unset = {};\n                modifier.$unset[key] = 1;\n              } else {\n                if (!modifier.$set)\n                  modifier.$set = {};\n                modifier.$set[key] = value;\n              }\n            });\n            self._collection.update(mongoId, modifier);\n          }\n        } else {\n          throw new Error(\"I don't know how to deal with this message\");\n        }\n\n      },\n\n      // Called at the end of a batch of updates.\n      endUpdate: function () {\n        self._collection.resumeObservers();\n      },\n\n      // Called around method stub invocations to capture the original versions\n      // of modified documents.\n      saveOriginals: function () {\n        self._collection.saveOriginals();\n      },\n      retrieveOriginals: function () {\n        return self._collection.retrieveOriginals();\n      }\n    });\n\n    if (!ok)\n      throw new Error(\"There is already a collection named '\" + name + \"'\");\n  }\n\n  self._defineMutationMethods();\n\n  // autopublish\n  if (Package.autopublish && !options._preventAutopublish && self._connection\n      && self._connection.publish) {\n    self._connection.publish(null, function () {\n      return self.find();\n    }, {is_auto: true});\n  }\n};\n\n///\n/// Main collection API\n///\n\n\n_.extend(Mongo.Collection.prototype, {\n\n  _getFindSelector: function (args) {\n    if (args.length == 0)\n      return {};\n    else\n      return args[0];\n  },\n\n  _getFindOptions: function (args) {\n    var self = this;\n    if (args.length < 2) {\n      return { transform: self._transform };\n    } else {\n      check(args[1], Match.Optional(Match.ObjectIncluding({\n        fields: Match.Optional(Match.OneOf(Object, undefined)),\n        sort: Match.Optional(Match.OneOf(Object, Array, undefined)),\n        limit: Match.Optional(Match.OneOf(Number, undefined)),\n        skip: Match.Optional(Match.OneOf(Number, undefined))\n     })));\n\n      return _.extend({\n        transform: self._transform\n      }, args[1]);\n    }\n  },\n\n  /**\n   * @summary Find the documents in a collection that match the selector.\n   * @locus Anywhere\n   * @method find\n   * @memberOf Mongo.Collection\n   * @instance\n   * @param {MongoSelector} [selector] A query describing the documents to find\n   * @param {Object} [options]\n   * @param {MongoSortSpecifier} options.sort Sort order (default: natural order)\n   * @param {Number} options.skip Number of results to skip at the beginning\n   * @param {Number} options.limit Maximum number of results to return\n   * @param {MongoFieldSpecifier} options.fields Dictionary of fields to return or exclude.\n   * @param {Boolean} options.reactive (Client only) Default `true`; pass `false` to disable reactivity\n   * @param {Function} options.transform Overrides `transform` on the  [`Collection`](#collections) for this cursor.  Pass `null` to disable transformation.\n   * @returns {Mongo.Cursor}\n   */\n  find: function (/* selector, options */) {\n    // Collection.find() (return all docs) behaves differently\n    // from Collection.find(undefined) (return 0 docs).  so be\n    // careful about the length of arguments.\n    var self = this;\n    var argArray = _.toArray(arguments);\n    return self._collection.find(self._getFindSelector(argArray),\n                                 self._getFindOptions(argArray));\n  },\n\n  /**\n   * @summary Finds the first document that matches the selector, as ordered by sort and skip options.\n   * @locus Anywhere\n   * @method findOne\n   * @memberOf Mongo.Collection\n   * @instance\n   * @param {MongoSelector} [selector] A query describing the documents to find\n   * @param {Object} [options]\n   * @param {MongoSortSpecifier} options.sort Sort order (default: natural order)\n   * @param {Number} options.skip Number of results to skip at the beginning\n   * @param {MongoFieldSpecifier} options.fields Dictionary of fields to return or exclude.\n   * @param {Boolean} options.reactive (Client only) Default true; pass false to disable reactivity\n   * @param {Function} options.transform Overrides `transform` on the [`Collection`](#collections) for this cursor.  Pass `null` to disable transformation.\n   * @returns {Object}\n   */\n  findOne: function (/* selector, options */) {\n    var self = this;\n    var argArray = _.toArray(arguments);\n    return self._collection.findOne(self._getFindSelector(argArray),\n                                    self._getFindOptions(argArray));\n  }\n\n});\n\nMongo.Collection._publishCursor = function (cursor, sub, collection) {\n  var observeHandle = cursor.observeChanges({\n    added: function (id, fields) {\n      sub.added(collection, id, fields);\n    },\n    changed: function (id, fields) {\n      sub.changed(collection, id, fields);\n    },\n    removed: function (id) {\n      sub.removed(collection, id);\n    }\n  });\n\n  // We don't call sub.ready() here: it gets called in livedata_server, after\n  // possibly calling _publishCursor on multiple returned cursors.\n\n  // register stop callback (expects lambda w/ no args).\n  sub.onStop(function () {observeHandle.stop();});\n};\n\n// protect against dangerous selectors.  falsey and {_id: falsey} are both\n// likely programmer error, and not what you want, particularly for destructive\n// operations.  JS regexps don't serialize over DDP but can be trivially\n// replaced by $regex.\nMongo.Collection._rewriteSelector = function (selector) {\n  // shorthand -- scalars match _id\n  if (LocalCollection._selectorIsId(selector))\n    selector = {_id: selector};\n\n  if (!selector || (('_id' in selector) && !selector._id))\n    // can't match anything\n    return {_id: Random.id()};\n\n  var ret = {};\n  _.each(selector, function (value, key) {\n    // Mongo supports both {field: /foo/} and {field: {$regex: /foo/}}\n    if (value instanceof RegExp) {\n      ret[key] = convertRegexpToMongoSelector(value);\n    } else if (value && value.$regex instanceof RegExp) {\n      ret[key] = convertRegexpToMongoSelector(value.$regex);\n      // if value is {$regex: /foo/, $options: ...} then $options\n      // override the ones set on $regex.\n      if (value.$options !== undefined)\n        ret[key].$options = value.$options;\n    }\n    else if (_.contains(['$or','$and','$nor'], key)) {\n      // Translate lower levels of $and/$or/$nor\n      ret[key] = _.map(value, function (v) {\n        return Mongo.Collection._rewriteSelector(v);\n      });\n    } else {\n      ret[key] = value;\n    }\n  });\n  return ret;\n};\n\n// convert a JS RegExp object to a Mongo {$regex: ..., $options: ...}\n// selector\nvar convertRegexpToMongoSelector = function (regexp) {\n  check(regexp, RegExp); // safety belt\n\n  var selector = {$regex: regexp.source};\n  var regexOptions = '';\n  // JS RegExp objects support 'i', 'm', and 'g'. Mongo regex $options\n  // support 'i', 'm', 'x', and 's'. So we support 'i' and 'm' here.\n  if (regexp.ignoreCase)\n    regexOptions += 'i';\n  if (regexp.multiline)\n    regexOptions += 'm';\n  if (regexOptions)\n    selector.$options = regexOptions;\n\n  return selector;\n};\n\nvar throwIfSelectorIsNotId = function (selector, methodName) {\n  if (!LocalCollection._selectorIsIdPerhapsAsObject(selector)) {\n    throw new Meteor.Error(\n      403, \"Not permitted. Untrusted code may only \" + methodName +\n        \" documents by ID.\");\n  }\n};\n\n// 'insert' immediately returns the inserted document's new _id.\n// The others return values immediately if you are in a stub, an in-memory\n// unmanaged collection, or a mongo-backed collection and you don't pass a\n// callback. 'update' and 'remove' return the number of affected\n// documents. 'upsert' returns an object with keys 'numberAffected' and, if an\n// insert happened, 'insertedId'.\n//\n// Otherwise, the semantics are exactly like other methods: they take\n// a callback as an optional last argument; if no callback is\n// provided, they block until the operation is complete, and throw an\n// exception if it fails; if a callback is provided, then they don't\n// necessarily block, and they call the callback when they finish with error and\n// result arguments.  (The insert method provides the document ID as its result;\n// update and remove provide the number of affected docs as the result; upsert\n// provides an object with numberAffected and maybe insertedId.)\n//\n// On the client, blocking is impossible, so if a callback\n// isn't provided, they just return immediately and any error\n// information is lost.\n//\n// There's one more tweak. On the client, if you don't provide a\n// callback, then if there is an error, a message will be logged with\n// Meteor._debug.\n//\n// The intent (though this is actually determined by the underlying\n// drivers) is that the operations should be done synchronously, not\n// generating their result until the database has acknowledged\n// them. In the future maybe we should provide a flag to turn this\n// off.\n\n/**\n * @summary Insert a document in the collection.  Returns its unique _id.\n * @locus Anywhere\n * @method  insert\n * @memberOf Mongo.Collection\n * @instance\n * @param {Object} doc The document to insert. May not yet have an _id attribute, in which case Meteor will generate one for you.\n * @param {Function} [callback] Optional.  If present, called with an error object as the first argument and, if no error, the _id as the second.\n */\n\n/**\n * @summary Modify one or more documents in the collection. Returns the number of affected documents.\n * @locus Anywhere\n * @method update\n * @memberOf Mongo.Collection\n * @instance\n * @param {MongoSelector} selector Specifies which documents to modify\n * @param {MongoModifier} modifier Specifies how to modify the documents\n * @param {Object} [options]\n * @param {Boolean} options.multi True to modify all matching documents; false to only modify one of the matching documents (the default).\n * @param {Boolean} options.upsert True to insert a document if no matching documents are found.\n * @param {Function} [callback] Optional.  If present, called with an error object as the first argument and, if no error, the number of affected documents as the second.\n */\n\n/**\n * @summary Remove documents from the collection\n * @locus Anywhere\n * @method remove\n * @memberOf Mongo.Collection\n * @instance\n * @param {MongoSelector} selector Specifies which documents to remove\n * @param {Function} [callback] Optional.  If present, called with an error object as its argument.\n */\n\n_.each([\"insert\", \"update\", \"remove\"], function (name) {\n  Mongo.Collection.prototype[name] = function (/* arguments */) {\n    var self = this;\n    var args = _.toArray(arguments);\n    var callback;\n    var insertId;\n    var ret;\n\n    // Pull off any callback (or perhaps a 'callback' variable that was passed\n    // in undefined, like how 'upsert' does it).\n    if (args.length &&\n        (args[args.length - 1] === undefined ||\n         args[args.length - 1] instanceof Function)) {\n      callback = args.pop();\n    }\n\n    if (name === \"insert\") {\n      if (!args.length)\n        throw new Error(\"insert requires an argument\");\n      // shallow-copy the document and generate an ID\n      args[0] = _.extend({}, args[0]);\n      if ('_id' in args[0]) {\n        insertId = args[0]._id;\n        if (!insertId || !(typeof insertId === 'string'\n              || insertId instanceof Mongo.ObjectID))\n          throw new Error(\"Meteor requires document _id fields to be non-empty strings or ObjectIDs\");\n      } else {\n        var generateId = true;\n        // Don't generate the id if we're the client and the 'outermost' call\n        // This optimization saves us passing both the randomSeed and the id\n        // Passing both is redundant.\n        if (self._connection && self._connection !== Meteor.server) {\n          var enclosing = DDP._CurrentInvocation.get();\n          if (!enclosing) {\n            generateId = false;\n          }\n        }\n        if (generateId) {\n          insertId = args[0]._id = self._makeNewID();\n        }\n      }\n    } else {\n      args[0] = Mongo.Collection._rewriteSelector(args[0]);\n\n      if (name === \"update\") {\n        // Mutate args but copy the original options object. We need to add\n        // insertedId to options, but don't want to mutate the caller's options\n        // object. We need to mutate `args` because we pass `args` into the\n        // driver below.\n        var options = args[2] = _.clone(args[2]) || {};\n        if (options && typeof options !== \"function\" && options.upsert) {\n          // set `insertedId` if absent.  `insertedId` is a Meteor extension.\n          if (options.insertedId) {\n            if (!(typeof options.insertedId === 'string'\n                  || options.insertedId instanceof Mongo.ObjectID))\n              throw new Error(\"insertedId must be string or ObjectID\");\n          } else if (! args[0]._id) {\n            options.insertedId = self._makeNewID();\n          }\n        }\n      }\n    }\n\n    // On inserts, always return the id that we generated; on all other\n    // operations, just return the result from the collection.\n    var chooseReturnValueFromCollectionResult = function (result) {\n      if (name === \"insert\") {\n        if (!insertId && result) {\n          insertId = result;\n        }\n        return insertId;\n      } else {\n        return result;\n      }\n    };\n\n    var wrappedCallback;\n    if (callback) {\n      wrappedCallback = function (error, result) {\n        callback(error, ! error && chooseReturnValueFromCollectionResult(result));\n      };\n    }\n\n    // XXX see #MeteorServerNull\n    if (self._connection && self._connection !== Meteor.server) {\n      // just remote to another endpoint, propagate return value or\n      // exception.\n\n      var enclosing = DDP._CurrentInvocation.get();\n      var alreadyInSimulation = enclosing && enclosing.isSimulation;\n\n      if (Meteor.isClient && !wrappedCallback && ! alreadyInSimulation) {\n        // Client can't block, so it can't report errors by exception,\n        // only by callback. If they forget the callback, give them a\n        // default one that logs the error, so they aren't totally\n        // baffled if their writes don't work because their database is\n        // down.\n        // Don't give a default callback in simulation, because inside stubs we\n        // want to return the results from the local collection immediately and\n        // not force a callback.\n        wrappedCallback = function (err) {\n          if (err)\n            Meteor._debug(name + \" failed: \" + (err.reason || err.stack));\n        };\n      }\n\n      if (!alreadyInSimulation && name !== \"insert\") {\n        // If we're about to actually send an RPC, we should throw an error if\n        // this is a non-ID selector, because the mutation methods only allow\n        // single-ID selectors. (If we don't throw here, we'll see flicker.)\n        throwIfSelectorIsNotId(args[0], name);\n      }\n\n      ret = chooseReturnValueFromCollectionResult(\n        self._connection.apply(self._prefix + name, args, {returnStubValue: true}, wrappedCallback)\n      );\n\n    } else {\n      // it's my collection.  descend into the collection object\n      // and propagate any exception.\n      args.push(wrappedCallback);\n      try {\n        // If the user provided a callback and the collection implements this\n        // operation asynchronously, then queryRet will be undefined, and the\n        // result will be returned through the callback instead.\n        var queryRet = self._collection[name].apply(self._collection, args);\n        ret = chooseReturnValueFromCollectionResult(queryRet);\n      } catch (e) {\n        if (callback) {\n          callback(e);\n          return null;\n        }\n        throw e;\n      }\n    }\n\n    // both sync and async, unless we threw an exception, return ret\n    // (new document ID for insert, num affected for update/remove, object with\n    // numberAffected and maybe insertedId for upsert).\n    return ret;\n  };\n});\n\n/**\n * @summary Modify one or more documents in the collection, or insert one if no matching documents were found. Returns an object with keys `numberAffected` (the number of documents modified)  and `insertedId` (the unique _id of the document that was inserted, if any).\n * @locus Anywhere\n * @param {MongoSelector} selector Specifies which documents to modify\n * @param {MongoModifier} modifier Specifies how to modify the documents\n * @param {Object} [options]\n * @param {Boolean} options.multi True to modify all matching documents; false to only modify one of the matching documents (the default).\n * @param {Function} [callback] Optional.  If present, called with an error object as the first argument and, if no error, the number of affected documents as the second.\n */\nMongo.Collection.prototype.upsert = function (selector, modifier,\n                                               options, callback) {\n  var self = this;\n  if (! callback && typeof options === \"function\") {\n    callback = options;\n    options = {};\n  }\n  return self.update(selector, modifier,\n              _.extend({}, options, { _returnObject: true, upsert: true }),\n              callback);\n};\n\n// We'll actually design an index API later. For now, we just pass through to\n// Mongo's, but make it synchronous.\nMongo.Collection.prototype._ensureIndex = function (index, options) {\n  var self = this;\n  if (!self._collection._ensureIndex)\n    throw new Error(\"Can only call _ensureIndex on server collections\");\n  self._collection._ensureIndex(index, options);\n};\nMongo.Collection.prototype._dropIndex = function (index) {\n  var self = this;\n  if (!self._collection._dropIndex)\n    throw new Error(\"Can only call _dropIndex on server collections\");\n  self._collection._dropIndex(index);\n};\nMongo.Collection.prototype._dropCollection = function () {\n  var self = this;\n  if (!self._collection.dropCollection)\n    throw new Error(\"Can only call _dropCollection on server collections\");\n  self._collection.dropCollection();\n};\nMongo.Collection.prototype._createCappedCollection = function (byteSize, maxDocuments) {\n  var self = this;\n  if (!self._collection._createCappedCollection)\n    throw new Error(\"Can only call _createCappedCollection on server collections\");\n  self._collection._createCappedCollection(byteSize, maxDocuments);\n};\n\nMongo.Collection.prototype.rawCollection = function () {\n  var self = this;\n  if (! self._collection.rawCollection) {\n    throw new Error(\"Can only call rawCollection on server collections\");\n  }\n  return self._collection.rawCollection();\n};\n\nMongo.Collection.prototype.rawDatabase = function () {\n  var self = this;\n  if (! (self._driver.mongo && self._driver.mongo.db)) {\n    throw new Error(\"Can only call rawDatabase on server collections\");\n  }\n  return self._driver.mongo.db;\n};\n\n\n/**\n * @summary Create a Mongo-style `ObjectID`.  If you don't specify a `hexString`, the `ObjectID` will generated randomly (not using MongoDB's ID construction rules).\n * @locus Anywhere\n * @class\n * @param {String} hexString Optional.  The 24-character hexadecimal contents of the ObjectID to create\n */\nMongo.ObjectID = LocalCollection._ObjectID;\n\n/**\n * @summary To create a cursor, use find. To access the documents in a cursor, use forEach, map, or fetch.\n * @class\n * @instanceName cursor\n */\nMongo.Cursor = LocalCollection.Cursor;\n\n/**\n * @deprecated in 0.9.1\n */\nMongo.Collection.Cursor = Mongo.Cursor;\n\n/**\n * @deprecated in 0.9.1\n */\nMongo.Collection.ObjectID = Mongo.ObjectID;\n\n///\n/// Remote methods and access control.\n///\n\n// Restrict default mutators on collection. allow() and deny() take the\n// same options:\n//\n// options.insert {Function(userId, doc)}\n//   return true to allow/deny adding this document\n//\n// options.update {Function(userId, docs, fields, modifier)}\n//   return true to allow/deny updating these documents.\n//   `fields` is passed as an array of fields that are to be modified\n//\n// options.remove {Function(userId, docs)}\n//   return true to allow/deny removing these documents\n//\n// options.fetch {Array}\n//   Fields to fetch for these validators. If any call to allow or deny\n//   does not have this option then all fields are loaded.\n//\n// allow and deny can be called multiple times. The validators are\n// evaluated as follows:\n// - If neither deny() nor allow() has been called on the collection,\n//   then the request is allowed if and only if the \"insecure\" smart\n//   package is in use.\n// - Otherwise, if any deny() function returns true, the request is denied.\n// - Otherwise, if any allow() function returns true, the request is allowed.\n// - Otherwise, the request is denied.\n//\n// Meteor may call your deny() and allow() functions in any order, and may not\n// call all of them if it is able to make a decision without calling them all\n// (so don't include side effects).\n\n(function () {\n  var addValidator = function(allowOrDeny, options) {\n    // validate keys\n    var VALID_KEYS = ['insert', 'update', 'remove', 'fetch', 'transform'];\n    _.each(_.keys(options), function (key) {\n      if (!_.contains(VALID_KEYS, key))\n        throw new Error(allowOrDeny + \": Invalid key: \" + key);\n    });\n\n    var self = this;\n    self._restricted = true;\n\n    _.each(['insert', 'update', 'remove'], function (name) {\n      if (options[name]) {\n        if (!(options[name] instanceof Function)) {\n          throw new Error(allowOrDeny + \": Value for `\" + name + \"` must be a function\");\n        }\n\n        // If the transform is specified at all (including as 'null') in this\n        // call, then take that; otherwise, take the transform from the\n        // collection.\n        if (options.transform === undefined) {\n          options[name].transform = self._transform;  // already wrapped\n        } else {\n          options[name].transform = LocalCollection.wrapTransform(\n            options.transform);\n        }\n\n        self._validators[name][allowOrDeny].push(options[name]);\n      }\n    });\n\n    // Only update the fetch fields if we're passed things that affect\n    // fetching. This way allow({}) and allow({insert: f}) don't result in\n    // setting fetchAllFields\n    if (options.update || options.remove || options.fetch) {\n      if (options.fetch && !(options.fetch instanceof Array)) {\n        throw new Error(allowOrDeny + \": Value for `fetch` must be an array\");\n      }\n      self._updateFetch(options.fetch);\n    }\n  };\n\n  /**\n   * @summary Allow users to write directly to this collection from client code, subject to limitations you define.\n   * @locus Server\n   * @param {Object} options\n   * @param {Function} options.insert,update,remove Functions that look at a proposed modification to the database and return true if it should be allowed.\n   * @param {String[]} options.fetch Optional performance enhancement. Limits the fields that will be fetched from the database for inspection by your `update` and `remove` functions.\n   * @param {Function} options.transform Overrides `transform` on the  [`Collection`](#collections).  Pass `null` to disable transformation.\n   */\n  Mongo.Collection.prototype.allow = function(options) {\n    addValidator.call(this, 'allow', options);\n  };\n\n  /**\n   * @summary Override `allow` rules.\n   * @locus Server\n   * @param {Object} options\n   * @param {Function} options.insert,update,remove Functions that look at a proposed modification to the database and return true if it should be denied, even if an [allow](#allow) rule says otherwise.\n   * @param {String[]} options.fetch Optional performance enhancement. Limits the fields that will be fetched from the database for inspection by your `update` and `remove` functions.\n   * @param {Function} options.transform Overrides `transform` on the  [`Collection`](#collections).  Pass `null` to disable transformation.\n   */\n  Mongo.Collection.prototype.deny = function(options) {\n    addValidator.call(this, 'deny', options);\n  };\n})();\n\n\nMongo.Collection.prototype._defineMutationMethods = function() {\n  var self = this;\n\n  // set to true once we call any allow or deny methods. If true, use\n  // allow/deny semantics. If false, use insecure mode semantics.\n  self._restricted = false;\n\n  // Insecure mode (default to allowing writes). Defaults to 'undefined' which\n  // means insecure iff the insecure package is loaded. This property can be\n  // overriden by tests or packages wishing to change insecure mode behavior of\n  // their collections.\n  self._insecure = undefined;\n\n  self._validators = {\n    insert: {allow: [], deny: []},\n    update: {allow: [], deny: []},\n    remove: {allow: [], deny: []},\n    upsert: {allow: [], deny: []}, // dummy arrays; can't set these!\n    fetch: [],\n    fetchAllFields: false\n  };\n\n  if (!self._name)\n    return; // anonymous collection\n\n  // XXX Think about method namespacing. Maybe methods should be\n  // \"Meteor:Mongo:insert/NAME\"?\n  self._prefix = '/' + self._name + '/';\n\n  // mutation methods\n  if (self._connection) {\n    var m = {};\n\n    _.each(['insert', 'update', 'remove'], function (method) {\n      m[self._prefix + method] = function (/* ... */) {\n        // All the methods do their own validation, instead of using check().\n        check(arguments, [Match.Any]);\n        var args = _.toArray(arguments);\n        try {\n          // For an insert, if the client didn't specify an _id, generate one\n          // now; because this uses DDP.randomStream, it will be consistent with\n          // what the client generated. We generate it now rather than later so\n          // that if (eg) an allow/deny rule does an insert to the same\n          // collection (not that it really should), the generated _id will\n          // still be the first use of the stream and will be consistent.\n          //\n          // However, we don't actually stick the _id onto the document yet,\n          // because we want allow/deny rules to be able to differentiate\n          // between arbitrary client-specified _id fields and merely\n          // client-controlled-via-randomSeed fields.\n          var generatedId = null;\n          if (method === \"insert\" && !_.has(args[0], '_id')) {\n            generatedId = self._makeNewID();\n          }\n\n          if (this.isSimulation) {\n            // In a client simulation, you can do any mutation (even with a\n            // complex selector).\n            if (generatedId !== null)\n              args[0]._id = generatedId;\n            return self._collection[method].apply(\n              self._collection, args);\n          }\n\n          // This is the server receiving a method call from the client.\n\n          // We don't allow arbitrary selectors in mutations from the client: only\n          // single-ID selectors.\n          if (method !== 'insert')\n            throwIfSelectorIsNotId(args[0], method);\n\n          if (self._restricted) {\n            // short circuit if there is no way it will pass.\n            if (self._validators[method].allow.length === 0) {\n              throw new Meteor.Error(\n                403, \"Access denied. No allow validators set on restricted \" +\n                  \"collection for method '\" + method + \"'.\");\n            }\n\n            var validatedMethodName =\n                  '_validated' + method.charAt(0).toUpperCase() + method.slice(1);\n            args.unshift(this.userId);\n            method === 'insert' && args.push(generatedId);\n            return self[validatedMethodName].apply(self, args);\n          } else if (self._isInsecure()) {\n            if (generatedId !== null)\n              args[0]._id = generatedId;\n            // In insecure mode, allow any mutation (with a simple selector).\n            // XXX This is kind of bogus.  Instead of blindly passing whatever\n            //     we get from the network to this function, we should actually\n            //     know the correct arguments for the function and pass just\n            //     them.  For example, if you have an extraneous extra null\n            //     argument and this is Mongo on the server, the .wrapAsync'd\n            //     functions like update will get confused and pass the\n            //     \"fut.resolver()\" in the wrong slot, where _update will never\n            //     invoke it. Bam, broken DDP connection.  Probably should just\n            //     take this whole method and write it three times, invoking\n            //     helpers for the common code.\n            return self._collection[method].apply(self._collection, args);\n          } else {\n            // In secure mode, if we haven't called allow or deny, then nothing\n            // is permitted.\n            throw new Meteor.Error(403, \"Access denied\");\n          }\n        } catch (e) {\n          if (e.name === 'MongoError' || e.name === 'MinimongoError') {\n            throw new Meteor.Error(409, e.toString());\n          } else {\n            throw e;\n          }\n        }\n      };\n    });\n    // Minimongo on the server gets no stubs; instead, by default\n    // it wait()s until its result is ready, yielding.\n    // This matches the behavior of macromongo on the server better.\n    // XXX see #MeteorServerNull\n    if (Meteor.isClient || self._connection === Meteor.server)\n      self._connection.methods(m);\n  }\n};\n\n\nMongo.Collection.prototype._updateFetch = function (fields) {\n  var self = this;\n\n  if (!self._validators.fetchAllFields) {\n    if (fields) {\n      self._validators.fetch = _.union(self._validators.fetch, fields);\n    } else {\n      self._validators.fetchAllFields = true;\n      // clear fetch just to make sure we don't accidentally read it\n      self._validators.fetch = null;\n    }\n  }\n};\n\nMongo.Collection.prototype._isInsecure = function () {\n  var self = this;\n  if (self._insecure === undefined)\n    return !!Package.insecure;\n  return self._insecure;\n};\n\nvar docToValidate = function (validator, doc, generatedId) {\n  var ret = doc;\n  if (validator.transform) {\n    ret = EJSON.clone(doc);\n    // If you set a server-side transform on your collection, then you don't get\n    // to tell the difference between \"client specified the ID\" and \"server\n    // generated the ID\", because transforms expect to get _id.  If you want to\n    // do that check, you can do it with a specific\n    // `C.allow({insert: f, transform: null})` validator.\n    if (generatedId !== null) {\n      ret._id = generatedId;\n    }\n    ret = validator.transform(ret);\n  }\n  return ret;\n};\n\nMongo.Collection.prototype._validatedInsert = function (userId, doc,\n                                                         generatedId) {\n  var self = this;\n\n  // call user validators.\n  // Any deny returns true means denied.\n  if (_.any(self._validators.insert.deny, function(validator) {\n    return validator(userId, docToValidate(validator, doc, generatedId));\n  })) {\n    throw new Meteor.Error(403, \"Access denied\");\n  }\n  // Any allow returns true means proceed. Throw error if they all fail.\n  if (_.all(self._validators.insert.allow, function(validator) {\n    return !validator(userId, docToValidate(validator, doc, generatedId));\n  })) {\n    throw new Meteor.Error(403, \"Access denied\");\n  }\n\n  // If we generated an ID above, insert it now: after the validation, but\n  // before actually inserting.\n  if (generatedId !== null)\n    doc._id = generatedId;\n\n  self._collection.insert.call(self._collection, doc);\n};\n\nvar transformDoc = function (validator, doc) {\n  if (validator.transform)\n    return validator.transform(doc);\n  return doc;\n};\n\n// Simulate a mongo `update` operation while validating that the access\n// control rules set by calls to `allow/deny` are satisfied. If all\n// pass, rewrite the mongo operation to use $in to set the list of\n// document ids to change ##ValidatedChange\nMongo.Collection.prototype._validatedUpdate = function(\n    userId, selector, mutator, options) {\n  var self = this;\n\n  check(mutator, Object);\n\n  options = _.clone(options) || {};\n\n  if (!LocalCollection._selectorIsIdPerhapsAsObject(selector))\n    throw new Error(\"validated update should be of a single ID\");\n\n  // We don't support upserts because they don't fit nicely into allow/deny\n  // rules.\n  if (options.upsert)\n    throw new Meteor.Error(403, \"Access denied. Upserts not \" +\n                           \"allowed in a restricted collection.\");\n\n  var noReplaceError = \"Access denied. In a restricted collection you can only\" +\n        \" update documents, not replace them. Use a Mongo update operator, such \" +\n        \"as '$set'.\";\n\n  // compute modified fields\n  var fields = [];\n  if (_.isEmpty(mutator)) {\n    throw new Meteor.Error(403, noReplaceError);\n  }\n  _.each(mutator, function (params, op) {\n    if (op.charAt(0) !== '$') {\n      throw new Meteor.Error(403, noReplaceError);\n    } else if (!_.has(ALLOWED_UPDATE_OPERATIONS, op)) {\n      throw new Meteor.Error(\n        403, \"Access denied. Operator \" + op + \" not allowed in a restricted collection.\");\n    } else {\n      _.each(_.keys(params), function (field) {\n        // treat dotted fields as if they are replacing their\n        // top-level part\n        if (field.indexOf('.') !== -1)\n          field = field.substring(0, field.indexOf('.'));\n\n        // record the field we are trying to change\n        if (!_.contains(fields, field))\n          fields.push(field);\n      });\n    }\n  });\n\n  var findOptions = {transform: null};\n  if (!self._validators.fetchAllFields) {\n    findOptions.fields = {};\n    _.each(self._validators.fetch, function(fieldName) {\n      findOptions.fields[fieldName] = 1;\n    });\n  }\n\n  var doc = self._collection.findOne(selector, findOptions);\n  if (!doc)  // none satisfied!\n    return 0;\n\n  // call user validators.\n  // Any deny returns true means denied.\n  if (_.any(self._validators.update.deny, function(validator) {\n    var factoriedDoc = transformDoc(validator, doc);\n    return validator(userId,\n                     factoriedDoc,\n                     fields,\n                     mutator);\n  })) {\n    throw new Meteor.Error(403, \"Access denied\");\n  }\n  // Any allow returns true means proceed. Throw error if they all fail.\n  if (_.all(self._validators.update.allow, function(validator) {\n    var factoriedDoc = transformDoc(validator, doc);\n    return !validator(userId,\n                      factoriedDoc,\n                      fields,\n                      mutator);\n  })) {\n    throw new Meteor.Error(403, \"Access denied\");\n  }\n\n  options._forbidReplace = true;\n\n  // Back when we supported arbitrary client-provided selectors, we actually\n  // rewrote the selector to include an _id clause before passing to Mongo to\n  // avoid races, but since selector is guaranteed to already just be an ID, we\n  // don't have to any more.\n\n  return self._collection.update.call(\n    self._collection, selector, mutator, options);\n};\n\n// Only allow these operations in validated updates. Specifically\n// whitelist operations, rather than blacklist, so new complex\n// operations that are added aren't automatically allowed. A complex\n// operation is one that does more than just modify its target\n// field. For now this contains all update operations except '$rename'.\n// http://docs.mongodb.org/manual/reference/operators/#update\nvar ALLOWED_UPDATE_OPERATIONS = {\n  $inc:1, $set:1, $unset:1, $addToSet:1, $pop:1, $pullAll:1, $pull:1,\n  $pushAll:1, $push:1, $bit:1\n};\n\n// Simulate a mongo `remove` operation while validating access control\n// rules. See #ValidatedChange\nMongo.Collection.prototype._validatedRemove = function(userId, selector) {\n  var self = this;\n\n  var findOptions = {transform: null};\n  if (!self._validators.fetchAllFields) {\n    findOptions.fields = {};\n    _.each(self._validators.fetch, function(fieldName) {\n      findOptions.fields[fieldName] = 1;\n    });\n  }\n\n  var doc = self._collection.findOne(selector, findOptions);\n  if (!doc)\n    return 0;\n\n  // call user validators.\n  // Any deny returns true means denied.\n  if (_.any(self._validators.remove.deny, function(validator) {\n    return validator(userId, transformDoc(validator, doc));\n  })) {\n    throw new Meteor.Error(403, \"Access denied\");\n  }\n  // Any allow returns true means proceed. Throw error if they all fail.\n  if (_.all(self._validators.remove.allow, function(validator) {\n    return !validator(userId, transformDoc(validator, doc));\n  })) {\n    throw new Meteor.Error(403, \"Access denied\");\n  }\n\n  // Back when we supported arbitrary client-provided selectors, we actually\n  // rewrote the selector to {_id: {$in: [ids that we found]}} before passing to\n  // Mongo to avoid races, but since selector is guaranteed to already just be\n  // an ID, we don't have to any more.\n\n  return self._collection.remove.call(self._collection, selector);\n};\n\n/**\n * @deprecated in 0.9.1\n */\nMeteor.Collection = Mongo.Collection;\n"]}