Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions lib/application.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,10 @@ Application._createApplication = function(client, item, callback){
item = client;
client = new Client();
}
var request = client.createPostRequest(client.concatAccountPath(APPLICATION_PATH), {application: item});
request.buffer().then(res =>{
client.sendRequest(() => client.createPostRequest(client.concatAccountPath(APPLICATION_PATH), {application: item}), function(err, res){
if(err){
return callback(err);
}
if(res.ok && res.headers.location){
Client.getIdFromLocationHeader(res.headers.location, function(err, id){
if(err){
Expand All @@ -64,8 +66,6 @@ Application._createApplication = function(client, item, callback){
else{
client.checkResponse(res, callback);
}
}).catch(err => {
return callback(err);
});
};

Expand Down
108 changes: 68 additions & 40 deletions lib/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,13 @@ class Client {

// Start background token refresh if using OAuth and auto-refresh is enabled
if (this.autoRefreshToken && this.clientId && this.clientSecret && !this.tempAccessToken) {
this.tokenReadyPromise = new Promise((resolve) => {
this.tokenReadyPromise = new Promise((resolve, reject) => {
this._tokenReadyResolve = resolve;
this._tokenReadyReject = reject;
});
this._scheduleTokenRefresh();
// avoid an unhandled rejection if the fetch fails before any request awaits it
this.tokenReadyPromise.catch(() => {});
process.nextTick(() => this._refreshToken());
}
}

Expand Down Expand Up @@ -199,52 +202,77 @@ class Client {
return this.prepareRequest(superagent.del(this.prepareUrl(path)));
}

makeRequest (method) {
var callback = arguments[arguments.length - 1];
var args = Array.prototype.slice.call(arguments, 1, arguments.length - 1);
var self = this;

const executeRequest = (isRetry = false) => {
var request = self["create" + method[0].toUpperCase() + method.substr(1).toLowerCase() + "Request"].apply(self, args);
request.buffer().then(res => {
self.checkResponse(res, callback);
}).catch(err => {
// Check for 401 error and no retry yet
if (!isRetry && err.status === 401 && self.autoRefreshToken && self.clientId && self.clientSecret) {
console.log("Got 401, refreshing token and retrying...");
self.tempAccessToken = null;
self.tempAccessTokenExpiration = null;

self.tokenReadyPromise = new Promise((resolve, reject) => {
self._tokenReadyResolve = resolve;
self._tokenReadyReject = reject;
});
self._refreshToken();

self.tokenReadyPromise.then(() => {
executeRequest(true);
}).catch((refreshErr) => {
console.error("Token refresh failed during retry:", refreshErr);
return callback(err); // Return original 401
});
} else {
return callback(err);
}
});
buildAuthenticatedRequest (buildRequest, callback) {
const build = (tokenErr) => {
let request;
try {
request = buildRequest();
} catch (err) {
return callback(tokenErr || err);
}
callback(null, request);
};

if (this.tokenReadyPromise) {
this.tokenReadyPromise.then(() => {
executeRequest();
}).catch((err) => {
this.tokenReadyPromise.then(() => build(), (err) => {
console.error("Token fetch failed:", err);
executeRequest();
build(err);
});
} else {
executeRequest();
build();
}
}

sendRequest (buildRequest, callback) {
const execute = (isRetry) => {
this.buildAuthenticatedRequest(buildRequest, (err, request) => {
if (err) {
return callback(err);
}
request.buffer().then((res) => callback(null, res), (err) => {
if (!isRetry && this._canRefreshOn401(err)) {
console.log("Got 401, refreshing token and retrying...");
return this._forceTokenRefresh().then(() => execute(true), (refreshErr) => {
console.error("Token refresh failed during retry:", refreshErr);
callback(err);
});
}
callback(err);
});
});
};
execute(false);
}

_canRefreshOn401 (err) {
return err.status === 401 && this.autoRefreshToken && this.clientId && this.clientSecret;
}

_forceTokenRefresh () {
this.tempAccessToken = null;
this.tempAccessTokenExpiration = null;
const tokenReadyPromise = new Promise((resolve, reject) => {
this._tokenReadyResolve = resolve;
this._tokenReadyReject = reject;
});
this.tokenReadyPromise = tokenReadyPromise;
this._refreshToken();
return tokenReadyPromise;
}

makeRequest (method) {
const callback = arguments[arguments.length - 1];
const args = Array.prototype.slice.call(arguments, 1, arguments.length - 1);
const createRequest = this["create" + method[0].toUpperCase() + method.substr(1).toLowerCase() + "Request"];

this.sendRequest(() => createRequest.apply(this, args), (err, res) => {
if (err) {
return callback(err);
}
this.checkResponse(res, callback);
});
}

checkResponse (res, callback) {
let defaultHandler = function(parsedData){
if (!res.ok) {
Expand Down
6 changes: 4 additions & 2 deletions lib/csrOrder.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,10 @@ CsrOrder.prototype.getNotes = function(callback){

CsrOrder.prototype.addNote = function(note, callback){
var self = this;
var request = this.client.createPostRequest(this.client.concatAccountPath(CSR_ORDER_PATH + "/" + this.id + "/notes"), {note: note});
request.buffer().then(res =>{
this.client.sendRequest(() => this.client.createPostRequest(this.client.concatAccountPath(CSR_ORDER_PATH + "/" + this.id + "/notes"), {note: note}), function(err, res){
if(err){
return callback(err);
}
if(res.ok && res.headers.location){
Client.getIdFromLocationHeader(res.headers.location, function(err, id){
if(err){
Expand Down
8 changes: 4 additions & 4 deletions lib/disconnect.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,10 @@ Disconnect.prototype.getNotes = function(callback){

Disconnect.prototype.addNote = function(note, callback){
var self = this;
var request = this.client.createPostRequest(this.client.concatAccountPath(DISCONNECT_PATH + "/" + this.id + "/notes"), {note: note});
request.buffer().then(res => {
this.client.sendRequest(() => this.client.createPostRequest(this.client.concatAccountPath(DISCONNECT_PATH + "/" + this.id + "/notes"), {note: note}), function(err, res){
if(err){
return callback(err);
}
if(res.ok && res.headers.location){
Client.getIdFromLocationHeader(res.headers.location, function(err, id){
if(err){
Expand All @@ -86,8 +88,6 @@ Disconnect.prototype.addNote = function(note, callback){
else{
self.client.checkResponse(res, callback);
}
}).catch(err => {
return callback(err);
});
};

Expand Down
6 changes: 4 additions & 2 deletions lib/dlda.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ Dlda.create = function(client, item, callback){
item = client;
client = new Client();
}
var request = client.createPostRequest(client.concatAccountPath(DLDA_PATH), {dldaOrder: item});
request.buffer().then(res => {
client.sendRequest(() => client.createPostRequest(client.concatAccountPath(DLDA_PATH), {dldaOrder: item}), function(err, res){
if(err){
return callback(err);
}
if(res.ok && res.headers.location){
Client.getIdFromLocationHeader(res.headers.location, function(err,id){
if(err){
Expand Down
86 changes: 62 additions & 24 deletions lib/importTnOrder.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,19 +79,26 @@ function sendFile(request, file, mediaType, callback){
else if(Buffer.isBuffer(file)){
stream = streamifier.createReadStream(file);
}
else if(typeof file.pipe === "function" && typeof file.read === "function" && typeof file.on === "function"){
else if(file && typeof file.pipe === "function" && typeof file.read === "function" && typeof file.on === "function"){
stream = file;
}
if(stream){
request.on("response", callback);
request.on("error", function(err, result){
return err;
});
stream.pipe(request);

return;
if(!stream){
return callback(new Error("Invalid data to send"));
}
throw new Error("Invalid data to send");
var done = false;
// a 4xx/5xx emits "response" then "error"; only report the first
var finish = function(err, res){
if(!done){
done = true;
callback(err, res);
}
};
request.on("response", function(res){
finish(null, res);
});
request.on("error", finish);
stream.on("error", finish);
stream.pipe(request);
}

ImportTnOrder.prototype.createFile = function(file, mediaType, callback){
Expand All @@ -100,18 +107,25 @@ ImportTnOrder.prototype.createFile = function(file, mediaType, callback){
mediaType = null;
}
var client = this.client;
var request = client.createPostRequest(client.concatAccountPath(IMPORT_TN_ORDER_PATH + "/" + this.id + "/" + LOAS_PATH));
sendFile(request, file, mediaType, function(res){
client.checkResponse(res, function(err, result){
client.buildAuthenticatedRequest(() => client.createPostRequest(client.concatAccountPath(IMPORT_TN_ORDER_PATH + "/" + this.id + "/" + LOAS_PATH)), function(err, request){
if(err){
return callback(err);
}
sendFile(request, file, mediaType, function(err, res){
if(err){
return callback(err);
}
if (typeof result !== 'undefined') {
return callback(null, result.filename);
}
else {
return callback(null, "");
}
client.checkResponse(res, function(err, result){
if(err){
return callback(err);
}
if (typeof result !== 'undefined') {
return callback(null, result.filename);
}
else {
return callback(null, "");
}
});
});
});
};
Expand All @@ -121,10 +135,17 @@ ImportTnOrder.prototype.updateFile = function(fileName, file, mediaType, callbac
callback = mediaType;
mediaType = null;
}
var request = this.client.createPutRequest(this.client.concatAccountPath(IMPORT_TN_ORDER_PATH + "/" + this.id + "/" + LOAS_PATH + "/" + fileName));
var client = this.client;
sendFile(request, file, mediaType, function(res){
client.checkResponse(res, callback);
client.buildAuthenticatedRequest(() => client.createPutRequest(client.concatAccountPath(IMPORT_TN_ORDER_PATH + "/" + this.id + "/" + LOAS_PATH + "/" + fileName)), function(err, request){
if(err){
return callback(err);
}
sendFile(request, file, mediaType, function(err, res){
if(err){
return callback(err);
}
client.checkResponse(res, callback);
});
});
};

Expand All @@ -150,8 +171,25 @@ ImportTnOrder.prototype.getFiles = function(metadata, callback){
});
};

ImportTnOrder.prototype.getFile = function(fileName, destination){
var request = this.client.createGetRequest(this.client.concatAccountPath(IMPORT_TN_ORDER_PATH + "/" + this.id + "/" + LOAS_PATH + "/" + fileName));
ImportTnOrder.prototype.getFile = function(fileName, destination, callback){
if(typeof destination === "function"){
callback = destination;
destination = null;
}
var client = this.client;
var buildRequest = () => client.createGetRequest(client.concatAccountPath(IMPORT_TN_ORDER_PATH + "/" + this.id + "/" + LOAS_PATH + "/" + fileName));
if(!callback){
return pipeToDestination(buildRequest(), destination);
}
client.buildAuthenticatedRequest(buildRequest, function(err, request){
if(err){
return callback(err);
}
callback(null, pipeToDestination(request, destination));
});
}

function pipeToDestination(request, destination){
if(destination){
var stream = null;
if(typeof destination === "string"){
Expand Down
6 changes: 4 additions & 2 deletions lib/importToAccount.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@ ImportToAccount.create = function(client, item, callback){
item = client;
client = new Client();
}
var request = client.createPostRequest(client.concatAccountPath(IMPORT_TO_ACCOUNT_PATH), {importToAccountNumberOrder: item});
request.buffer().then(res =>{
client.sendRequest(() => client.createPostRequest(client.concatAccountPath(IMPORT_TO_ACCOUNT_PATH), {importToAccountNumberOrder: item}), function(err, res){
if(err){
return callback(err);
}
if(res.ok){
callback(null, res.body)
}else {
Expand Down
6 changes: 4 additions & 2 deletions lib/lidbs.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ Lidbs.create = function(client, item, callback){
item = client;
client = new Client();
}
var request = client.createPostRequest(client.concatAccountPath(LIDBS_ORDER_PATH), {lidbOrder: item});
request.buffer().then(res =>{
client.sendRequest(() => client.createPostRequest(client.concatAccountPath(LIDBS_ORDER_PATH), {lidbOrder: item}), function(err, res){
if(err){
return callback(err);
}
if(res.ok && res.headers.location){
Client.getIdFromLocationHeader(res.headers.location, function(err,id){
if(err){
Expand Down
12 changes: 8 additions & 4 deletions lib/lsrOrder.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,10 @@ LsrOrder.create = function(client, item, callback){
item = client;
client = new Client();
}
var request = client.createPostRequest(client.concatAccountPath(LSR_ORDER_PATH), {lsrOrder: item});
request.buffer().then(res => {
client.sendRequest(() => client.createPostRequest(client.concatAccountPath(LSR_ORDER_PATH), {lsrOrder: item}), function(err, res){
if(err){
return callback(err);
}
if(res.ok && res.headers.location){
Client.getIdFromLocationHeader(res.headers.location, function(err,id){
if(err){
Expand Down Expand Up @@ -83,8 +85,10 @@ LsrOrder.prototype.getNotes = function(callback){

LsrOrder.prototype.addNote = function(note, callback){
var self = this;
var request = this.client.createPostRequest(this.client.concatAccountPath(LSR_ORDER_PATH + "/" + this.id + "/notes"), {note: note});
request.buffer().then(res =>{
this.client.sendRequest(() => this.client.createPostRequest(this.client.concatAccountPath(LSR_ORDER_PATH + "/" + this.id + "/notes"), {note: note}), function(err, res){
if(err){
return callback(err);
}
if(res.ok && res.headers.location){
Client.getIdFromLocationHeader(res.headers.location, function(err, id){
if(err){
Expand Down
8 changes: 4 additions & 4 deletions lib/order.js
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,10 @@ Order.prototype.getNotes = function(callback){

Order.prototype.addNote = function(note, callback){
var self = this;
var request = this.client.createPostRequest(this.client.concatAccountPath(ORDER_PATH + "/" + this.id + "/notes"), {note: note});
request.buffer().then(res => {
this.client.sendRequest(() => this.client.createPostRequest(this.client.concatAccountPath(ORDER_PATH + "/" + this.id + "/notes"), {note: note}), function(err, res){
if(err){
return callback(err);
}
if(res.ok && res.headers.location){
Client.getIdFromLocationHeader(res.headers.location, function(err, id){
if(err){
Expand All @@ -135,8 +137,6 @@ Order.prototype.addNote = function(note, callback){
else{
self.client.checkResponse(res, callback);
}
}).catch(err => {
return callback(err);
});
};

Expand Down
Loading