| "use strict"; |
| |
| var inherits = require('inherits'); |
| inherits(PouchError, Error); |
| |
| function PouchError(opts) { |
| Error.call(opts.reason); |
| this.status = opts.status; |
| this.name = opts.error; |
| this.message = opts.reason; |
| this.error = true; |
| } |
| |
| PouchError.prototype.toString = function () { |
| return JSON.stringify({ |
| status: this.status, |
| name: this.name, |
| message: this.message |
| }); |
| }; |
| |
| exports.UNAUTHORIZED = new PouchError({ |
| status: 401, |
| error: 'unauthorized', |
| reason: "Name or password is incorrect." |
| }); |
| |
| exports.MISSING_BULK_DOCS = new PouchError({ |
| status: 400, |
| error: 'bad_request', |
| reason: "Missing JSON list of 'docs'" |
| }); |
| |
| exports.MISSING_DOC = new PouchError({ |
| status: 404, |
| error: 'not_found', |
| reason: 'missing' |
| }); |
| |
| exports.REV_CONFLICT = new PouchError({ |
| status: 409, |
| error: 'conflict', |
| reason: 'Document update conflict' |
| }); |
| |
| exports.INVALID_ID = new PouchError({ |
| status: 400, |
| error: 'invalid_id', |
| reason: '_id field must contain a string' |
| }); |
| |
| exports.MISSING_ID = new PouchError({ |
| status: 412, |
| error: 'missing_id', |
| reason: '_id is required for puts' |
| }); |
| |
| exports.RESERVED_ID = new PouchError({ |
| status: 400, |
| error: 'bad_request', |
| reason: 'Only reserved document ids may start with underscore.' |
| }); |
| |
| exports.NOT_OPEN = new PouchError({ |
| status: 412, |
| error: 'precondition_failed', |
| reason: 'Database not open' |
| }); |
| |
| exports.UNKNOWN_ERROR = new PouchError({ |
| status: 500, |
| error: 'unknown_error', |
| reason: 'Database encountered an unknown error' |
| }); |
| |
| exports.BAD_ARG = new PouchError({ |
| status: 500, |
| error: 'badarg', |
| reason: 'Some query argument is invalid' |
| }); |
| |
| exports.INVALID_REQUEST = new PouchError({ |
| status: 400, |
| error: 'invalid_request', |
| reason: 'Request was invalid' |
| }); |
| |
| exports.QUERY_PARSE_ERROR = new PouchError({ |
| status: 400, |
| error: 'query_parse_error', |
| reason: 'Some query parameter is invalid' |
| }); |
| |
| exports.DOC_VALIDATION = new PouchError({ |
| status: 500, |
| error: 'doc_validation', |
| reason: 'Bad special document member' |
| }); |
| |
| exports.BAD_REQUEST = new PouchError({ |
| status: 400, |
| error: 'bad_request', |
| reason: 'Something wrong with the request' |
| }); |
| |
| exports.NOT_AN_OBJECT = new PouchError({ |
| status: 400, |
| error: 'bad_request', |
| reason: 'Document must be a JSON object' |
| }); |
| |
| exports.DB_MISSING = new PouchError({ |
| status: 404, |
| error: 'not_found', |
| reason: 'Database not found' |
| }); |
| |
| exports.IDB_ERROR = new PouchError({ |
| status: 500, |
| error: 'indexed_db_went_bad', |
| reason: 'unknown' |
| }); |
| |
| exports.WSQ_ERROR = new PouchError({ |
| status: 500, |
| error: 'web_sql_went_bad', |
| reason: 'unknown' |
| }); |
| |
| exports.LDB_ERROR = new PouchError({ |
| status: 500, |
| error: 'levelDB_went_went_bad', |
| reason: 'unknown' |
| }); |
| |
| exports.FORBIDDEN = new PouchError({ |
| status: 403, |
| error: 'forbidden', |
| reason: 'Forbidden by design doc validate_doc_update function' |
| }); |
| |
| exports.INVALID_REV = new PouchError({ |
| status: 400, |
| error: 'bad_request', |
| reason: 'Invalid rev format' |
| }); |
| |
| exports.FILE_EXISTS = new PouchError({ |
| status: 412, |
| error: 'file_exists', |
| reason: 'The database could not be created, the file already exists.' |
| }); |
| |
| exports.MISSING_STUB = new PouchError({ |
| status: 412, |
| error: 'missing_stub' |
| }); |
| |
| exports.error = function (error, reason, name) { |
| function CustomPouchError(reason) { |
| // inherit error properties from our parent error manually |
| // so as to allow proper JSON parsing. |
| /* jshint ignore:start */ |
| for (var p in error) { |
| if (typeof error[p] !== 'function') { |
| this[p] = error[p]; |
| } |
| } |
| /* jshint ignore:end */ |
| if (name !== undefined) { |
| this.name = name; |
| } |
| if (reason !== undefined) { |
| this.reason = reason; |
| } |
| } |
| CustomPouchError.prototype = PouchError.prototype; |
| return new CustomPouchError(reason); |
| }; |
| |
| // Find one of the errors defined above based on the value |
| // of the specified property. |
| // If reason is provided prefer the error matching that reason. |
| // This is for differentiating between errors with the same name and status, |
| // eg, bad_request. |
| exports.getErrorTypeByProp = function (prop, value, reason) { |
| var errors = exports; |
| var keys = Object.keys(errors).filter(function (key) { |
| var error = errors[key]; |
| return typeof error !== 'function' && error[prop] === value; |
| }); |
| var key = reason && keys.filter(function (key) { |
| var error = errors[key]; |
| return error.message === reason; |
| })[0] || keys[0]; |
| return (key) ? errors[key] : null; |
| }; |
| |
| exports.generateErrorFromResponse = function (res) { |
| var error, errName, errType, errMsg, errReason; |
| var errors = exports; |
| |
| errName = (res.error === true && typeof res.name === 'string') ? |
| res.name : |
| res.error; |
| errReason = res.reason; |
| errType = errors.getErrorTypeByProp('name', errName, errReason); |
| |
| if (res.missing || |
| errReason === 'missing' || |
| errReason === 'deleted' || |
| errName === 'not_found') { |
| errType = errors.MISSING_DOC; |
| } else if (errName === 'doc_validation') { |
| // doc validation needs special treatment since |
| // res.reason depends on the validation error. |
| // see utils.js |
| errType = errors.DOC_VALIDATION; |
| errMsg = errReason; |
| } else if (errName === 'bad_request' && errType.message !== errReason) { |
| // if bad_request error already found based on reason don't override. |
| errType = errors.BAD_REQUEST; |
| } |
| |
| // fallback to error by statys or unknown error. |
| if (!errType) { |
| errType = errors.getErrorTypeByProp('status', res.status, errReason) || |
| errors.UNKNOWN_ERROR; |
| } |
| |
| error = errors.error(errType, errReason, errName); |
| |
| // Keep custom message. |
| if (errMsg) { |
| error.message = errMsg; |
| } |
| |
| // Keep helpful response data in our error messages. |
| if (res.id) { |
| error.id = res.id; |
| } |
| if (res.status) { |
| error.status = res.status; |
| } |
| if (res.missing) { |
| error.missing = res.missing; |
| } |
| |
| return error; |
| }; |