KyleAMathews / superagent-bluebird-promise

Add promise support to superagent using Bluebird
MIT License
182 stars 37 forks source link

Broken while using bluebird 3 #37

Closed janpieterz closed 8 years ago

janpieterz commented 9 years ago

When updating to bluebird 3 the package breaks: http://bluebirdjs.com/docs/new-in-bluebird-3.html and http://bluebirdjs.com/docs/api/cancellation.html

I don't have time to check it out further currently, just wanted to let you know.

veke commented 8 years ago

Confirmed. This installs bluebird 3 as package dependency => not compatible

janpieterz commented 8 years ago

@veke Until this library gets fixed I have a version that does work with version 3. @KyleAMathews I'd be more than happy to open a pull request if you're willing to break compatibility with <3

// From https://gist.github.com/epeli/11209665

var Promise = require("bluebird");

// So you can `var request = require("superagent-bluebird-promise")`
var superagent = module.exports = require("superagent");
var Request = superagent.Request;

Promise.config({
    // Enable warnings.
    warnings: true,
    // Enable long stack traces.
    longStackTraces: true,
    // Enable cancellation.
    cancellation: true
});
// Create custom error type.
// Create a new object, that prototypally inherits from the Error constructor.
var SuperagentPromiseError = function(message, originalError) {
  var stack;
  this.message = message;
  this.name = 'SuperagentPromiseError';
  this.originalError = originalError;

  if (Error.captureStackTrace) {
    Error.captureStackTrace(this, this.constructor);
    stack = this.stack;
  }
  else {
    stack = (new Error(message)).stack;
  }

  if (Object.defineProperty) {
    Object.defineProperty(this, 'stack', {
      get: function() {
        if (this.originalError) {
          return stack + '\nCaused by:  ' + this.originalError.stack;
        }

        return stack;
      }
    });
  }
};

SuperagentPromiseError.prototype = new Error();
SuperagentPromiseError.prototype.constructor = SuperagentPromiseError;
superagent.SuperagentPromiseError = SuperagentPromiseError;

/**
 * @namespace utils
 * @class Superagent
 */

/**
 *
 * Add promise support for superagent/supertest
 *
 * Call .promise() to return promise for the request
 *
 * @method then
 * @return {Bluebird.Promise}
 */
Request.prototype.promise = function() {
  var req = this;
  var error;

  return new Promise(function(resolve, reject, onCancel) {
      req.end(function(err, res) {
        if (typeof res !== "undefined" && res.status >= 400) {
          var msg = 'cannot ' + req.method + ' ' + req.url + ' (' + res.status + ')';
          error = new SuperagentPromiseError(msg);
          error.status = res.status;
          error.body = res.body;
          error.res = res;
          reject(error);
        } else if (err) {
          reject(new SuperagentPromiseError('Bad request', err));
        } else {
          resolve(res);
        }
      });
      onCancel(function() {
           req.abort();
       });
    })
    .catch(Promise.CancellationError, function(err) {      
      req.abort();
      throw err;
    });
};

/**
 *
 * Make superagent requests Promises/A+ conformant
 *
 * Call .then([onFulfilled], [onRejected]) to register callbacks
 *
 * @method then
 * @param {function} [onFulfilled]
 * @param {function} [onRejected]
 * @return {Bluebird.Promise}
 */
Request.prototype.then = function() {
  var promise = this.promise();
  return promise.then.apply(promise, arguments);
};
KyleAMathews commented 8 years ago

Yeah, a PR and a new major release would be great. Thanks! On Mon, Nov 9, 2015 at 6:11 AM Jan-Pieter Zoutewelle < notifications@github.com> wrote:

@veke https://github.com/veke Until this library gets fixed I have a version that does work with version 3. @KyleAMathews https://github.com/KyleAMathews I'd be more than happy to open a pull request if you're willing to break compatibility with <3

// From https://gist.github.com/epeli/11209665 var Promise = require("bluebird"); // So you can var request = require("superagent-bluebird-promise")var superagent = module.exports = require("superagent");var Request = superagent.Request;

Promise.config({ // Enable warnings. warnings: true, // Enable long stack traces. longStackTraces: true, // Enable cancellation. cancellation: true });// Create custom error type.// Create a new object, that prototypally inherits from the Error constructor.var SuperagentPromiseError = function(message, originalError) { var stack; this.message = message; this.name = 'SuperagentPromiseError'; this.originalError = originalError;

if (Error.captureStackTrace) { Error.captureStackTrace(this, this.constructor); stack = this.stack; } else { stack = (new Error(message)).stack; }

if (Object.defineProperty) { Object.defineProperty(this, 'stack', { get: function() { if (this.originalError) { return stack + '\nCaused by: ' + this.originalError.stack; }

    return stack;
  }
});

} }; SuperagentPromiseError.prototype = new Error();SuperagentPromiseError.prototype.constructor = SuperagentPromiseError; superagent.SuperagentPromiseError = SuperagentPromiseError; /* * @namespace utils * @class Superagent / /* * * Add promise support for superagent/supertest * * Call .promise() to return promise for the request * * @method then * @return {Bluebird.Promise} /Request.prototype.promise = function() { var req = this; var error;

return new Promise(function(resolve, reject, onCancel) { req.end(function(err, res) { if (typeof res !== "undefined" && res.status >= 400) { var msg = 'cannot ' + req.method + ' ' + req.url + ' (' + res.status + ')'; error = new SuperagentPromiseError(msg); error.status = res.status; error.body = res.body; error.res = res; reject(error); } else if (err) { reject(new SuperagentPromiseError('Bad request', err)); } else { resolve(res); } }); onCancel(function() { req.abort(); }); }) .catch(Promise.CancellationError, function(err) { req.abort(); throw err; }); }; /* * * Make superagent requests Promises/A+ conformant * * Call .then([onFulfilled], [onRejected]) to register callbacks * * @method then * @param {function} [onFulfilled] * @param {function} [onRejected] * @return {Bluebird.Promise} /Request.prototype.then = function() { var promise = this.promise(); return promise.then.apply(promise, arguments); };

— Reply to this email directly or view it on GitHub https://github.com/KyleAMathews/superagent-bluebird-promise/issues/37#issuecomment-155073244 .

matthewgertner commented 8 years ago

+1 and BTW you definitely shouldn't use a * for the peerDependencies versions. This caused our app to break on our CI server as soon as Bluebird 3 came out. You should lock down the peerDependencies to a known compatible version.

MMRandy commented 8 years ago

+1 What's the status of the PR, is this happening anytime soon? Thx.

janpieterz commented 8 years ago

A pull request has been opened here: https://github.com/KyleAMathews/superagent-bluebird-promise/pull/42

On 19 nov. 2015, at 16:55, MMRandy notifications@github.com wrote:

+1 What's the status of the PR, is this happening anytime soon? Thx.

— Reply to this email directly or view it on GitHub.

KyleAMathews commented 8 years ago

So as it turns out, this library was broken under Bluebird 2.9.x as well. I set the peerDependency for now to 2.8.x. https://github.com/KyleAMathews/superagent-bluebird-promise/commit/b44fd4db7fbdc37e5694cc2a04945669668ec784

MatthewPikar commented 8 years ago

+1 This would be great!

heycalmdown commented 8 years ago

+1

trueter commented 8 years ago

Lets make it happen.

KyleAMathews commented 8 years ago

Forgot to close this. #42 was merged.