box-node-sdk 1.32.0 → 1.34.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -3
- package/lib/managers/files.js +84 -5
- package/lib/managers/metadata.js +6 -1
- package/lib/util/config.js +25 -2
- package/lib/util/paging-iterator.js +8 -1
- package/lib/util/url-path.js +10 -1
- package/package.json +3 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,9 +1,27 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## 1.
|
|
3
|
+
## 1.34.2 [2020-08-20]
|
|
4
4
|
|
|
5
|
-
-
|
|
6
|
-
|
|
5
|
+
- Make iterator bug fix for uploading files non breaking ([#534](https://github.com/box/box-node-sdk/pull/534))
|
|
6
|
+
|
|
7
|
+
## 1.34.1 [2020-08-17]
|
|
8
|
+
|
|
9
|
+
- Fix iterator bug for uploading new file versions ([#531](https://github.com/box/box-node-sdk/pull/531))
|
|
10
|
+
|
|
11
|
+
## 1.34.0 [2020-08-04]
|
|
12
|
+
|
|
13
|
+
- Add zip functionality ([#525](https://github.com/box/box-node-sdk/pull/525))
|
|
14
|
+
- Add proxy support for `http`, `https`, `socks` and `pac` protocols ([#529](https://github.com/box/box-node-sdk/pull/529))
|
|
15
|
+
|
|
16
|
+
## 1.33.0 [2020-06-25]
|
|
17
|
+
|
|
18
|
+
- Add path parameter sanitization ([#505](https://github.com/box/box-node-sdk/pull/505))
|
|
19
|
+
- Add support for all streams for uploading files ([#519](https://github.com/box/box-node-sdk/pull/519))
|
|
20
|
+
|
|
21
|
+
## 1.32.0 [2020-04-01]
|
|
22
|
+
|
|
23
|
+
- Temporarily removed Node 4 and Node 5 builds from Travis, due to tests not passing. Will investigate, going forward ([#495](https://github.com/box/box-node-sdk/pull/495)).
|
|
24
|
+
- Fixed an issue where an error is thrown during a retry when a response is not returned by the previous call ([#477](https://github.com/box/box-node-sdk/pull/477)).
|
|
7
25
|
- Added the ability to [query](./docs/metadata.md#query) Box items based on their metadata ([#487](https://github.com/box/box-node-sdk/pull/487)).
|
|
8
26
|
|
|
9
27
|
## 1.31.0 [2020-02-13]
|
package/lib/managers/files.js
CHANGED
|
@@ -44,7 +44,8 @@ var urlPath = require('../util/url-path'),
|
|
|
44
44
|
var BASE_PATH = '/files',
|
|
45
45
|
VERSIONS_SUBRESOURCE = '/versions',
|
|
46
46
|
WATERMARK_SUBRESOURCE = '/watermark',
|
|
47
|
-
UPLOAD_SESSION_SUBRESOURCE = '/upload_sessions'
|
|
47
|
+
UPLOAD_SESSION_SUBRESOURCE = '/upload_sessions',
|
|
48
|
+
ZIP_DOWNLOAD_PATH = '/zip_downloads';
|
|
48
49
|
|
|
49
50
|
// Enum of valid lock types
|
|
50
51
|
var lockTypes = {
|
|
@@ -78,10 +79,11 @@ function createFileMetadataFormData(parentFolderID, filename, options) {
|
|
|
78
79
|
/**
|
|
79
80
|
* Returns the multipart form value for file upload content.
|
|
80
81
|
* @param {string|Buffer|Stream} content - the content of the file being uploaded
|
|
82
|
+
* @param {Object} options - options for the content
|
|
81
83
|
* @returns {Object} - the form value expected by the API for the 'content' key
|
|
82
84
|
* @private
|
|
83
85
|
*/
|
|
84
|
-
function createFileContentFormData(content) {
|
|
86
|
+
function createFileContentFormData(content, options) {
|
|
85
87
|
// The upload API appears to look for a form field that contains a filename
|
|
86
88
|
// property and assume that this form field contains the file content. Thus,
|
|
87
89
|
// the value of name does not actually matter (as long as it does not conflict
|
|
@@ -90,7 +92,7 @@ function createFileContentFormData(content) {
|
|
|
90
92
|
// filename specified in the metadata form field instead.
|
|
91
93
|
return {
|
|
92
94
|
value: content,
|
|
93
|
-
options: { filename: 'unused' }
|
|
95
|
+
options: Object.assign({ filename: 'unused' }, options)
|
|
94
96
|
};
|
|
95
97
|
}
|
|
96
98
|
|
|
@@ -601,6 +603,7 @@ Files.prototype.promoteVersion = function(fileID, versionID, callback) {
|
|
|
601
603
|
* @param {Object} [options] - Optional parameters
|
|
602
604
|
* @param {string} [options.content_created_at] - RFC 3339 timestamp when the file was created
|
|
603
605
|
* @param {string} [options.content_modified_at] - RFC 3339 timestamp when the file was last modified
|
|
606
|
+
* @param {int} [options.content_length] - Optional length of the content. Required if content is a read stream of any type other than fs stream.
|
|
604
607
|
* @param {Function} [callback] - called with data about the upload if successful, or an error if the
|
|
605
608
|
* upload failed
|
|
606
609
|
* @returns {Promise<Object>} A promise resolving to the uploaded file
|
|
@@ -613,10 +616,17 @@ Files.prototype.uploadFile = function(parentFolderID, filename, content, options
|
|
|
613
616
|
options = {};
|
|
614
617
|
}
|
|
615
618
|
|
|
619
|
+
var formOptions = {};
|
|
620
|
+
if (options && options.hasOwnProperty('content_length')) {
|
|
621
|
+
formOptions.knownLength = options.content_length;
|
|
622
|
+
// Delete content_length from options so it's not added to the attributes of the form
|
|
623
|
+
delete options.content_length;
|
|
624
|
+
}
|
|
625
|
+
|
|
616
626
|
var apiPath = urlPath(BASE_PATH, '/content'),
|
|
617
627
|
multipartFormData = {
|
|
618
628
|
attributes: createFileMetadataFormData(parentFolderID, filename, options),
|
|
619
|
-
content: createFileContentFormData(content)
|
|
629
|
+
content: createFileContentFormData(content, formOptions)
|
|
620
630
|
};
|
|
621
631
|
|
|
622
632
|
return this.client.wrapWithDefaultHandler(this.client.upload)(apiPath, null, multipartFormData, callback);
|
|
@@ -635,6 +645,7 @@ Files.prototype.uploadFile = function(parentFolderID, filename, content, options
|
|
|
635
645
|
* @param {Object} [options] - Optional parameters
|
|
636
646
|
* @param {string} [options.content_modified_at] - RFC 3339 timestamp when the file was last modified
|
|
637
647
|
* @param {string} [options.name] - A new name for the file
|
|
648
|
+
* @param {int} [options.content_length] - Optional length of the content. Required if content is a read stream of any type other than fs stream.
|
|
638
649
|
* @param {Function} [callback] - called with data about the upload if successful, or an error if the
|
|
639
650
|
* upload failed
|
|
640
651
|
* @returns {Promise<Object>} A promise resolving to the uploaded file
|
|
@@ -650,11 +661,18 @@ Files.prototype.uploadNewFileVersion = function(fileID, content, options, callba
|
|
|
650
661
|
var apiPath = urlPath(BASE_PATH, fileID, '/content'),
|
|
651
662
|
multipartFormData = {};
|
|
652
663
|
|
|
664
|
+
|
|
665
|
+
var formOptions = {};
|
|
653
666
|
if (options) {
|
|
667
|
+
if (options.hasOwnProperty('content_length')) {
|
|
668
|
+
formOptions.knownLength = options.content_length;
|
|
669
|
+
// Delete content_length from options so it's not added to the attributes of the form
|
|
670
|
+
delete options.content_length;
|
|
671
|
+
}
|
|
654
672
|
multipartFormData.attributes = JSON.stringify(options);
|
|
655
673
|
}
|
|
656
674
|
|
|
657
|
-
multipartFormData.content = createFileContentFormData(content);
|
|
675
|
+
multipartFormData.content = createFileContentFormData(content, formOptions);
|
|
658
676
|
|
|
659
677
|
return this.client.wrapWithDefaultHandler(this.client.upload)(apiPath, null, multipartFormData, callback);
|
|
660
678
|
};
|
|
@@ -1574,6 +1592,67 @@ Files.prototype.getRepresentationContent = function(fileID, representationType,
|
|
|
1574
1592
|
.asCallback(callback);
|
|
1575
1593
|
};
|
|
1576
1594
|
|
|
1595
|
+
/**
|
|
1596
|
+
* Creates a zip of multiple files and folders.
|
|
1597
|
+
*
|
|
1598
|
+
* API Endpoint: '/zip_downloads'
|
|
1599
|
+
* Method: POST
|
|
1600
|
+
*
|
|
1601
|
+
* @param {name} name - The name of the zip file to be created
|
|
1602
|
+
* @param {Array} items - Array of files or folders to be part of the created zip
|
|
1603
|
+
* @param {Function} [callback] Passed a stream over the representation contents if successful
|
|
1604
|
+
* @returns {Promise<string>} A promise resolving to the file's download URL
|
|
1605
|
+
*/
|
|
1606
|
+
Files.prototype.createZip = function(name, items, callback) {
|
|
1607
|
+
var params = {
|
|
1608
|
+
body: {
|
|
1609
|
+
download_file_name: name,
|
|
1610
|
+
items
|
|
1611
|
+
}
|
|
1612
|
+
};
|
|
1613
|
+
|
|
1614
|
+
return this.client.wrapWithDefaultHandler(this.client.post)(ZIP_DOWNLOAD_PATH, params, callback);
|
|
1615
|
+
};
|
|
1616
|
+
|
|
1617
|
+
/**
|
|
1618
|
+
* Creates a zip of multiple files and folders and downloads it.
|
|
1619
|
+
*
|
|
1620
|
+
* API Endpoint: '/zip_downloads'
|
|
1621
|
+
* Method: GET
|
|
1622
|
+
*
|
|
1623
|
+
* @param {name} name - The name of the zip file to be created
|
|
1624
|
+
* @param {Array} items - Array of files or folders to be part of the created zip
|
|
1625
|
+
* @param {Stream} stream - Stream to pipe the readable stream of the zip file
|
|
1626
|
+
* @param {Function} [callback] - Passed a status response object
|
|
1627
|
+
* @returns {Promise<Readable>} A promise resolving for the file stream
|
|
1628
|
+
*/
|
|
1629
|
+
Files.prototype.downloadZip = function(name, items, stream, callback) {
|
|
1630
|
+
var downloadStreamOptions = {
|
|
1631
|
+
streaming: true,
|
|
1632
|
+
headers: {}
|
|
1633
|
+
};
|
|
1634
|
+
|
|
1635
|
+
var params = {
|
|
1636
|
+
body: {
|
|
1637
|
+
download_file_name: name,
|
|
1638
|
+
items
|
|
1639
|
+
}
|
|
1640
|
+
};
|
|
1641
|
+
|
|
1642
|
+
return this.client.post(ZIP_DOWNLOAD_PATH, params)
|
|
1643
|
+
.then(response => this.client.get(response.body.download_url, downloadStreamOptions)
|
|
1644
|
+
.then(responseStream => {
|
|
1645
|
+
responseStream.pipe(stream);
|
|
1646
|
+
// eslint-disable-next-line promise/avoid-new
|
|
1647
|
+
return new Promise((resolve, reject) => {
|
|
1648
|
+
responseStream.on('end', () => resolve('Done downloading'));
|
|
1649
|
+
responseStream.on('error', error => reject(error));
|
|
1650
|
+
}).then(() => this.client.get(response.body.status_url).then(responseStatus => responseStatus.body));
|
|
1651
|
+
})
|
|
1652
|
+
)
|
|
1653
|
+
.asCallback(callback);
|
|
1654
|
+
};
|
|
1655
|
+
|
|
1577
1656
|
/**
|
|
1578
1657
|
* @module box-node-sdk/lib/managers/files
|
|
1579
1658
|
* @see {@Link Files}
|
package/lib/managers/metadata.js
CHANGED
|
@@ -325,7 +325,12 @@ Metadata.prototype = {
|
|
|
325
325
|
*
|
|
326
326
|
* @param {string} from - The template used in the query. Must be in the form scope.templateKey
|
|
327
327
|
* @param {string} ancestorFolderId - The folder_id to which to restrain the query
|
|
328
|
-
* @param {Object} options -
|
|
328
|
+
* @param {Object} options - Optional parameters
|
|
329
|
+
* @param {string} [options.query] - The logical expression of the query
|
|
330
|
+
* @param {Object} [options.query_parameters] - Required if query present. The arguments for the query
|
|
331
|
+
* @param {string} [options.index_name] - The name of the Index to use
|
|
332
|
+
* @param {Object} [options.order_by] - The field_key(s) to order on and the corresponding direction(s)
|
|
333
|
+
* @param {Array} [options.fields] - An array of fields to return
|
|
329
334
|
* @param {Function} [callback] - Passed a collection of items and their associated metadata
|
|
330
335
|
* @returns {Promise<void>} Promise resolving to a collection of items and their associated metadata
|
|
331
336
|
*/
|
package/lib/util/config.js
CHANGED
|
@@ -10,7 +10,9 @@
|
|
|
10
10
|
var assert = require('assert'),
|
|
11
11
|
https = require('https'),
|
|
12
12
|
merge = require('merge-options'),
|
|
13
|
-
sdkVersion = require('../../package.json').version
|
|
13
|
+
sdkVersion = require('../../package.json').version,
|
|
14
|
+
ProxyAgent = require('proxy-agent'),
|
|
15
|
+
url = require('url');
|
|
14
16
|
|
|
15
17
|
// ------------------------------------------------------------------------------
|
|
16
18
|
// Private
|
|
@@ -64,6 +66,11 @@ var defaults = {
|
|
|
64
66
|
iterators: false,
|
|
65
67
|
enterpriseID: undefined,
|
|
66
68
|
analyticsClient: null,
|
|
69
|
+
proxy: {
|
|
70
|
+
url: null,
|
|
71
|
+
username: null,
|
|
72
|
+
password: null,
|
|
73
|
+
},
|
|
67
74
|
request: {
|
|
68
75
|
// By default, require API SSL cert to be valid
|
|
69
76
|
strictSSL: true,
|
|
@@ -130,6 +137,22 @@ function validateAppAuthParams(appAuth) {
|
|
|
130
137
|
}
|
|
131
138
|
}
|
|
132
139
|
|
|
140
|
+
/**
|
|
141
|
+
* Update the agentClass based on the proxy config values passed in by the user
|
|
142
|
+
* @param {UserConfigurationOptions} params The current Config values
|
|
143
|
+
* @returns {void}
|
|
144
|
+
* @private
|
|
145
|
+
*/
|
|
146
|
+
function updateRequestAgent(params) {
|
|
147
|
+
if (params.proxy.url) {
|
|
148
|
+
params.request.agentClass = ProxyAgent;
|
|
149
|
+
params.request.agentOptions = Object.assign({}, params.request.agentOptions, url.parse(params.proxy.url));
|
|
150
|
+
if (params.proxy.username && params.proxy.password) {
|
|
151
|
+
Object.assign(params.request.agentOptions, {auth: `${params.proxy.username}:${params.proxy.password}`});
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
133
156
|
// ------------------------------------------------------------------------------
|
|
134
157
|
// Public
|
|
135
158
|
// ------------------------------------------------------------------------------
|
|
@@ -157,8 +180,8 @@ function Config(params) {
|
|
|
157
180
|
|
|
158
181
|
// Set the given params or default value if params property is missing
|
|
159
182
|
this._params = merge(defaults, params);
|
|
183
|
+
updateRequestAgent(this._params);
|
|
160
184
|
Object.assign(this, this._params);
|
|
161
|
-
|
|
162
185
|
// Freeze the object so that configuration options cannot be modified
|
|
163
186
|
Object.freeze(this);
|
|
164
187
|
}
|
|
@@ -58,7 +58,11 @@ class PagingIterator {
|
|
|
58
58
|
* @returns {boolean} Whether the response is iterable
|
|
59
59
|
*/
|
|
60
60
|
static isIterable(response) {
|
|
61
|
-
|
|
61
|
+
// POST responses for uploading a file are explicitly excluded here because, while the response is iterable,
|
|
62
|
+
// it always contains only a single entry and historically has not been handled as iterable in the SDK.
|
|
63
|
+
// This behavior is being preserved here to avoid a breaking change.
|
|
64
|
+
let UPLOAD_PATTERN = /.*upload\.box\.com.*\/content/;
|
|
65
|
+
var isGetOrPostRequest = (response.request && (response.request.method === 'GET' || (response.request.method === 'POST' && !UPLOAD_PATTERN.test(response.request.uri.href)))),
|
|
62
66
|
hasEntries = (response.body && Array.isArray(response.body.entries)),
|
|
63
67
|
notEventStream = (response.body && !response.body.next_stream_position);
|
|
64
68
|
|
|
@@ -160,6 +164,9 @@ class PagingIterator {
|
|
|
160
164
|
if (response.request.method === 'GET') {
|
|
161
165
|
this.options.qs[this.nextField] = this.nextValue;
|
|
162
166
|
} else if (response.request.method === 'POST') {
|
|
167
|
+
if (!this.options.body) {
|
|
168
|
+
this.options.body = {};
|
|
169
|
+
}
|
|
163
170
|
this.options.body[this.nextField] = this.nextValue;
|
|
164
171
|
let bodyString = JSON.stringify(this.options.body);
|
|
165
172
|
this.options.headers['content-length'] = bodyString.length;
|
package/lib/util/url-path.js
CHANGED
|
@@ -8,6 +8,8 @@
|
|
|
8
8
|
// Private
|
|
9
9
|
// ------------------------------------------------------------------------------
|
|
10
10
|
|
|
11
|
+
// Pattern to check for relative paths
|
|
12
|
+
var PATTERN = /\/\.+/;
|
|
11
13
|
/**
|
|
12
14
|
* remove leading & trailing slashes from some string. This is useful for
|
|
13
15
|
* removing slashes from the path segments that are actually a part of the
|
|
@@ -39,7 +41,14 @@ function trimSlashes(segment) {
|
|
|
39
41
|
*/
|
|
40
42
|
module.exports = function urlPath(/* arguments*/) {
|
|
41
43
|
var args = Array.prototype.slice.call(arguments);
|
|
42
|
-
var path = args.map(x => String(x))
|
|
44
|
+
var path = args.map(x => String(x))
|
|
45
|
+
.map(x => {
|
|
46
|
+
var trimmedX = trimSlashes(x);
|
|
47
|
+
if (PATTERN.test(trimmedX)) {
|
|
48
|
+
throw new Error(`An invalid path parameter exists in ${trimmedX}. Relative path parameters cannot be passed.`);
|
|
49
|
+
}
|
|
50
|
+
return trimmedX;
|
|
51
|
+
})
|
|
43
52
|
.map(x => encodeURIComponent(x))
|
|
44
53
|
.join('/');
|
|
45
54
|
return `/${path}`;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "box-node-sdk",
|
|
3
3
|
"author": "Box <oss@box.com>",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.34.2",
|
|
5
5
|
"description": "Official SDK for Box Plaform APIs",
|
|
6
6
|
"license": "Apache-2.0",
|
|
7
7
|
"repository": {
|
|
@@ -36,8 +36,8 @@
|
|
|
36
36
|
"http-status": "^1.4.1",
|
|
37
37
|
"jsonwebtoken": "^8.5.1",
|
|
38
38
|
"merge-options": "^1.0.1",
|
|
39
|
-
"npm-upgrade": "^2.0.2",
|
|
40
39
|
"promise-queue": "^2.2.3",
|
|
40
|
+
"proxy-agent": "^3.1.1",
|
|
41
41
|
"request": "^2.88.0",
|
|
42
42
|
"url-template": "^2.0.8",
|
|
43
43
|
"uuid": "^3.3.3"
|
|
@@ -57,6 +57,7 @@
|
|
|
57
57
|
"mockery": "^2.1.0",
|
|
58
58
|
"nock": "^9.6.1",
|
|
59
59
|
"np": "^5.1.3",
|
|
60
|
+
"npm-upgrade": "^2.0.3",
|
|
60
61
|
"nyc": "^11.9.0",
|
|
61
62
|
"shelljs": "^0.8.3",
|
|
62
63
|
"shelljs-nodecli": "^0.1.1",
|