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
536 changes: 333 additions & 203 deletions dist/workfront.js

Large diffs are not rendered by default.

7 changes: 3 additions & 4 deletions dist/workfront.min.js

Large diffs are not rendered by default.

Binary file added examples/node/image.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
69 changes: 69 additions & 0 deletions examples/node/upload-an-image.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/**
* Copyright 2015 Workfront
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/**
* Logs in, then uploads an image and attaches it to a task
*/

var ApiFactory = require('./../../').ApiFactory;
var util = require('util');
var fs = require('fs');

var stream = fs.createReadStream('./image.jpg');

var instance = ApiFactory.getInstance({
url: 'http://localhost:8080',
version: '4.0'
});

util.log('Logging in ...');
instance.login('admin@user.attask', 'user').then(
function() {
util.log('Uploading a sweet picture...');
instance.upload(stream, {filename: 'sweet.jpg', contentType: 'image/jpeg'}).then(
function(data) {
util.log('Upload success. Received data:');
console.log(util.inspect(data, {colors:true}));

instance.create('DOCU', {
name: 'sweet.jpg',
handle: data.handle,
docObjCode: 'TASK',

//Obviously this will only work with a real TASK ID
objID: '561ffe36000006ee9f8453a6c921d636'
}).then(
function(data) {
util.log('Document creation success. Received data:');
console.log(util.inspect(data, {colors:true}));
},
function(error) {
util.log('Document creation failure. Received data:');
console.log(util.inspect(error, {colors:true}));
}
);
},
function(error) {
util.log('Upload failure. Received data:');
console.log(util.inspect(error, {colors:true}));
}
);
},
function(error) {
util.log('Login failure. Received data:');
console.log(util.inspect(error, {colors:true}));
}
);
1 change: 1 addition & 0 deletions gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ gulp.task('build', 'Generates browser-ready version for API in '+BUILD_DIR, ['cl
}
)
.ignore('promise/polyfill')
.exclude('./plugins/upload')
.bundle()
.pipe(source('workfront.js'))
.pipe(buffer())
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"description": "A Workfront API for the Node.js and the Web",
"main": "index.js",
"dependencies": {
"form-data": "0.2.0",
"promise": "^6.0.1"
},
"devDependencies": {
Expand Down
8 changes: 6 additions & 2 deletions src/Api.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,14 @@ require('./plugins/remove')(Api);
require('./plugins/report')(Api);
require('./plugins/count')(Api);
require('./plugins/copy')(Api);
require('./plugins/upload')(Api);
require('./plugins/execute')(Api);
require('./plugins/namedQuery')(Api);
require('./plugins/metadata')(Api);
require('./plugins/apiKey')(Api);

module.exports = Api;
if(typeof(window)==='undefined'){
//These plugins only work in node
require('./plugins/upload')(Api);
}

module.exports = Api;
57 changes: 30 additions & 27 deletions src/plugins/request.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,33 @@ module.exports = function(Api) {
return method !== Api.Methods.GET && method !== Api.Methods.PUT;
};

Api.prototype._handleResponse = function(resolve, reject){
return function (response) {
var body = '';
if (typeof response.setEncoding === 'function') {
response.setEncoding('utf8');
}
response.on('data', function (chunk) {
body += chunk;
});
response.on('end', function () {
var data;
try {
data = JSON.parse(body);
}
catch(e) {
reject(body);
return;
}
if (data.error) {
reject(data);
} else {
resolve(data.data);
}
});
};
};

Api.prototype.request = function(path, params, fields, method) {
fields = fields || [];
if (typeof fields === 'string') {
Expand All @@ -38,7 +65,7 @@ module.exports = function(Api) {

var options = {},
alwaysUseGet = this.httpOptions.alwaysUseGet;

util._extend(options, this.httpOptions);
if (alwaysUseGet) {
params.method = method;
Expand Down Expand Up @@ -72,36 +99,12 @@ module.exports = function(Api) {
var httpTransport = this.httpTransport;

return new Promise(function (resolve, reject) {
var request = httpTransport.request(options, function (response) {
var body = '';
if (typeof response.setEncoding === 'function') {
response.setEncoding('utf8');
}
response.on('data', function (chunk) {
body += chunk;
});
response.on('end', function () {
var data;
try {
data = JSON.parse(body);
}
catch(e) {
reject(body);
return;
}
if (data.error) {
reject(data);
} else {
resolve(data.data);
}
});
});
var request = httpTransport.request(options, this._handleResponse(resolve, reject));
request.on('error', reject);
if (!alwaysUseGet && params && requestHasData(options.method)) {
request.write(params);
}
request.end();
});
}.bind(this));
};
};

34 changes: 31 additions & 3 deletions src/plugins/upload.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,12 @@
* limitations under the License.
*/

var FormData = require('form-data'),
util = require('util');

/**
* @author Hovhannes Babayan <bhovhannes at gmail dot com>
* @author Matt Winchester <mwinche at gmail dot com>
*/
module.exports = function(Api) {
/**
Expand All @@ -24,8 +28,32 @@ module.exports = function(Api) {
* Returned 'handle' can be passed to create() method to create a new document.
* @memberOf Workfront.Api
* @param {fs.ReadStream} stream A readable stream with file contents
* @param {Object} [overrides] Override the filename and content type (using keys
* `filename` and `contentType` respectively).
*/
Api.prototype.upload = function (/*stream*/) {
throw new Error('Not implemented')
Api.prototype.upload = function(stream, overrides) {
var form = new FormData();
form.append('uploadedFile', stream, overrides);

var options = {
method: 'POST'
};

util._extend(options, this.httpOptions);
options.headers = form.getHeaders();
options.headers.sessionID = this.httpOptions.headers.sessionID;
options.path += '/upload';

delete options.headers['Content-Length'];

var httpTransport = this.httpTransport;

return new Promise(function (resolve, reject) {
var request = httpTransport.request(options, this._handleResponse(resolve, reject));

form.pipe(request);

request.on('error', reject);
}.bind(this));
};
};
};
3 changes: 3 additions & 0 deletions test/plugins/sample.file
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Here is some sample content that needs to be uploaded.

It is a few lines.
79 changes: 79 additions & 0 deletions test/plugins/upload.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/**
* Copyright 2015 Workfront
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

require('./../common');
var nock = require('nock');
var fs = require('fs');

var Api = require('./../../').Api;


describe('Api.upload() method', function() {
it('should call upload() with proper params and file contents and return value received from upload()', function(done) {
var content = ['Content-Disposition: form-data; name="uploadedFile"; filename="sample.file"',
'Content-Type: false',
'Here is some sample content that needs to be uploaded.',
'It is a few lines.'
].join(' ');

var url = 'http://foobar:8000';
nock(url)
.post('/attask/api/upload')
.reply(200, function(uri, requestBody){
expect(requestBody.replace(/[\n\r]+/g, ' ')).to.contain(content);

return {
data: {
'handle': '3cbd483b0ebe45a78492a08f95f2eb88'
}
};
});

var api = new Api({url: url});
var stream = fs.createReadStream('./test/plugins/sample.file');
var promise = api.upload(stream);
expect(promise).to.eventually.deep.equal({'handle': '3cbd483b0ebe45a78492a08f95f2eb88'}).and.notify(done);
});

it('should allow for overriding filename and content type', function(done) {
var content = ['Content-Disposition: form-data; name="uploadedFile"; filename="test.txt"',
'Content-Type: text/plain',
'Here is some sample content that needs to be uploaded.',
'It is a few lines.'
].join(' ');

var url = 'http://foobar:8000';
nock(url)
.post('/attask/api/upload')
.reply(200, function(uri, requestBody){
expect(requestBody.replace(/[\n\r]+/g, ' ')).to.contain(content);

return {
data: {
'handle': '3cbd483b0ebe45a78492a08f95f2eb88'
}
};
});

var api = new Api({url: url});
var stream = fs.createReadStream('./test/plugins/sample.file');
var promise = api.upload(stream, {
filename: 'test.txt',
contentType: 'text/plain'
});
expect(promise).to.eventually.deep.equal({'handle': '3cbd483b0ebe45a78492a08f95f2eb88'}).and.notify(done);
});
});