Ejemplo n.º 1
0
 app.dbWrapper.registerWrapper(function (name, db, next) {
   //'fix' the PouchDB api (support opts arg everywhere)
   function noop(orig, args) {
     return orig();
   }
   // TODO: expand
   wrappers.installWrapperMethods(db, {info: noop});
   return next();
 });
Ejemplo n.º 2
0
  return utils.nodify(Promise.resolve().then(function () {
    // add wrappers and make system db
    if (!info.isOnlineAuthDB) {
      wrappers.installWrapperMethods(args.db, writeWrappers);
      systemDB.installSystemDBProtection(args.db);

      // store validation doc
      return args.db.put(designDoc);
    }
  }).catch(function (err) {
Ejemplo n.º 3
0
 app.dbWrapper.registerWrapper(function (name, db, next) {
   //'fix' the PouchDB api (support opts arg everywhere)
   function noop(orig, args) {
     return orig();
   }
   var wrapperMethods = {};
   ['info', 'removeAttachment'].forEach(function (name) {
     wrapperMethods[name] = noop;
   });
   wrappers.installWrapperMethods(db, wrapperMethods);
   return next();
 });
Ejemplo n.º 4
0
  app.dbWrapper.registerWrapper(function (name, db, next) {
    // db.info() should just return the non-uri encoded db name
    wrappers.installWrapperMethods(db, {
      info: function (orig, args) {
        return orig().then(function (info) {
          info.db_name = decodeURIComponent(info.db_name);
          return info;
        });
      }
    });

    return next();
  });
Ejemplo n.º 5
0
exports.installSizeWrapper = function () {
  var db = this;

  wrappers.installWrapperMethods(db, {
    info: function (orig, args) {
      var resp;
      return orig().then(function (info) {
        resp = info;

        return exports.getDiskSize.call(db);
      }).then(function (diskSize) {
        resp.disk_size = diskSize;

        return resp;
      }).catch(function () {
        //surpress - .info() should keep functioning if for some reason
        //it's impossible to get the disk_size.
        return resp;
      });
    }
  });
};
Ejemplo n.º 6
0
exports.enableUndo = function (options) {
	if (!options) { options = {}; }
	if (!options.hasOwnProperty('limit')) { options.limit = 100; }
	var db = this,
		PouchDB = this.constructor,
		Promise = PouchDB.utils.Promise,
		uuid = PouchDB.utils.uuid,
		error = function (options) {
			var error = new Error(options.reason);
			error.status = options.status;
			error.error = options.error;
			error.reason = options.reason;
			return error;
		},
		origBulkDocs = db.bulkDocs;

	var wrapUndo = function (orig, args) {
		var docs = args.docs;
		return orig().then(function (result) {
			var undoId = uuid();
			return db.get('_local/_undo').catch(function (err) {
				if (err.status !== 404) { throw err; }
				return { _id: '_local/_undo', history: [], undos: {} };
			}).then(function (undoDoc) {
				undoDoc.history.push(undoId);
				undoDoc.undos[undoId] = result.filter(function (row) {
					return row.ok;
				}).map(function (row, i) {
					return {
						id: row.id,
						oldRev: docs[i]._rev,
						newRev: row.rev
					};
				});
				if (undoDoc.history.length > options.limit) {
					undoDoc.history.slice(0, -options.limit).forEach(function (undoId) {
						delete undoDoc.undos[undoId];
						undoDoc.history.shift();
					});
				}
				return origBulkDocs.call(db, [undoDoc]); // FIXME: pouchdb bug? doesn't throw conflict if rev is incorrect
			}).then(function () { 
				return result.map(function (row) {
					row.undoId = undoId;
					return row;
				});
			});
		});
	};

	db.undo = function (undoId) {
		return db.get('_local/_undo').then(function (undoDoc) {
			var revisions = undoDoc.undos[undoId];
			if (typeof revisions === 'undefined') {
				throw error({
					status: 404,
					error: 'not_found',
					reason: 'Undo with that ID not found'
				});
			}
			return Promise.all(revisions.map(function (revision) {
				// get latest revision
				return db.get(revision.id, { open_revs: 'all' }).then(function (doc) {
					var latestRev = doc[0].ok._rev; // HACK: this will stop undo working where there are unresolved conflicts
					if (revision.newRev !== latestRev) {
						throw error({
							status: 409,
							error: 'conflict',
							reason: 'The document has changed since this undoID was issued'
						});
					}
					return db.get(revision.id, { rev: revision.oldRev }).then(function (doc) {
						if (!revision.oldRev) { doc._deleted = true; }
						doc._rev = revision.newRev;
						return doc;
					});
				});
			})).then(function (docs) {
				return origBulkDocs.call(db, docs);
			}).then(function () {
				delete undoDoc.undos[undoId];
				return origBulkDocs.call(db, [undoDoc]);
			});
		}).then(function () {
			return { id: undoId, ok: true };
		});
	};

	db.clearUndo = function () {
		return db.get('_local/_undo').then(function (doc) {
			doc._deleted = true;
			return origBulkDocs.call(db, [doc]);
		}).catch(function (err) {
			if (err.status !== 404) { throw err; }
			// already deleted
		});
	};

	wrappers.installWrapperMethods(db, { bulkDocs: wrapUndo });
};
exports.transform = exports.filter = function transform(config) {
  var db = this;

  var incoming = function (doc) {
    if (!isUntransformable(doc) && config.incoming) {
      return config.incoming(utils.clone(doc));
    }
    return doc;
  };
  var outgoing = function (doc) {
    if (!isUntransformable(doc) && config.outgoing) {
      return config.outgoing(utils.clone(doc));
    }
    return doc;
  };

  var handlers = {};

  if (db.type() === 'http') {
    handlers.put = function (orig, args) {
      args.doc = incoming(args.doc);
      return orig();
    };
    handlers.query = function (orig) {
      return orig().then(function (res) {
        res.rows.forEach(function (row) {
          if (row.doc) {
            row.doc = outgoing(row.doc);
          }
        });

        return res;
      });
    };
  }

  handlers.get = function (orig) {
    return orig().then(function (res) {
      if (Array.isArray(res)) {
        // open_revs style, it's a list of docs
        res.forEach(function (doc) {
          if (doc.ok) {
            doc.ok = outgoing(doc.ok);
          }
        });
      } else {
        res = outgoing(res);
      }
      return res;
    });
  };

  handlers.bulkDocs = function (orig, args) {
    for (var i = 0; i < args.docs.length; i++) {
      args.docs[i] = incoming(args.docs[i]);
    }
    return orig();
  };

  handlers.allDocs = function (orig) {
    return orig().then(function (res) {
      res.rows.forEach(function (row) {
        if (row.doc) {
          row.doc = outgoing(row.doc);
        }
      });
      return res;
    });
  };

  handlers.changes = function (orig, args) {
    function modifyChange(change) {
      if (change.doc) {
        change.doc = outgoing(change.doc);
      }
      return change;
    }

    function modifyChanges(res) {
      res.results = res.results.map(modifyChange);
      return res;
    }

    if (args.options.complete) {
      var origComplete = args.options.complete;
      args.options.complete = function (err, res) {
        /* istanbul ignore next */
        if (err) {
          return origComplete(err);
        }
        origComplete(null, modifyChanges(res));
      };
    }

    var changes = orig();
    // override some events
    var origOn = changes.on;
    changes.on = function (event, listener) {
      if (event === 'change') {
        return origOn.apply(changes, [event, function (change) {
          listener(modifyChange(change));
        }]);
      } else if (event === 'complete') {
        return origOn.apply(changes, [event, function (res) {
          listener(modifyChanges(res));
        }]);
      }
      return origOn.apply(changes, [event, listener]);
    };

    var origThen = changes.then;
    changes.then = function (resolve, reject) {
      return origThen.apply(changes, [function (res) {
        resolve(modifyChanges(res));
      }, reject]);
    };
    return changes;
  };
  wrappers.installWrapperMethods(db, handlers);
};
Ejemplo n.º 8
0
exports.transform = exports.filter = function transform(config) {
  var db = this;

  var incoming = function (doc) {
    if (!isUntransformable(doc) && config.incoming) {
      return config.incoming(utils.clone(doc));
    }
    return doc;
  };
  var outgoing = function (doc) {
    if (!isUntransformable(doc) && config.outgoing) {
      return config.outgoing(utils.clone(doc));
    }
    return doc;
  };

  var handlers = {};

  if (db.type() === 'http') {
    handlers.query = function (orig) {
      var none = {};
      return orig().then(function (res) {
        return utils.Promise.all(res.rows.map(function (row) {
          if (row.doc) {
            return outgoing(row.doc);
          }
          return none;
        })).then(function (resp) {
          resp.forEach(function (doc, i) {
            if (doc === none) {
              return;
            }
            res.rows[i].doc = doc;
          });
          return res;
        });
      });
    };
  }

  handlers.get = function (orig) {
    return orig().then(function (res) {
      if (Array.isArray(res)) {
        var none = {};
        // open_revs style, it's a list of docs
        return utils.Promise.all(res.map(function (row) {
          if (row.ok) {
            return outgoing(row.ok);
          }
          return none;
        })).then(function (resp) {
          resp.forEach(function (doc, i) {
            if (doc === none) {
              return;
            }
            res[i].ok = doc;
          });
          return res;
        });
      } else {
        return outgoing(res);
      }
    });
  };

  handlers.bulkDocs = function (orig, args) {
    for (var i = 0; i < args.docs.length; i++) {
      args.docs[i] = incoming(args.docs[i]);
    }
    return Promise.all(args.docs).then(function (docs) {
      args.docs = docs;
      return orig();
    });
  };

  handlers.allDocs = function (orig) {
    return orig().then(function (res) {
      var none = {};
      return utils.Promise.all(res.rows.map(function (row) {
        if (row.doc) {
          return outgoing(row.doc);
        }
        return none;
      })).then(function (resp) {
        resp.forEach(function (doc, i) {
          if (doc === none) {
            return;
          }
          res.rows[i].doc = doc;
        });
        return res;
      });
    });
  };

  handlers.bulkGet = function (orig) {
    return orig().then(function (res) {
      var none = {};
      return utils.Promise.all(res.results.map(function (result) {
        if (result.id && result.docs && Array.isArray(result.docs)) {
          return {
            docs: result.docs.map(function(doc) {
              if (doc.ok) {
                return {ok: outgoing(doc.ok)};
              } else {
                return doc;
              }
            }),
            id: result.id
          };
        } else {
          return none;
        }
      })).then(function (results) {
        return {results: results};
      });
    });
  };
  
  handlers.changes = function (orig) {
    function modifyChange(change) {
      if (change.doc) {
        return utils.Promise.resolve(outgoing(change.doc)).then(function (doc) {
          change.doc = doc;
          return change;
        });
      }
      return utils.Promise.resolve(change);
    }

    function modifyChanges(res) {
      if (res.results) {
        return utils.Promise.all(res.results.map(modifyChange)).then(function (results) {
          res.results = results;
          return res;
        });
      }
      return utils.Promise.resolve(res);
    }

    var changes = orig();
    // override some events
    var origOn = changes.on;
    changes.on = function (event, listener) {
      if (event === 'change') {
        return origOn.apply(changes, [event, function (change) {
          modifyChange(change).then(function (resp) {
            immediate(function () {
              listener(resp);
            });
          });
        }]);
      } else if (event === 'complete') {
        return origOn.apply(changes, [event, function (res) {
          modifyChanges(res).then(function (resp) {
            process.nextTick(function () {
              listener(resp);
            });
          });
        }]);
      }
      return origOn.apply(changes, [event, listener]);
    };

    var origThen = changes.then;
    changes.then = function (resolve, reject) {
      return origThen.apply(changes, [function (res) {
        return modifyChanges(res).then(resolve, reject);
      }, reject]);
    };
    return changes;
  };
  wrappers.installWrapperMethods(db, handlers);
};