'use strict';
var _ = require('lodash'),
fs = require('fs');
module.exports = function (Connection) {
Connection.addInstanceMethods(
/** @lends Connection.prototype */
{
/**
* Used to retrieve the metadata about a file.
* @summary Get Information About a File.
* @see {@link https://developers.box.com/docs/#files-get}
* @param {number} id - The file's ID.
* @param {requestCallback} done - The callback to invoke (with possible errors) when the request returns.
* @param {?RequestHeaders} [headers] - Additional headers.
* @param {?RequestConfig} [config] - Configure the request behaviour.
*/
getFileInfo: function (id, done, headers, config) {
if (!_.isNumber(parseInt(id, 10))) {
return done(new Error('id must be specified.'));
}
this._request(['files', id], 'GET', done, null, null, null, headers, null, config);
},
/**
* Called after a {@link Connection#getFile} is performed.
* @callback getFileCallback
* @param {Error} [error] - Any error that may have occurred.
*/
/**
* Retrieves the actual data of the file. An optional {@linkcode opts.version} parameter
* can be set to download a previous version of the file.
* @summary Download a File.
* @see {@link https://developers.box.com/docs/#files-download-a-file}
* @param {number} id - The file's ID.
* @param {number} version - File version to download. Can be null (meaning get the latest).
* @param {string} dest - Full path to where the file should be saved.
* @param {getFileCallback} done - The callback to invoke (with possible errors) when the request returns.
* @param {?RequestConfig} [config] - Configure the request behaviour.
*/
getFile: function (id, version, dest, done, config) {
if (!_.isNumber(parseInt(id, 10))) {
return done(new Error('id must be specified.'));
}
if (!_.isEmpty(version) && !_.isNumber(parseInt(version, 10))) {
return done(new Error('version must be a number.'));
}
if (!_.isString(dest)) {
return done(new Error('destination must be a string.'));
}
var wr = fs.createWriteStream(dest);
var cbCalled = false;
wr.on("error", function (err) {
done(err);
});
wr.on("close", function (ex) {
if (!cbCalled) {
done();
}
cbCalled = true;
});
var opts = {};
if (version) {
opts.version = version;
}
this._request(['files', id, 'content'], 'GET', function (err) {
if (err) {
done(err);
cbCalled = true;
}
}, opts, null, null, null, wr, config);
},
/**
* Fields to set for {@link Connection#updateFile}.
* @external FieldsUpdateFile
* @see {@link https://developers.box.com/docs/#files-update-a-files-information}
*/
/**
* Used to update individual or multiple fields in the file object, including renaming the file,
* changing it’s description, and creating a shared link for the file. To move a file, change
* the ID of its parent folder. An optional {@linkcode header[If-Match]} header can be included
* to ensure that client only updates the file if it knows about the latest version.
* @summary Update a file’s information.
* @see {@link https://developers.box.com/docs/#files-update-a-files-information}
* @param {number} id - The file's ID.
* @param {external:FieldsUpdateFile} fields - The fields to update.
* @param {requestCallback} done - The callback to invoke (with possible errors) when the request returns.
* @param {?RequestHeaders} [headers] - Additional headers.
* @param {?RequestConfig} [config] - Configure the request behaviour.
*/
updateFile: function (id, fields, done, headers, config) {
if (!_.isNumber(parseInt(id, 10))) {
return done(new Error('id must be specified.'));
}
if (!_.isObject(fields)) {
return done(new Error('An fields object must be provided.'));
}
this._request(['files', id], 'PUT', done, null, fields, null, headers, null, config);
},
/**
* Options to set for {@link Connection#uploadFile}.
* @typedef {Object} OptsUploadFile
* @property {timestamp} [content_created_at] - The time this file was created on the user’s machine.
* @property {timestamp} [content_modified_at] - The time this file was last modified on the user’s machine.
* @see {@link https://developers.box.com/docs/#files-upload-a-file}
*/
/**
* Use the Uploads API to allow users to add a new file. The user can then upload a file by
* specifying the destination folder for the file. If the user provides a file name that
* already exists in the destination folder, the user will receive an error. You can
* optionally specify a {@linkcode header[Content-MD5]} header with the SHA1 hash of the file
* to ensure that the file is not corrupted in transit.
* @summary Upload a File.
* @see {@link https://developers.box.com/docs/#files-upload-a-file}
* @param {string} name - The fully qualified path to the local file.
* @param {number} parent_id - The parent folder's ID.
* @param {?OptsUploadFile} opts - Request options.
* @param {requestCallback} done - The callback to invoke (with possible errors) when the request returns.
* @param {?RequestHeaders} [headers] - Additional headers.
* @param {?RequestConfig} [config] - Configure the request behaviour.
*/
uploadFile: function (name, parent_id, opts, done, headers, config) {
if (!_.isString(name) || !_.isNumber(parseInt(parent_id, 10))) {
return done(new Error('Invalid params. Required - name: string, parent_id: number'));
}
opts = opts || {};
opts.parent_id = parent_id;
var data = fs.createReadStream(name);
this._request(['files', 'content'], 'POST', done, null, opts, data, headers, null, config);
},
/**
* Discards a file to the trash. The etag of the file can be included as an
* {@linkcode header[If-Match]} header to prevent race conditions.
* @summary Delete a file.
* @see {@link https://developers.box.com/docs/#files-delete-a-file}
* @param {number} id - The file's ID.
* @param {requestCallback} done - The callback to invoke (with possible errors) when the request returns.
* @param {?RequestHeaders} [headers] - Additional headers.
* @param {?RequestConfig} [config] - Configure the request behaviour.
*/
deleteFile: function (id, done, headers, config) {
if (!_.isNumber(parseInt(id, 10))) {
return done(new Error('id must be specified.'));
}
this._request(['files', id], 'DELETE', done, null, null, null, headers, null, config);
},
/**
* Options to set for {@link Connection#uploadFileNewVersion}.
* @typedef {Object} OptsUploadFileNewVersion
* @property {timestamp} [content_modified_at] - The time this file was last modified on the user’s machine.
* @see {@link https://developers.box.com/docs/#files-upload-a-new-version-of-a-file}
*/
/**
* This method is used to upload a new version of an existing file in a user’s account.
* An optional {@linkcode header[If-Match]} header can be included to ensure that client
* only overwrites the file if it knows about the latest version. The filename on Box
* will remain the same as the previous version.
* @summary Upload a New Version of a File.
* @see {@link https://developers.box.com/docs/#files-upload-a-new-version-of-a-file}
* @param {string} name - The fully qualified path to the local file.
* @param {number} id - The file's ID.
* @param {?OptsUploadFileNewVersion} opts - Request options.
* @param {requestCallback} done - The callback to invoke (with possible errors) when the request returns.
* @param {?RequestHeaders} [headers] - Additional headers.
* @param {?RequestConfig} [config] - Configure the request behaviour.
*/
uploadFileNewVersion: function (name, id, opts, done, headers, config) {
if (!_.isString(name) || !_.isNumber(parseInt(id, 10))) {
return done(new Error('Invalid params. Required - name: string, id: number'));
}
var data = fs.createReadStream(name);
this._request(['files', id, 'content'], 'POST', done, null, opts, data, headers, null, config);
},
/**
* If there are previous versions of this file, this method can be used to retrieve
* metadata about the older versions.
* @summary View Versions of a File.
* @see {@link https://developers.box.com/docs/#files-view-versions-of-a-file}
* @param {number} id - The file's ID.
* @param {requestCallback} done - The callback to invoke (with possible errors) when the request returns.
* @param {?RequestConfig} [config] - Configure the request behaviour.
*/
getFileVersions: function (id, done, config) {
if (!_.isNumber(parseInt(id, 10))) {
return done(new Error('id must be specified.'));
}
this._request(['files', id, 'versions'], 'GET', done, null, null, null, null, null, config);
},
/**
* If there are previous versions of this file, this method can be used to promote one of the
* older versions to the top of the stack. This actually mints a copy of the old version and
* puts it on the top of the versions stack. The file will have the exact same contents, the
* same SHA1/etag, and the same name as the original. Other properties such as comments do not
* get updated to their former values.
* @summary Promote an Old Version of a File.
* @see {@link https://developers.box.com/docs/#files-promote-old-version}
* @param {number} id - The file's ID.
* @param {number} version - File version to promote.
* @param {requestCallback} done - The callback to invoke (with possible errors) when the request returns.
* @param {?RequestConfig} [config] - Configure the request behaviour.
*/
promoteFileVersion: function (id, version, done, config) {
if (!_.isNumber(parseInt(id, 10))) {
return done(new Error('id must be specified.'));
}
if (!_.isEmpty(version) && !_.isNumber(parseInt(version, 10))) {
return done(new Error('version must be a number.'));
}
var payload = {
type: 'file_version',
id: version
};
this._request(['files', id, 'versions', 'current'], 'POST', done, null, payload, null, null, null, config);
},
/**
* Discards a specific file version to the trash.
* @summary Delete an Old Version of a File.
* @see {@link https://developers.box.com/docs/#files-delete-version}
* @param {number} id - The file's ID.
* @param {number} version - File version to promote.
* @param {requestCallback} done - The callback to invoke (with possible errors) when the request returns.
* @param {?RequestHeaders} [headers] - Additional headers.
* @param {?RequestConfig} [config] - Configure the request behaviour.
*/
deleteFileVersion: function (id, version, done, headers, config) {
if (!_.isNumber(parseInt(id, 10))) {
return done(new Error('id must be specified.'));
}
if (!_.isEmpty(version) && !_.isNumber(parseInt(version, 10))) {
return done(new Error('version must be a number.'));
}
this._request(['files', id, 'versions', version], 'DELETE', done, null, null, null, headers, null, config);
},
/**
* Used to create a copy of a file in another folder. The original version of the file will
* not be altered.
* @summary Copy a File.
* @see {@link https://developers.box.com/docs/#files-copy-a-file}
* @param {number} id - The file's ID.
* @param {number} parent_id - The destination parent folder's ID.
* @param {string} name - The destination file's name. Can be null.
* @param {requestCallback} done - The callback to invoke (with possible errors) when the request returns.
* @param {?RequestConfig} [config] - Configure the request behaviour.
*/
copyFile: function (id, parent_id, name, done, config) {
if (!_.isNumber(parseInt(id, 10)) || !_.isNumber(parseInt(parent_id, 10))) {
return done(new Error('Invalid params. Required - id: number, parent_id: number'));
}
var opts = {
parent: {
id: parent_id.toString()
}
};
if (name) {
opts.name = name;
}
this._request(['files', id, 'copy'], 'POST', done, null, opts, null, null, null, config);
},
/**
* Options to pass to {@link Connection#getFileThumbnail}.
* @external OptsGetFileThumbnail
* @see {@link https://developers.box.com/docs/#files-get-a-thumbnail-for-a-file}
*/
/**
* Retrieves a thumbnail, or smaller image representation, of this file. Sizes of 32x32,
* 64x64, 128x128, and 256x256 can be returned. Currently thumbnails are only available
* in .png format and will only be generated for image file formats.
* @summary Get a Thumbnail for a File.
* @see {@link https://developers.box.com/docs/#files-get-a-thumbnail-for-a-file}
* @param {number} id - The file's ID.
* @param {external:OptsGetFileThumbnail} opts - Thumbnail options.
* @param {string} dest - Full path to where the file should be saved.
* @param {getFileCallback} done - The callback to invoke (with possible errors) when the request returns.
* @param {?RequestConfig} [config] - Configure the request behaviour.
*/
getFileThumbnail: function (id, opts, dest, done, config) {
if (!_.isNumber(parseInt(id, 10))) {
return done(new Error('id must be specified.'));
}
if (!_.isString(dest)) {
return done(new Error('destination must be a string.'));
}
var wr = fs.createWriteStream(dest);
var cbCalled = false;
wr.on("error", function (err) {
done(err);
});
wr.on("close", function (ex) {
if (!cbCalled) {
done();
}
cbCalled = true;
});
this._request(['files', id, 'thumbnail.png'], 'GET', function (err) {
if (err) {
done(err);
cbCalled = true;
}
}, opts, null, null, null, wr, config);
},
/**
* Retrieves an item that has been moved to the trash.
* @summary Get a Trashed File.
* @see {@link https://developers.box.com/docs/#files-get-a-trashed-file}
* @param {number} id - The folder's ID.
* @param {requestCallback} done - The callback to invoke (with possible errors) when the request returns.
* @param {?RequestConfig} [config] - Configure the request behaviour.
*/
getTrashedFile: function (id, done, config) {
if (!_.isNumber(parseInt(id, 10))) {
return done(new Error('id must be specified.'));
}
this._request(['files', id, 'trash'], 'GET', done, null, null, null, null, null, config);
},
/**
* Permanently deletes an item that is in the trash. The item will no longer exist in Box.
* This action cannot be undone.
* @summary Permanently Delete a Trashed File.
* @see {@link https://developers.box.com/docs/#files-permanently-delete-a-trashed-file}
* @param {number} id - The folder's ID.
* @param {requestCallback} done - The callback to invoke (with possible errors) when the request returns.
* @param {?RequestConfig} [config] - Configure the request behaviour.
*/
deleteTrashedFile: function (id, done, config) {
if (!_.isNumber(parseInt(id, 10))) {
return done(new Error('id must be specified.'));
}
this._request(['files', id, 'trash'], 'DELETE', done, null, null, null, null, null, config);
},
/**
* Restores an item that has been moved to the trash. Default behavior is to restore the
* item to the folder it was in before it was moved to the trash. If that parent folder
* no longer exists or if there is now an item with the same name in that parent folder,
* the new parent folder and/or new name will need to be included in the request.
* @summary Restore a Trashed Item.
* @see {@link https://developers.box.com/docs/#files-restore-a-trashed-item}
* @param {number} id - The file's ID.
* @param {?string} name - The file's name.
* @param {number} parent_id - The parent folder's ID. Can be null.
* @param {requestCallback} done - The callback to invoke (with possible errors) when the request returns.
* @param {?RequestConfig} [config] - Configure the request behaviour.
*/
restoreTrashedFile: function (id, name, parent_id, done, config) {
if ((name && !_.isString(name)) || (parent_id && !_.isNumber(parseInt(parent_id, 10)))) {
return done(new Error('Invalid params. Required - name: string, parent_id: number'));
}
var opts = {};
if (name) {
opts.name = name;
}
if (parent_id) {
opts.parent = {
id: parent_id.toString()
};
}
this._request(['files', id], 'POST', done, null, opts, null, null, null, config);
},
/**
* Retrieves the comments on a particular file, if any exist.
* @summary View the Comments on a File.
* @see {@link https://developers.box.com/docs/#files-view-the-comments-on-a-file}
* @param {number} id - The file's ID.
* @param {requestCallback} done - The callback to invoke (with possible errors) when the request returns.
* @param {?RequestConfig} [config] - Configure the request behaviour.
*/
getFileComments: function (id, done, config) {
if (!_.isNumber(parseInt(id, 10))) {
return done(new Error('id must be specified.'));
}
this._request(['files', id, 'comments'], 'GET', done, null, null, null, null, null, config);
},
/**
* Retrieves all of the tasks for given file.
* @summary Get the tasks for a file.
* @see {@link https://developers.box.com/docs/#files-get-the-tasks-for-a-file}
* @param {number} id - The file's ID.
* @param {requestCallback} done - The callback to invoke (with possible errors) when the request returns.
* @param {?RequestConfig} [config] - Configure the request behaviour.
*/
getFileTasks: function (id, done, config) {
if (!_.isNumber(parseInt(id, 10))) {
return done(new Error('id must be specified.'));
}
this._request(['files', id, 'tasks'], 'GET', done, null, null, null, null, null, config);
}
});
};