contentful-export 8.2.1 → 8.2.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.
|
@@ -13,19 +13,26 @@ var _stream = require("stream");
|
|
|
13
13
|
var _util = require("util");
|
|
14
14
|
var _embargoedAssets = require("../utils/embargoedAssets");
|
|
15
15
|
var _axios = _interopRequireDefault(require("axios"));
|
|
16
|
+
var _axiosRetry = _interopRequireDefault(require("axios-retry"));
|
|
16
17
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
17
18
|
const streamPipeline = (0, _util.promisify)(_stream.pipeline);
|
|
18
19
|
|
|
20
|
+
// For streaming responses, axios timeout applies to time-to-first-byte, not total transfer duration
|
|
21
|
+
const DEFAULT_DOWNLOAD_TIMEOUT_MS = 30000;
|
|
22
|
+
const DEFAULT_RETRY_LIMIT = 3;
|
|
23
|
+
|
|
19
24
|
/**
|
|
20
25
|
* @param {Object} options - The options for downloading the asset.
|
|
21
26
|
* @param {string} options.url - The URL of the asset to download.
|
|
22
27
|
* @param {string} options.directory - The directory where the asset should be saved.
|
|
23
28
|
* @param {import('axios').AxiosInstance} options.httpClient - The HTTP client to use for downloading the asset.
|
|
29
|
+
* @param {string} options.assetId - The ID of the asset being downloaded, used in error messages.
|
|
24
30
|
*/
|
|
25
31
|
async function downloadAsset({
|
|
26
32
|
url,
|
|
27
33
|
directory,
|
|
28
|
-
httpClient
|
|
34
|
+
httpClient,
|
|
35
|
+
assetId
|
|
29
36
|
}) {
|
|
30
37
|
// handle urls without protocol
|
|
31
38
|
if (url.startsWith('//')) {
|
|
@@ -57,7 +64,14 @@ async function downloadAsset({
|
|
|
57
64
|
* @type {import('axios').AxiosError}
|
|
58
65
|
*/
|
|
59
66
|
const axiosError = e;
|
|
60
|
-
|
|
67
|
+
if (axiosError.response) {
|
|
68
|
+
throw new Error(`error downloading asset ${assetId} (${url}): HTTP ${axiosError.response.status} ${axiosError.response.statusText}`, {
|
|
69
|
+
cause: axiosError
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
throw new Error(`error downloading asset ${assetId} (${url}): ${e.message}`, {
|
|
73
|
+
cause: e
|
|
74
|
+
});
|
|
61
75
|
}
|
|
62
76
|
}
|
|
63
77
|
function downloadAssets(options) {
|
|
@@ -67,11 +81,24 @@ function downloadAssets(options) {
|
|
|
67
81
|
let errorCount = 0;
|
|
68
82
|
const httpClient = _axios.default.create({
|
|
69
83
|
headers: options.headers,
|
|
70
|
-
timeout:
|
|
84
|
+
timeout: DEFAULT_DOWNLOAD_TIMEOUT_MS,
|
|
71
85
|
httpAgent: options.httpAgent,
|
|
72
86
|
httpsAgent: options.httpsAgent,
|
|
73
87
|
proxy: options.proxy
|
|
74
88
|
});
|
|
89
|
+
(0, _axiosRetry.default)(httpClient, {
|
|
90
|
+
retries: DEFAULT_RETRY_LIMIT,
|
|
91
|
+
retryDelay: _axiosRetry.default.exponentialDelay,
|
|
92
|
+
shouldResetTimeout: true,
|
|
93
|
+
retryCondition: error => {
|
|
94
|
+
var _error$response;
|
|
95
|
+
return _axiosRetry.default.isNetworkOrIdempotentRequestError(error) || ((_error$response = error.response) === null || _error$response === void 0 ? void 0 : _error$response.status) === 429;
|
|
96
|
+
},
|
|
97
|
+
onRetry: (retryCount, error) => {
|
|
98
|
+
const status = error.response ? `HTTP ${error.response.status}` : error.code || error.message;
|
|
99
|
+
_contentfulBatchLibs.logEmitter.emit('warning', `Asset download failed (${status}), retrying (attempt ${retryCount})...`);
|
|
100
|
+
}
|
|
101
|
+
});
|
|
75
102
|
return _bluebird.default.map(ctx.data.assets, asset => {
|
|
76
103
|
const entityName = (0, _contentfulBatchLibs.getEntityName)(asset);
|
|
77
104
|
if (!asset.fields.file) {
|
|
@@ -87,10 +114,12 @@ function downloadAssets(options) {
|
|
|
87
114
|
errorCount++;
|
|
88
115
|
return _bluebird.default.resolve();
|
|
89
116
|
}
|
|
117
|
+
const assetId = asset.sys.id;
|
|
90
118
|
let startingPromise = _bluebird.default.resolve({
|
|
91
119
|
url,
|
|
92
120
|
directory: options.exportDir,
|
|
93
|
-
httpClient
|
|
121
|
+
httpClient,
|
|
122
|
+
assetId
|
|
94
123
|
});
|
|
95
124
|
if ((0, _embargoedAssets.isEmbargoedAsset)(url)) {
|
|
96
125
|
const {
|
|
@@ -103,13 +132,15 @@ function downloadAssets(options) {
|
|
|
103
132
|
startingPromise = (0, _embargoedAssets.signUrl)(host, accessToken, spaceId, environmentId, url, expiresAtMs, httpClient).then(signedUrl => ({
|
|
104
133
|
url: signedUrl,
|
|
105
134
|
directory: options.exportDir,
|
|
106
|
-
httpClient
|
|
135
|
+
httpClient,
|
|
136
|
+
assetId
|
|
107
137
|
}));
|
|
108
138
|
}
|
|
109
139
|
return startingPromise.then(downloadAsset).then(() => {
|
|
110
140
|
task.output = `${_figures.default.tick} downloaded ${entityName} (${url})`;
|
|
111
141
|
successCount++;
|
|
112
142
|
}).catch(error => {
|
|
143
|
+
_contentfulBatchLibs.logEmitter.emit('warning', error.message);
|
|
113
144
|
task.output = `${_figures.default.cross} error downloading ${url}: ${error.message}`;
|
|
114
145
|
errorCount++;
|
|
115
146
|
});
|
|
@@ -71,8 +71,11 @@ function getFullSourceSpace({
|
|
|
71
71
|
method: 'getTags'
|
|
72
72
|
}).then(extractItems).then(items => {
|
|
73
73
|
ctx.data.tags = items;
|
|
74
|
-
}).catch(
|
|
75
|
-
|
|
74
|
+
}).catch(err => {
|
|
75
|
+
_contentfulBatchLibs.logEmitter.emit('error', new Error(`Fetching tags failed: ${err.message}`, {
|
|
76
|
+
cause: err
|
|
77
|
+
}));
|
|
78
|
+
throw err;
|
|
76
79
|
});
|
|
77
80
|
}),
|
|
78
81
|
skip: () => skipTags
|
|
@@ -257,7 +260,7 @@ function getEditorInterfaces(contentTypes) {
|
|
|
257
260
|
}).catch(() => {
|
|
258
261
|
// old contentTypes may not have an editor interface but we'll handle in a later stage
|
|
259
262
|
// but it should not stop getting the data process
|
|
260
|
-
_contentfulBatchLibs.logEmitter.emit('warning', `No editor interface found for ${contentType}`);
|
|
263
|
+
_contentfulBatchLibs.logEmitter.emit('warning', `No editor interface found for ${contentType.name || contentType.sys.id}`);
|
|
261
264
|
return _bluebird.default.resolve(null);
|
|
262
265
|
});
|
|
263
266
|
}, {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "contentful-export",
|
|
3
|
-
"version": "8.2.
|
|
3
|
+
"version": "8.2.2",
|
|
4
4
|
"description": "this tool allows you to export a space to a JSON dump",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "types.d.ts",
|
|
@@ -46,6 +46,7 @@
|
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
48
|
"axios": "^1.13.5",
|
|
49
|
+
"axios-retry": "^4.5.0",
|
|
49
50
|
"bfj": "^9.1.3",
|
|
50
51
|
"bluebird": "^3.3.3",
|
|
51
52
|
"cli-table3": "^0.6.0",
|