files.com 1.0.295 → 1.0.297
Sign up to get free protection for your applications and to get access to all the features.
- package/_VERSION +1 -1
- package/docs/models/Automation.md +8 -8
- package/lib/Api.js +180 -80
- package/lib/Errors.js +2 -2
- package/lib/isomorphic/File.node.js +5 -3
- package/lib/models/Automation.js +4 -4
- package/package.json +2 -3
- package/src/Api.js +68 -30
- package/src/Errors.js +2 -2
- package/src/isomorphic/File.node.js +5 -2
- package/src/models/Automation.js +4 -4
- package/test/package.json +2 -1
- package/test/src/index.js +54 -40
package/_VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.0.
|
1
|
+
1.0.297
|
@@ -8,7 +8,7 @@
|
|
8
8
|
"automation": "create_folder",
|
9
9
|
"deleted": true,
|
10
10
|
"disabled": true,
|
11
|
-
"trigger": "
|
11
|
+
"trigger": "daily",
|
12
12
|
"interval": "week",
|
13
13
|
"last_modified_at": "2000-01-01T01:00:00Z",
|
14
14
|
"name": "example",
|
@@ -49,13 +49,13 @@
|
|
49
49
|
* `automation` (string): Automation type
|
50
50
|
* `deleted` (boolean): Indicates if the automation has been deleted.
|
51
51
|
* `disabled` (boolean): If true, this automation will not run.
|
52
|
-
* `trigger` (string): How this automation is triggered to run.
|
52
|
+
* `trigger` (string): How this automation is triggered to run.
|
53
53
|
* `interval` (string): If trigger is `daily`, this specifies how often to run this automation. One of: `day`, `week`, `week_end`, `month`, `month_end`, `quarter`, `quarter_end`, `year`, `year_end`
|
54
54
|
* `last_modified_at` (date-time): Time when automation was last modified. Does not change for name or description updates.
|
55
55
|
* `name` (string): Name for this automation.
|
56
56
|
* `schedule` (object): If trigger is `custom_schedule`, Custom schedule description for when the automation should be run.
|
57
57
|
* `source` (string): Source Path
|
58
|
-
* `destinations` (array): Destination
|
58
|
+
* `destinations` (array): Destination Paths
|
59
59
|
* `destination_replace_from` (string): If set, this string in the destination path will be replaced with the value in `destination_replace_to`.
|
60
60
|
* `destination_replace_to` (string): If set, this string will replace the value `destination_replace_from` in the destination filename. You can use special patterns here.
|
61
61
|
* `description` (string): Description for the this Automation.
|
@@ -126,7 +126,7 @@ await Automation.create({
|
|
126
126
|
'description': "example",
|
127
127
|
'disabled': true,
|
128
128
|
'name': "example",
|
129
|
-
'trigger': "
|
129
|
+
'trigger': "daily",
|
130
130
|
'trigger_actions': ["create"],
|
131
131
|
'value': {"limit":"1"},
|
132
132
|
'recurring_day': 25,
|
@@ -151,7 +151,7 @@ await Automation.create({
|
|
151
151
|
* `description` (string): Description for the this Automation.
|
152
152
|
* `disabled` (boolean): If true, this automation will not run.
|
153
153
|
* `name` (string): Name for this automation.
|
154
|
-
* `trigger` (string): How this automation is triggered to run.
|
154
|
+
* `trigger` (string): How this automation is triggered to run.
|
155
155
|
* `trigger_actions` (array(string)): If trigger is `action`, this is the list of action types on which to trigger the automation. Valid actions are create, read, update, destroy, move, copy
|
156
156
|
* `value` (object): A Hash of attributes specific to the automation type.
|
157
157
|
* `recurring_day` (int64): If trigger type is `daily`, this specifies a day number to run in one of the supported intervals: `week`, `month`, `quarter`, `year`.
|
@@ -193,7 +193,7 @@ await automation.update({
|
|
193
193
|
'description': "example",
|
194
194
|
'disabled': true,
|
195
195
|
'name': "example",
|
196
|
-
'trigger': "
|
196
|
+
'trigger': "daily",
|
197
197
|
'trigger_actions': ["create"],
|
198
198
|
'value': {"limit":"1"},
|
199
199
|
'recurring_day': 25,
|
@@ -218,7 +218,7 @@ await automation.update({
|
|
218
218
|
* `description` (string): Description for the this Automation.
|
219
219
|
* `disabled` (boolean): If true, this automation will not run.
|
220
220
|
* `name` (string): Name for this automation.
|
221
|
-
* `trigger` (string): How this automation is triggered to run.
|
221
|
+
* `trigger` (string): How this automation is triggered to run.
|
222
222
|
* `trigger_actions` (array(string)): If trigger is `action`, this is the list of action types on which to trigger the automation. Valid actions are create, read, update, destroy, move, copy
|
223
223
|
* `value` (object): A Hash of attributes specific to the automation type.
|
224
224
|
* `recurring_day` (int64): If trigger type is `daily`, this specifies a day number to run in one of the supported intervals: `week`, `month`, `quarter`, `year`.
|
@@ -232,7 +232,7 @@ await automation.update({
|
|
232
232
|
"automation": "create_folder",
|
233
233
|
"deleted": true,
|
234
234
|
"disabled": true,
|
235
|
-
"trigger": "
|
235
|
+
"trigger": "daily",
|
236
236
|
"interval": "week",
|
237
237
|
"last_modified_at": "2000-01-01T01:00:00Z",
|
238
238
|
"name": "example",
|
package/lib/Api.js
CHANGED
@@ -7,92 +7,192 @@ exports.default = void 0;
|
|
7
7
|
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
|
8
8
|
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
9
9
|
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
|
10
|
-
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
|
11
10
|
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
|
12
11
|
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
|
13
12
|
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
14
|
-
var
|
15
|
-
var
|
13
|
+
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
|
14
|
+
var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
|
15
|
+
var _crossFetch = _interopRequireDefault(require("cross-fetch"));
|
16
16
|
var _Files = _interopRequireDefault(require("./Files"));
|
17
17
|
var errors = _interopRequireWildcard(require("./Errors"));
|
18
18
|
var _Logger = _interopRequireDefault(require("./Logger"));
|
19
19
|
var _utils = require("./utils");
|
20
|
+
var _excluded = ["timeoutSecs"];
|
20
21
|
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
21
22
|
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
22
23
|
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
|
23
24
|
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { (0, _defineProperty2.default)(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
|
25
|
+
var _fetchWithTimeout = function _fetchWithTimeout(url) {
|
26
|
+
var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
|
27
|
+
timeoutSecs = _ref.timeoutSecs,
|
28
|
+
options = (0, _objectWithoutProperties2.default)(_ref, _excluded);
|
29
|
+
return timeoutSecs <= 0 ? (0, _crossFetch.default)(url, options) : Promise.race([(0, _crossFetch.default)(url, options), new Promise(function (_, reject) {
|
30
|
+
setTimeout(function () {
|
31
|
+
return reject(new errors.FilesError('Request timed out'));
|
32
|
+
}, timeoutSecs * 1000);
|
33
|
+
})]);
|
34
|
+
};
|
35
|
+
var fetchWithRetry = /*#__PURE__*/function () {
|
36
|
+
var _ref2 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(url, options) {
|
37
|
+
var retries,
|
38
|
+
maxRetries,
|
39
|
+
minRetryDelaySecs,
|
40
|
+
maxRetryDelaySecs,
|
41
|
+
nextRetries,
|
42
|
+
delaySecs,
|
43
|
+
_args = arguments;
|
44
|
+
return _regenerator.default.wrap(function _callee$(_context) {
|
45
|
+
while (1) switch (_context.prev = _context.next) {
|
46
|
+
case 0:
|
47
|
+
retries = _args.length > 2 && _args[2] !== undefined ? _args[2] : 0;
|
48
|
+
maxRetries = _Files.default.getMaxNetworkRetries();
|
49
|
+
minRetryDelaySecs = _Files.default.getMinNetworkRetryDelay();
|
50
|
+
maxRetryDelaySecs = _Files.default.getMaxNetworkRetryDelay();
|
51
|
+
_context.prev = 4;
|
52
|
+
_context.next = 7;
|
53
|
+
return _fetchWithTimeout(url, options);
|
54
|
+
case 7:
|
55
|
+
return _context.abrupt("return", _context.sent);
|
56
|
+
case 10:
|
57
|
+
_context.prev = 10;
|
58
|
+
_context.t0 = _context["catch"](4);
|
59
|
+
_Logger.default.info("Request #".concat(retries + 1, " failed: ").concat(_context.t0.message));
|
60
|
+
if (!(retries >= maxRetries)) {
|
61
|
+
_context.next = 17;
|
62
|
+
break;
|
63
|
+
}
|
64
|
+
throw _context.t0;
|
65
|
+
case 17:
|
66
|
+
nextRetries = retries + 1;
|
67
|
+
_Logger.default.info("Retrying request (retry ".concat(nextRetries, " of ").concat(maxRetries, ")"));
|
68
|
+
delaySecs = Math.min(minRetryDelaySecs * Math.pow(2, retries), maxRetryDelaySecs); // exponential backoff
|
69
|
+
_context.next = 22;
|
70
|
+
return new Promise(function (resolve) {
|
71
|
+
return setTimeout(resolve, delaySecs * 1000);
|
72
|
+
});
|
73
|
+
case 22:
|
74
|
+
return _context.abrupt("return", fetchWithRetry(url, options, nextRetries));
|
75
|
+
case 23:
|
76
|
+
case "end":
|
77
|
+
return _context.stop();
|
78
|
+
}
|
79
|
+
}, _callee, null, [[4, 10]]);
|
80
|
+
}));
|
81
|
+
return function fetchWithRetry(_x, _x2) {
|
82
|
+
return _ref2.apply(this, arguments);
|
83
|
+
};
|
84
|
+
}();
|
24
85
|
var Api = /*#__PURE__*/(0, _createClass2.default)(function Api() {
|
25
86
|
(0, _classCallCheck2.default)(this, Api);
|
26
87
|
});
|
27
|
-
(0, _defineProperty2.default)(Api, "_configureAutoRetry", function () {
|
28
|
-
(0, _axiosRetry.default)(_axios.default, {
|
29
|
-
retries: _Files.default.getMaxNetworkRetries(),
|
30
|
-
retryDelay: function retryDelay(retries) {
|
31
|
-
_Logger.default.info("Retrying request (retry ".concat(retries, " of ").concat(_Files.default.getMaxNetworkRetries(), ")"));
|
32
|
-
return Math.min(retries * _Files.default.getMinNetworkRetryDelay() * 1000, _Files.default.getMaxNetworkRetryDelay() * 1000);
|
33
|
-
}
|
34
|
-
});
|
35
|
-
});
|
36
88
|
(0, _defineProperty2.default)(Api, "_sendVerbatim", /*#__PURE__*/function () {
|
37
|
-
var
|
38
|
-
var isExternal, baseUrl, url, response;
|
39
|
-
return _regenerator.default.wrap(function
|
40
|
-
while (1) switch (
|
89
|
+
var _ref3 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee2(path, verb, options) {
|
90
|
+
var isExternal, baseUrl, url, agent, response, headers, contentType, data, normalizedResponse;
|
91
|
+
return _regenerator.default.wrap(function _callee2$(_context2) {
|
92
|
+
while (1) switch (_context2.prev = _context2.next) {
|
41
93
|
case 0:
|
42
94
|
isExternal = /^[a-zA-Z]+:\/\//.test(path);
|
43
95
|
baseUrl = _Files.default.getBaseUrl();
|
44
96
|
if (!(!isExternal && !baseUrl)) {
|
45
|
-
|
97
|
+
_context2.next = 4;
|
46
98
|
break;
|
47
99
|
}
|
48
100
|
throw new errors.ConfigurationError('Base URL has not been set - use Files.setBaseUrl() to set it');
|
49
101
|
case 4:
|
50
102
|
url = isExternal ? path : "".concat(baseUrl).concat(_Files.default.getEndpointPrefix()).concat(path);
|
51
103
|
_Logger.default.debug("Sending request: ".concat(verb, " ").concat(url));
|
52
|
-
_Logger.default.debug('Sending options:', _objectSpread(_objectSpread({
|
104
|
+
_Logger.default.debug('Sending options:', _objectSpread(_objectSpread({
|
105
|
+
method: verb
|
106
|
+
}, options), {}, {
|
53
107
|
headers: _objectSpread(_objectSpread({}, options.headers), {}, {
|
54
108
|
'X-FilesAPI-Key': '<redacted>'
|
55
109
|
})
|
56
110
|
}));
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
return (
|
111
|
+
_context2.prev = 7;
|
112
|
+
agent = (options === null || options === void 0 ? void 0 : options.agent) || (options === null || options === void 0 ? void 0 : options.httpsAgent) || (options === null || options === void 0 ? void 0 : options.httpAgent);
|
113
|
+
_context2.next = 11;
|
114
|
+
return fetchWithRetry(url, _objectSpread({
|
115
|
+
agent: agent,
|
61
116
|
method: verb,
|
62
|
-
|
63
|
-
url: url
|
117
|
+
timeoutSecs: _Files.default.getNetworkTimeout()
|
64
118
|
}, options));
|
65
119
|
case 11:
|
66
|
-
response =
|
120
|
+
response = _context2.sent;
|
121
|
+
headers = Object.fromEntries(response.headers.entries());
|
67
122
|
_Logger.default.debug("Status: ".concat(response.status, " ").concat(response.statusText));
|
68
123
|
if (_Files.default.shouldDebugResponseHeaders()) {
|
69
124
|
_Logger.default.debug('Response Headers: ');
|
70
|
-
_Logger.default.debug(
|
125
|
+
_Logger.default.debug(headers);
|
126
|
+
}
|
127
|
+
contentType = headers['content-type'] || '';
|
128
|
+
if (!contentType.includes('application/json')) {
|
129
|
+
_context2.next = 22;
|
130
|
+
break;
|
131
|
+
}
|
132
|
+
_context2.next = 19;
|
133
|
+
return response.json();
|
134
|
+
case 19:
|
135
|
+
data = _context2.sent;
|
136
|
+
_context2.next = 35;
|
137
|
+
break;
|
138
|
+
case 22:
|
139
|
+
if (!contentType.includes('text/')) {
|
140
|
+
_context2.next = 28;
|
141
|
+
break;
|
71
142
|
}
|
72
|
-
|
143
|
+
_context2.next = 25;
|
144
|
+
return response.text();
|
145
|
+
case 25:
|
146
|
+
data = _context2.sent;
|
147
|
+
_context2.next = 35;
|
148
|
+
break;
|
149
|
+
case 28:
|
150
|
+
if (!contentType.includes('multipart/form-data')) {
|
151
|
+
_context2.next = 34;
|
152
|
+
break;
|
153
|
+
}
|
154
|
+
_context2.next = 31;
|
155
|
+
return response.formData();
|
156
|
+
case 31:
|
157
|
+
data = _context2.sent;
|
158
|
+
_context2.next = 35;
|
159
|
+
break;
|
160
|
+
case 34:
|
161
|
+
data = response.body;
|
162
|
+
case 35:
|
163
|
+
normalizedResponse = {
|
73
164
|
status: response.status,
|
74
165
|
reason: response.statusText,
|
75
|
-
headers:
|
76
|
-
data:
|
77
|
-
}
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
166
|
+
headers: headers,
|
167
|
+
data: data
|
168
|
+
};
|
169
|
+
if (response.ok) {
|
170
|
+
_context2.next = 38;
|
171
|
+
break;
|
172
|
+
}
|
173
|
+
throw {
|
174
|
+
response: normalizedResponse
|
175
|
+
};
|
176
|
+
case 38:
|
177
|
+
return _context2.abrupt("return", normalizedResponse);
|
178
|
+
case 41:
|
179
|
+
_context2.prev = 41;
|
180
|
+
_context2.t0 = _context2["catch"](7);
|
181
|
+
errors.handleErrorResponse(_context2.t0);
|
182
|
+
case 44:
|
83
183
|
case "end":
|
84
|
-
return
|
184
|
+
return _context2.stop();
|
85
185
|
}
|
86
|
-
},
|
186
|
+
}, _callee2, null, [[7, 41]]);
|
87
187
|
}));
|
88
|
-
return function (
|
89
|
-
return
|
188
|
+
return function (_x3, _x4, _x5) {
|
189
|
+
return _ref3.apply(this, arguments);
|
90
190
|
};
|
91
191
|
}());
|
92
192
|
(0, _defineProperty2.default)(Api, "sendFilePart", function (externalUrl, verb, data) {
|
93
193
|
var headers = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
|
94
194
|
var params = {
|
95
|
-
|
195
|
+
body: data
|
96
196
|
};
|
97
197
|
if (headers) {
|
98
198
|
params.headers = headers;
|
@@ -100,20 +200,20 @@ var Api = /*#__PURE__*/(0, _createClass2.default)(function Api() {
|
|
100
200
|
return Api._sendVerbatim(externalUrl, verb, params);
|
101
201
|
});
|
102
202
|
(0, _defineProperty2.default)(Api, "_autoPaginate", /*#__PURE__*/function () {
|
103
|
-
var
|
203
|
+
var _ref4 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee3(path, verb, params, options, response, metadata) {
|
104
204
|
var _options$autoPaginate;
|
105
|
-
var _response$headers, nextCursor,
|
106
|
-
return _regenerator.default.wrap(function
|
107
|
-
while (1) switch (
|
205
|
+
var _response$headers, nextCursor, _ref5, autoPaginateCount, previousAutoPaginateData, nextPage, nextParams, nextMetadata;
|
206
|
+
return _regenerator.default.wrap(function _callee3$(_context3) {
|
207
|
+
while (1) switch (_context3.prev = _context3.next) {
|
108
208
|
case 0:
|
109
209
|
if (!((_options$autoPaginate = options.autoPaginate) !== null && _options$autoPaginate !== void 0 ? _options$autoPaginate : _Files.default.getAutoPaginate())) {
|
110
|
-
|
210
|
+
_context3.next = 12;
|
111
211
|
break;
|
112
212
|
}
|
113
213
|
nextCursor = response === null || response === void 0 || (_response$headers = response.headers) === null || _response$headers === void 0 ? void 0 : _response$headers['x-files-cursor'];
|
114
|
-
|
214
|
+
_ref5 = metadata || {}, autoPaginateCount = _ref5.autoPaginateCount, previousAutoPaginateData = _ref5.previousAutoPaginateData;
|
115
215
|
if (!nextCursor) {
|
116
|
-
|
216
|
+
_context3.next = 10;
|
117
217
|
break;
|
118
218
|
}
|
119
219
|
nextPage = (Number(params === null || params === void 0 ? void 0 : params.page) || 1) + 1;
|
@@ -125,30 +225,30 @@ var Api = /*#__PURE__*/(0, _createClass2.default)(function Api() {
|
|
125
225
|
autoPaginateCount: (autoPaginateCount || 1) + 1,
|
126
226
|
previousAutoPaginateData: [].concat((0, _toConsumableArray2.default)(previousAutoPaginateData || []), (0, _toConsumableArray2.default)((response === null || response === void 0 ? void 0 : response.data) || []))
|
127
227
|
};
|
128
|
-
return
|
228
|
+
return _context3.abrupt("return", Api.sendRequest(path, verb, nextParams, options, nextMetadata));
|
129
229
|
case 10:
|
130
230
|
if (!previousAutoPaginateData) {
|
131
|
-
|
231
|
+
_context3.next = 12;
|
132
232
|
break;
|
133
233
|
}
|
134
|
-
return
|
234
|
+
return _context3.abrupt("return", _objectSpread(_objectSpread({}, response), {}, {
|
135
235
|
autoPaginateRequests: autoPaginateCount,
|
136
236
|
data: [].concat((0, _toConsumableArray2.default)(previousAutoPaginateData), (0, _toConsumableArray2.default)((response === null || response === void 0 ? void 0 : response.data) || []))
|
137
237
|
}));
|
138
238
|
case 12:
|
139
|
-
return
|
239
|
+
return _context3.abrupt("return", response);
|
140
240
|
case 13:
|
141
241
|
case "end":
|
142
|
-
return
|
242
|
+
return _context3.stop();
|
143
243
|
}
|
144
|
-
},
|
244
|
+
}, _callee3);
|
145
245
|
}));
|
146
|
-
return function (
|
147
|
-
return
|
246
|
+
return function (_x6, _x7, _x8, _x9, _x10, _x11) {
|
247
|
+
return _ref4.apply(this, arguments);
|
148
248
|
};
|
149
249
|
}());
|
150
250
|
(0, _defineProperty2.default)(Api, "sendRequest", /*#__PURE__*/function () {
|
151
|
-
var
|
251
|
+
var _ref6 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee4(path, verb) {
|
152
252
|
var params,
|
153
253
|
options,
|
154
254
|
metadata,
|
@@ -162,13 +262,13 @@ var Api = /*#__PURE__*/(0, _createClass2.default)(function Api() {
|
|
162
262
|
hasParams,
|
163
263
|
pairs,
|
164
264
|
response,
|
165
|
-
|
166
|
-
return _regenerator.default.wrap(function
|
167
|
-
while (1) switch (
|
265
|
+
_args4 = arguments;
|
266
|
+
return _regenerator.default.wrap(function _callee4$(_context4) {
|
267
|
+
while (1) switch (_context4.prev = _context4.next) {
|
168
268
|
case 0:
|
169
|
-
params =
|
170
|
-
options =
|
171
|
-
metadata =
|
269
|
+
params = _args4.length > 2 && _args4[2] !== undefined ? _args4[2] : null;
|
270
|
+
options = _args4.length > 3 && _args4[3] !== undefined ? _args4[3] : {};
|
271
|
+
metadata = _args4.length > 4 && _args4[4] !== undefined ? _args4[4] : null;
|
172
272
|
headers = _objectSpread(_objectSpread({
|
173
273
|
Accept: 'application/json'
|
174
274
|
}, options.headers), {}, {
|
@@ -176,26 +276,26 @@ var Api = /*#__PURE__*/(0, _createClass2.default)(function Api() {
|
|
176
276
|
});
|
177
277
|
isExternal = /^[a-zA-Z]+:\/\//.test(path);
|
178
278
|
if (isExternal) {
|
179
|
-
|
279
|
+
_context4.next = 17;
|
180
280
|
break;
|
181
281
|
}
|
182
282
|
sessionId = options.sessionId || _Files.default.getSessionId();
|
183
283
|
if (!sessionId) {
|
184
|
-
|
284
|
+
_context4.next = 11;
|
185
285
|
break;
|
186
286
|
}
|
187
287
|
headers['X-FilesAPI-Auth'] = sessionId;
|
188
|
-
|
288
|
+
_context4.next = 17;
|
189
289
|
break;
|
190
290
|
case 11:
|
191
291
|
isCreatingSession = path === '/sessions' && verb.toUpperCase() === 'POST'; // api key cannot be used when creating a session
|
192
292
|
if (isCreatingSession) {
|
193
|
-
|
293
|
+
_context4.next = 17;
|
194
294
|
break;
|
195
295
|
}
|
196
296
|
apiKey = options.apiKey || _Files.default.getApiKey();
|
197
297
|
if (apiKey) {
|
198
|
-
|
298
|
+
_context4.next = 16;
|
199
299
|
break;
|
200
300
|
}
|
201
301
|
throw new errors.ConfigurationError('API key has not been set - use Files.setApiKey() to set it');
|
@@ -209,41 +309,41 @@ var Api = /*#__PURE__*/(0, _createClass2.default)(function Api() {
|
|
209
309
|
hasParams = (0, _utils.isObject)(params) && !(0, _utils.isEmpty)(params);
|
210
310
|
if (hasParams) {
|
211
311
|
if (verb.toUpperCase() === 'GET') {
|
212
|
-
pairs = Object.entries(params).map(function (
|
213
|
-
var
|
214
|
-
key =
|
215
|
-
value =
|
312
|
+
pairs = Object.entries(params).map(function (_ref7) {
|
313
|
+
var _ref8 = (0, _slicedToArray2.default)(_ref7, 2),
|
314
|
+
key = _ref8[0],
|
315
|
+
value = _ref8[1];
|
216
316
|
return "".concat(encodeURIComponent(key), "=").concat(encodeURIComponent(value));
|
217
317
|
});
|
218
318
|
requestPath += path.includes('?') ? '&' : '?';
|
219
319
|
requestPath += pairs.join('&');
|
220
320
|
} else {
|
221
|
-
updatedOptions.
|
321
|
+
updatedOptions.body = JSON.stringify(params);
|
222
322
|
headers['Content-Type'] = 'application/json';
|
223
323
|
}
|
224
324
|
}
|
225
325
|
if (_Files.default.shouldDebugRequest()) {
|
226
326
|
_Logger.default.debug('Request Options:');
|
227
327
|
_Logger.default.debug(_objectSpread(_objectSpread({}, updatedOptions), {}, {
|
228
|
-
|
328
|
+
body: hasParams ? "payload keys: ".concat(Object.keys(params).join(', ')) : '(none)',
|
229
329
|
headers: _objectSpread(_objectSpread({}, headers), {}, {
|
230
330
|
'X-FilesAPI-Key': '<redacted>'
|
231
331
|
})
|
232
332
|
}));
|
233
333
|
}
|
234
|
-
|
334
|
+
_context4.next = 24;
|
235
335
|
return Api._sendVerbatim(requestPath, verb, updatedOptions);
|
236
336
|
case 24:
|
237
|
-
response =
|
238
|
-
return
|
337
|
+
response = _context4.sent;
|
338
|
+
return _context4.abrupt("return", Api._autoPaginate(path, verb, params, updatedOptions, response, metadata));
|
239
339
|
case 26:
|
240
340
|
case "end":
|
241
|
-
return
|
341
|
+
return _context4.stop();
|
242
342
|
}
|
243
|
-
},
|
343
|
+
}, _callee4);
|
244
344
|
}));
|
245
|
-
return function (
|
246
|
-
return
|
345
|
+
return function (_x12, _x13) {
|
346
|
+
return _ref6.apply(this, arguments);
|
247
347
|
};
|
248
348
|
}());
|
249
349
|
var _default = Api;
|
package/lib/Errors.js
CHANGED
@@ -56,14 +56,14 @@ var handleErrorResponse = function handleErrorResponse(error) {
|
|
56
56
|
var message = ((_errorData = errorData) === null || _errorData === void 0 ? void 0 : _errorData.error) || (response === null || response === void 0 ? void 0 : response.statusText) || error.message;
|
57
57
|
var code = (response === null || response === void 0 ? void 0 : response.status) || ((_errorData2 = errorData) === null || _errorData2 === void 0 ? void 0 : _errorData2['http-code']) || 0;
|
58
58
|
if (!errorData) {
|
59
|
-
_Logger.default.error('FilesApiError Exception
|
59
|
+
_Logger.default.error('FilesApiError Exception:', code, message);
|
60
60
|
throw new FilesApiError(message, code);
|
61
61
|
}
|
62
62
|
if (Array.isArray(errorData)) {
|
63
63
|
errorData = errorData[0];
|
64
64
|
}
|
65
65
|
if (!errorData.type) {
|
66
|
-
_Logger.default.error('FilesApiError Exception
|
66
|
+
_Logger.default.error('FilesApiError Exception:', code, message);
|
67
67
|
throw new FilesApiError(message, code);
|
68
68
|
}
|
69
69
|
var parts = errorData.type.split('/');
|
@@ -24,8 +24,12 @@ var saveUrlToStream = /*#__PURE__*/function () {
|
|
24
24
|
var https = require('https');
|
25
25
|
https.get(url, function (response) {
|
26
26
|
response.pipe(stream);
|
27
|
-
stream.on('finish',
|
27
|
+
stream.on('finish', function () {
|
28
|
+
stream.close();
|
29
|
+
resolve();
|
30
|
+
});
|
28
31
|
}).on('error', function (error) {
|
32
|
+
stream.close();
|
29
33
|
reject(error);
|
30
34
|
});
|
31
35
|
}));
|
@@ -80,8 +84,6 @@ var saveUrlToFile = /*#__PURE__*/function () {
|
|
80
84
|
_context3.next = 3;
|
81
85
|
return saveUrlToStream(url, stream);
|
82
86
|
case 3:
|
83
|
-
stream.close();
|
84
|
-
case 4:
|
85
87
|
case "end":
|
86
88
|
return _context3.stop();
|
87
89
|
}
|
package/lib/models/Automation.js
CHANGED
@@ -59,7 +59,7 @@ var Automation = /*#__PURE__*/(0, _createClass2.default)(function Automation() {
|
|
59
59
|
(0, _defineProperty2.default)(this, "setDisabled", function (value) {
|
60
60
|
_this.attributes.disabled = value;
|
61
61
|
});
|
62
|
-
// string # How this automation is triggered to run.
|
62
|
+
// string # How this automation is triggered to run.
|
63
63
|
(0, _defineProperty2.default)(this, "getTrigger", function () {
|
64
64
|
return _this.attributes.trigger;
|
65
65
|
});
|
@@ -101,7 +101,7 @@ var Automation = /*#__PURE__*/(0, _createClass2.default)(function Automation() {
|
|
101
101
|
(0, _defineProperty2.default)(this, "setSource", function (value) {
|
102
102
|
_this.attributes.source = value;
|
103
103
|
});
|
104
|
-
// array # Destination
|
104
|
+
// array # Destination Paths
|
105
105
|
(0, _defineProperty2.default)(this, "getDestinations", function () {
|
106
106
|
return _this.attributes.destinations;
|
107
107
|
});
|
@@ -267,7 +267,7 @@ var Automation = /*#__PURE__*/(0, _createClass2.default)(function Automation() {
|
|
267
267
|
// description - string - Description for the this Automation.
|
268
268
|
// disabled - boolean - If true, this automation will not run.
|
269
269
|
// name - string - Name for this automation.
|
270
|
-
// trigger - string - How this automation is triggered to run.
|
270
|
+
// trigger - string - How this automation is triggered to run.
|
271
271
|
// trigger_actions - array(string) - If trigger is `action`, this is the list of action types on which to trigger the automation. Valid actions are create, read, update, destroy, move, copy
|
272
272
|
// value - object - A Hash of attributes specific to the automation type.
|
273
273
|
// recurring_day - int64 - If trigger type is `daily`, this specifies a day number to run in one of the supported intervals: `week`, `month`, `quarter`, `year`.
|
@@ -616,7 +616,7 @@ var Automation = /*#__PURE__*/(0, _createClass2.default)(function Automation() {
|
|
616
616
|
// description - string - Description for the this Automation.
|
617
617
|
// disabled - boolean - If true, this automation will not run.
|
618
618
|
// name - string - Name for this automation.
|
619
|
-
// trigger - string - How this automation is triggered to run.
|
619
|
+
// trigger - string - How this automation is triggered to run.
|
620
620
|
// trigger_actions - array(string) - If trigger is `action`, this is the list of action types on which to trigger the automation. Valid actions are create, read, update, destroy, move, copy
|
621
621
|
// value - object - A Hash of attributes specific to the automation type.
|
622
622
|
// recurring_day - int64 - If trigger type is `daily`, this specifies a day number to run in one of the supported intervals: `week`, `month`, `quarter`, `year`.
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "files.com",
|
3
|
-
"version": "1.0.
|
3
|
+
"version": "1.0.297",
|
4
4
|
"description": "Files.com SDK for JavaScript",
|
5
5
|
"keywords": [
|
6
6
|
"files.com",
|
@@ -20,8 +20,7 @@
|
|
20
20
|
"main": "lib/files.js",
|
21
21
|
"dependencies": {
|
22
22
|
"@babel/runtime": "^7.10.3",
|
23
|
-
"
|
24
|
-
"axios-retry": "^3.5.0",
|
23
|
+
"cross-fetch": "^4.0.0",
|
25
24
|
"readable-stream": "^4.4.0",
|
26
25
|
"safe-buffer": "^5.2.1"
|
27
26
|
},
|
package/src/Api.js
CHANGED
@@ -1,29 +1,45 @@
|
|
1
|
-
import
|
2
|
-
import axiosRetry from 'axios-retry'
|
1
|
+
import fetch from 'cross-fetch'
|
3
2
|
|
4
3
|
import Files from './Files'
|
5
4
|
import * as errors from './Errors'
|
6
5
|
import Logger from './Logger'
|
7
6
|
import { isEmpty, isObject } from './utils'
|
8
7
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
8
|
+
const _fetchWithTimeout = (url, { timeoutSecs, ...options } = {}) =>
|
9
|
+
timeoutSecs <= 0
|
10
|
+
? fetch(url, options)
|
11
|
+
: Promise.race([
|
12
|
+
fetch(url, options),
|
13
|
+
new Promise((_, reject) => {
|
14
|
+
setTimeout(() => reject(new errors.FilesError('Request timed out')), timeoutSecs * 1000)
|
15
|
+
})
|
16
|
+
])
|
17
|
+
|
18
|
+
const fetchWithRetry = async (url, options, retries = 0) => {
|
19
|
+
const maxRetries = Files.getMaxNetworkRetries()
|
20
|
+
const minRetryDelaySecs = Files.getMinNetworkRetryDelay()
|
21
|
+
const maxRetryDelaySecs = Files.getMaxNetworkRetryDelay()
|
22
|
+
|
23
|
+
try {
|
24
|
+
return await _fetchWithTimeout(url, options)
|
25
|
+
} catch (error) {
|
26
|
+
Logger.info(`Request #${retries + 1} failed: ${error.message}`)
|
27
|
+
|
28
|
+
if (retries >= maxRetries) {
|
29
|
+
throw error
|
30
|
+
} else {
|
31
|
+
const nextRetries = retries + 1
|
32
|
+
Logger.info(`Retrying request (retry ${nextRetries} of ${maxRetries})`)
|
33
|
+
|
34
|
+
const delaySecs = Math.min(minRetryDelaySecs * 2 ** retries, maxRetryDelaySecs) // exponential backoff
|
35
|
+
await new Promise(resolve => setTimeout(resolve, delaySecs * 1000))
|
36
|
+
|
37
|
+
return fetchWithRetry(url, options, nextRetries)
|
38
|
+
}
|
25
39
|
}
|
40
|
+
}
|
26
41
|
|
42
|
+
class Api {
|
27
43
|
static _sendVerbatim = async (path, verb, options) => {
|
28
44
|
const isExternal = /^[a-zA-Z]+:\/\//.test(path)
|
29
45
|
const baseUrl = Files.getBaseUrl()
|
@@ -39,6 +55,7 @@ class Api {
|
|
39
55
|
Logger.debug(`Sending request: ${verb} ${url}`)
|
40
56
|
|
41
57
|
Logger.debug('Sending options:', {
|
58
|
+
method: verb,
|
42
59
|
...options,
|
43
60
|
headers: {
|
44
61
|
...options.headers,
|
@@ -46,36 +63,57 @@ class Api {
|
|
46
63
|
},
|
47
64
|
})
|
48
65
|
|
49
|
-
Api._configureAutoRetry()
|
50
|
-
|
51
66
|
try {
|
52
|
-
const
|
67
|
+
const agent = options?.agent || options?.httpsAgent || options?.httpAgent
|
68
|
+
|
69
|
+
const response = await fetchWithRetry(url, {
|
70
|
+
agent,
|
53
71
|
method: verb,
|
54
|
-
|
55
|
-
url,
|
72
|
+
timeoutSecs: Files.getNetworkTimeout(),
|
56
73
|
...options,
|
57
74
|
})
|
58
75
|
|
76
|
+
const headers = Object.fromEntries(response.headers.entries())
|
77
|
+
|
59
78
|
Logger.debug(`Status: ${response.status} ${response.statusText}`)
|
60
79
|
|
61
80
|
if (Files.shouldDebugResponseHeaders()) {
|
62
81
|
Logger.debug('Response Headers: ')
|
63
|
-
Logger.debug(
|
82
|
+
Logger.debug(headers)
|
83
|
+
}
|
84
|
+
|
85
|
+
const contentType = headers['content-type'] || ''
|
86
|
+
let data
|
87
|
+
|
88
|
+
if (contentType.includes('application/json')) {
|
89
|
+
data = await response.json()
|
90
|
+
} else if (contentType.includes('text/')) {
|
91
|
+
data = await response.text()
|
92
|
+
} else if (contentType.includes('multipart/form-data')) {
|
93
|
+
data = await response.formData()
|
94
|
+
} else {
|
95
|
+
data = response.body
|
64
96
|
}
|
65
97
|
|
66
|
-
|
98
|
+
const normalizedResponse = {
|
67
99
|
status: response.status,
|
68
100
|
reason: response.statusText,
|
69
|
-
headers
|
70
|
-
data
|
101
|
+
headers,
|
102
|
+
data,
|
103
|
+
}
|
104
|
+
|
105
|
+
if (!response.ok) {
|
106
|
+
throw { response: normalizedResponse }
|
71
107
|
}
|
108
|
+
|
109
|
+
return normalizedResponse
|
72
110
|
} catch (error) {
|
73
111
|
errors.handleErrorResponse(error)
|
74
112
|
}
|
75
113
|
}
|
76
114
|
|
77
115
|
static sendFilePart = (externalUrl, verb, data, headers = {}) => {
|
78
|
-
const params = { data }
|
116
|
+
const params = { body: data }
|
79
117
|
|
80
118
|
if (headers) {
|
81
119
|
params.headers = headers
|
@@ -166,7 +204,7 @@ class Api {
|
|
166
204
|
requestPath += path.includes('?') ? '&' : '?'
|
167
205
|
requestPath += pairs.join('&')
|
168
206
|
} else {
|
169
|
-
updatedOptions.
|
207
|
+
updatedOptions.body = JSON.stringify(params)
|
170
208
|
headers['Content-Type'] = 'application/json'
|
171
209
|
}
|
172
210
|
}
|
@@ -175,7 +213,7 @@ class Api {
|
|
175
213
|
Logger.debug('Request Options:')
|
176
214
|
Logger.debug({
|
177
215
|
...updatedOptions,
|
178
|
-
|
216
|
+
body: hasParams
|
179
217
|
? `payload keys: ${Object.keys(params).join(', ')}`
|
180
218
|
: '(none)',
|
181
219
|
headers: {
|
package/src/Errors.js
CHANGED
@@ -32,7 +32,7 @@ export const handleErrorResponse = error => {
|
|
32
32
|
const code = response?.status || errorData?.['http-code'] || 0
|
33
33
|
|
34
34
|
if (!errorData) {
|
35
|
-
Logger.error('FilesApiError Exception
|
35
|
+
Logger.error('FilesApiError Exception:', code, message)
|
36
36
|
throw new FilesApiError(message, code)
|
37
37
|
}
|
38
38
|
|
@@ -41,7 +41,7 @@ export const handleErrorResponse = error => {
|
|
41
41
|
}
|
42
42
|
|
43
43
|
if (!errorData.type) {
|
44
|
-
Logger.error('FilesApiError Exception
|
44
|
+
Logger.error('FilesApiError Exception:', code, message)
|
45
45
|
throw new FilesApiError(message, code)
|
46
46
|
}
|
47
47
|
|
@@ -14,9 +14,13 @@ const saveUrlToStream = async (url, stream) => new Promise((resolve, reject) =>
|
|
14
14
|
https.get(url, response => {
|
15
15
|
response.pipe(stream)
|
16
16
|
|
17
|
-
stream.on('finish',
|
17
|
+
stream.on('finish', () => {
|
18
|
+
stream.close()
|
19
|
+
resolve()
|
20
|
+
})
|
18
21
|
})
|
19
22
|
.on('error', error => {
|
23
|
+
stream.close()
|
20
24
|
reject(error)
|
21
25
|
})
|
22
26
|
})
|
@@ -37,7 +41,6 @@ const saveUrlToString = async url => new Promise((resolve, reject) => {
|
|
37
41
|
const saveUrlToFile = async (url, destinationPath) => {
|
38
42
|
const stream = openDiskFileWriteStream(destinationPath)
|
39
43
|
await saveUrlToStream(url, stream)
|
40
|
-
stream.close()
|
41
44
|
}
|
42
45
|
|
43
46
|
export {
|
package/src/models/Automation.js
CHANGED
@@ -51,7 +51,7 @@ class Automation {
|
|
51
51
|
this.attributes.disabled = value
|
52
52
|
}
|
53
53
|
|
54
|
-
// string # How this automation is triggered to run.
|
54
|
+
// string # How this automation is triggered to run.
|
55
55
|
getTrigger = () => this.attributes.trigger
|
56
56
|
|
57
57
|
setTrigger = value => {
|
@@ -93,7 +93,7 @@ class Automation {
|
|
93
93
|
this.attributes.source = value
|
94
94
|
}
|
95
95
|
|
96
|
-
// array # Destination
|
96
|
+
// array # Destination Paths
|
97
97
|
getDestinations = () => this.attributes.destinations
|
98
98
|
|
99
99
|
setDestinations = value => {
|
@@ -235,7 +235,7 @@ class Automation {
|
|
235
235
|
// description - string - Description for the this Automation.
|
236
236
|
// disabled - boolean - If true, this automation will not run.
|
237
237
|
// name - string - Name for this automation.
|
238
|
-
// trigger - string - How this automation is triggered to run.
|
238
|
+
// trigger - string - How this automation is triggered to run.
|
239
239
|
// trigger_actions - array(string) - If trigger is `action`, this is the list of action types on which to trigger the automation. Valid actions are create, read, update, destroy, move, copy
|
240
240
|
// value - object - A Hash of attributes specific to the automation type.
|
241
241
|
// recurring_day - int64 - If trigger type is `daily`, this specifies a day number to run in one of the supported intervals: `week`, `month`, `quarter`, `year`.
|
@@ -422,7 +422,7 @@ class Automation {
|
|
422
422
|
// description - string - Description for the this Automation.
|
423
423
|
// disabled - boolean - If true, this automation will not run.
|
424
424
|
// name - string - Name for this automation.
|
425
|
-
// trigger - string - How this automation is triggered to run.
|
425
|
+
// trigger - string - How this automation is triggered to run.
|
426
426
|
// trigger_actions - array(string) - If trigger is `action`, this is the list of action types on which to trigger the automation. Valid actions are create, read, update, destroy, move, copy
|
427
427
|
// value - object - A Hash of attributes specific to the automation type.
|
428
428
|
// recurring_day - int64 - If trigger type is `daily`, this specifies a day number to run in one of the supported intervals: `week`, `month`, `quarter`, `year`.
|
package/test/package.json
CHANGED
package/test/src/index.js
CHANGED
@@ -1,6 +1,3 @@
|
|
1
|
-
import assert from 'assert'
|
2
|
-
// import * as errors from 'files.com/lib/Errors'
|
3
|
-
const errors = require('files.com/lib/Errors')
|
4
1
|
import Files from 'files.com/lib/Files'
|
5
2
|
import Logger, { LogLevel } from 'files.com/lib/Logger'
|
6
3
|
import ApiKey from 'files.com/lib/models/ApiKey'
|
@@ -9,6 +6,9 @@ import Folder from 'files.com/lib/models/Folder'
|
|
9
6
|
import Session from 'files.com/lib/models/Session'
|
10
7
|
import User from 'files.com/lib/models/User'
|
11
8
|
import { isBrowser } from 'files.com/lib/utils'
|
9
|
+
import invariant from 'tiny-invariant'
|
10
|
+
|
11
|
+
const errors = require('files.com/lib/Errors')
|
12
12
|
|
13
13
|
// name of an existing folder in your root to create/delete test files and folders
|
14
14
|
const SDK_TEST_ROOT_FOLDER = 'sdk-test'
|
@@ -32,11 +32,17 @@ if (apiDomain.substr(-10) === 'staging.av') {
|
|
32
32
|
process.env.NODE_TLS_REJECT_UNAUTHORIZED = 0
|
33
33
|
}
|
34
34
|
|
35
|
-
|
35
|
+
const DEBUG_MODE = false
|
36
|
+
|
37
|
+
Files.setLogLevel(DEBUG_MODE ? LogLevel.DEBUG : LogLevel.INFO)
|
36
38
|
|
37
39
|
Files.configureDebugging({
|
38
|
-
debugRequest:
|
39
|
-
debugResponseHeaders:
|
40
|
+
debugRequest: DEBUG_MODE,
|
41
|
+
debugResponseHeaders: DEBUG_MODE,
|
42
|
+
})
|
43
|
+
|
44
|
+
Files.configureNetwork({
|
45
|
+
networkTimeout: DEBUG_MODE ? 10 : 30,
|
40
46
|
})
|
41
47
|
|
42
48
|
const testSuite = async () => {
|
@@ -49,7 +55,7 @@ const testSuite = async () => {
|
|
49
55
|
|
50
56
|
const firstPageItems = await Folder.listFor('/', { per_page: 1 })
|
51
57
|
|
52
|
-
|
58
|
+
invariant(firstPageItems.length === 1, 'First page should have 1 item')
|
53
59
|
|
54
60
|
Files.configureNetwork({
|
55
61
|
autoPaginate: true,
|
@@ -59,7 +65,7 @@ const testSuite = async () => {
|
|
59
65
|
const allPageItems = await Folder.listFor('/', { per_page: 1 })
|
60
66
|
|
61
67
|
// if auto-pagination executed, we'll have found more than just the 1 we requested
|
62
|
-
|
68
|
+
invariant(allPageItems.length > 1, 'Auto-pagination should have found more than 1 item across all pages')
|
63
69
|
|
64
70
|
Logger.info('***** testFolderListAutoPagination() succeeded! *****')
|
65
71
|
}
|
@@ -72,18 +78,20 @@ const testSuite = async () => {
|
|
72
78
|
|
73
79
|
const file = await File.uploadFile(destinationPath, sourceFilePath)
|
74
80
|
|
75
|
-
|
76
|
-
|
81
|
+
invariant(!!file.path, 'Uploaded file response object should have a path')
|
82
|
+
invariant(file.display_name === displayName, 'Uploaded file response object should have the same display_name as the file we uploaded')
|
77
83
|
|
78
84
|
const foundFile = await File.find(destinationPath)
|
79
85
|
|
80
|
-
|
81
|
-
|
82
|
-
|
86
|
+
invariant(foundFile.path === destinationPath, 'Found file should have the same path as the file we uploaded')
|
87
|
+
invariant(foundFile.display_name === displayName, 'Found file should have the same display_name as the file we uploaded')
|
88
|
+
invariant(typeof foundFile.getDownloadUri() === 'undefined', 'Found file should not have a download uri yet')
|
83
89
|
|
84
90
|
if (!isBrowser()) {
|
85
91
|
const downloadableFile = await foundFile.download()
|
86
|
-
|
92
|
+
|
93
|
+
invariant(downloadableFile.size > 0, 'Uploaded file should not be empty')
|
94
|
+
invariant(typeof downloadableFile.getDownloadUri() !== 'undefined', 'Downloadable file should have a download uri')
|
87
95
|
|
88
96
|
const downloadPath = `./${displayName}`
|
89
97
|
await downloadableFile.downloadToFile(downloadPath)
|
@@ -92,7 +100,8 @@ const testSuite = async () => {
|
|
92
100
|
const originalBuffer = fs.readFileSync(sourceFilePath)
|
93
101
|
const downloadedBuffer = fs.readFileSync(downloadPath)
|
94
102
|
|
95
|
-
|
103
|
+
invariant(originalBuffer.length === downloadedBuffer.length, 'Source file length should match downloaded file length')
|
104
|
+
invariant(originalBuffer.equals(downloadedBuffer), 'Source file contents should match downloaded file contents')
|
96
105
|
|
97
106
|
fs.unlinkSync(downloadPath)
|
98
107
|
}
|
@@ -109,22 +118,22 @@ const testSuite = async () => {
|
|
109
118
|
const sourceFileContents = 'The quick brown fox jumped over the lazy dogs.'
|
110
119
|
const file = await File.uploadData(destinationPath, sourceFileContents)
|
111
120
|
|
112
|
-
|
113
|
-
|
121
|
+
invariant(!!file.path, 'Uploaded file response object should have a path')
|
122
|
+
invariant(file.display_name === displayName, 'Uploaded file response object should have the same display_name as the file we uploaded')
|
114
123
|
|
115
124
|
const foundFile = await File.find(destinationPath)
|
116
125
|
|
117
|
-
|
118
|
-
|
119
|
-
|
126
|
+
invariant(foundFile.path === destinationPath, 'Found file should have the same path as the file we uploaded')
|
127
|
+
invariant(foundFile.display_name === displayName, 'Found file should have the same display_name as the file we uploaded')
|
128
|
+
invariant(typeof foundFile.getDownloadUri() === 'undefined', 'Found file should not have a download uri yet')
|
120
129
|
|
121
130
|
if (!isBrowser()) {
|
122
131
|
const downloadableFile = await foundFile.download()
|
123
|
-
|
132
|
+
invariant(typeof downloadableFile.getDownloadUri() !== 'undefined', 'Downloadable file should have a download uri')
|
124
133
|
|
125
134
|
const downloadedFileContents = await downloadableFile.downloadToString()
|
126
135
|
|
127
|
-
|
136
|
+
invariant(sourceFileContents === downloadedFileContents, 'Source file contents should match downloaded file contents')
|
128
137
|
}
|
129
138
|
|
130
139
|
await file.delete()
|
@@ -141,14 +150,14 @@ const testSuite = async () => {
|
|
141
150
|
|
142
151
|
const file = await File.uploadFile(destinationPath, sourceFilePath)
|
143
152
|
|
144
|
-
|
145
|
-
|
153
|
+
invariant(!!file.path, 'Uploaded file response object should have a path')
|
154
|
+
invariant(file.display_name === displayName, 'Uploaded file response object should have the same display_name as the file we uploaded')
|
146
155
|
|
147
156
|
const foundFile = await File.find(destinationPath)
|
148
157
|
|
149
|
-
|
150
|
-
|
151
|
-
|
158
|
+
invariant(foundFile.path === destinationPath, 'Found file should have the same path as the file we uploaded')
|
159
|
+
invariant(foundFile.display_name === displayName, 'Found file should have the same display_name as the file we uploaded')
|
160
|
+
invariant(typeof foundFile.getDownloadUri() === 'undefined', 'Found file should not have a download uri yet')
|
152
161
|
|
153
162
|
await file.delete()
|
154
163
|
|
@@ -167,7 +176,7 @@ const testSuite = async () => {
|
|
167
176
|
|
168
177
|
const session = await Session.create({ username, password })
|
169
178
|
|
170
|
-
|
179
|
+
invariant(!!session.id, 'Session should have an id')
|
171
180
|
|
172
181
|
const manual = await ApiKey.list({ user_id: 0 }, { sessionId: session.id })
|
173
182
|
|
@@ -175,7 +184,7 @@ const testSuite = async () => {
|
|
175
184
|
|
176
185
|
const auto = await ApiKey.list({ user_id: 0 })
|
177
186
|
|
178
|
-
|
187
|
+
invariant(JSON.stringify(manual.attributes) === JSON.stringify(auto.attributes), 'Manual and auto session API key lists should match')
|
179
188
|
|
180
189
|
await Session.destroy()
|
181
190
|
|
@@ -197,7 +206,7 @@ const testSuite = async () => {
|
|
197
206
|
caughtInvalidCredentialsError = error instanceof errors.NotAuthenticated_InvalidCredentialsError
|
198
207
|
}
|
199
208
|
|
200
|
-
|
209
|
+
invariant(caughtInvalidCredentialsError === true, 'should have caught an invalid credentials error')
|
201
210
|
|
202
211
|
// restore valid api key
|
203
212
|
Files.setApiKey(apiKey)
|
@@ -218,9 +227,9 @@ const testSuite = async () => {
|
|
218
227
|
|
219
228
|
const updatedUser = await User.find(firstUser.id)
|
220
229
|
|
221
|
-
|
222
|
-
|
223
|
-
|
230
|
+
invariant(updatedUser.isLoaded(), 'updated user should be loaded')
|
231
|
+
invariant(oldName !== newName, 'old name should not equal new name')
|
232
|
+
invariant(updatedUser.name === newName, 'updated user name should match new name')
|
224
233
|
|
225
234
|
Logger.info('***** testUserListAndUpdate() succeeded! *****');
|
226
235
|
}
|
@@ -229,13 +238,18 @@ const testSuite = async () => {
|
|
229
238
|
// execute all tests
|
230
239
|
//
|
231
240
|
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
241
|
+
try {
|
242
|
+
await testFolderListAutoPagination()
|
243
|
+
await testUploadAndDownloadToFile()
|
244
|
+
await testUploadAndDownloadToString()
|
245
|
+
// await testUploadHugeFile() // to run this test, put a file (or symlink) at huge-file.ext
|
246
|
+
await testSession()
|
247
|
+
await testFailure()
|
248
|
+
await testUserListAndUpdate()
|
249
|
+
} catch (error) {
|
250
|
+
console.log('*** TEST SUITE FAILED ***')
|
251
|
+
console.error(error)
|
252
|
+
}
|
239
253
|
}
|
240
254
|
|
241
255
|
export default testSuite
|