contentful-export 7.20.0 → 7.21.0
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/dist/index.js +3 -1
- package/dist/parseOptions.js +14 -12
- package/dist/tasks/download-assets.js +36 -13
- package/dist/usageParams.js +1 -1
- package/dist/utils/embargoedAssets.js +27 -11
- package/package.json +7 -3
package/dist/index.js
CHANGED
@@ -170,7 +170,9 @@ function runContentfulExport(params) {
|
|
170
170
|
return (0, _contentfulBatchLibs.writeErrorLogFile)(options.errorLogFile, errorLog).then(() => {
|
171
171
|
const multiError = new Error('Errors occured');
|
172
172
|
multiError.name = 'ContentfulMultiError';
|
173
|
-
multiError
|
173
|
+
Object.assign(multiError, {
|
174
|
+
errors: errorLog
|
175
|
+
});
|
174
176
|
throw multiError;
|
175
177
|
});
|
176
178
|
}
|
package/dist/parseOptions.js
CHANGED
@@ -8,7 +8,7 @@ var _contentfulBatchLibs = require("contentful-batch-libs");
|
|
8
8
|
var _format = require("date-fns/format");
|
9
9
|
var _path = require("path");
|
10
10
|
var _querystring = _interopRequireDefault(require("querystring"));
|
11
|
-
var _package = require("../package");
|
11
|
+
var _package = require("../package.json");
|
12
12
|
var _headers = require("./utils/headers");
|
13
13
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
14
14
|
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
@@ -48,11 +48,6 @@ function parseOptions(params) {
|
|
48
48
|
if (!options.managementToken) {
|
49
49
|
throw new Error('The `managementToken` option is required.');
|
50
50
|
}
|
51
|
-
const proxySimpleExp = /.+:\d+/;
|
52
|
-
const proxyAuthExp = /.+:.+@.+:\d+/;
|
53
|
-
if (options.proxy && !(proxySimpleExp.test(options.proxy) || proxyAuthExp.test(options.proxy))) {
|
54
|
-
throw new Error('Please provide the proxy config in the following format:\nhost:port or user:password@host:port');
|
55
|
-
}
|
56
51
|
options.startTime = new Date();
|
57
52
|
options.contentFile = options.contentFile || `contentful-export-${options.spaceId}-${options.environmentId}-${(0, _format.format)(options.startTime, "yyyy-MM-dd'T'HH-mm-ss")}.json`;
|
58
53
|
options.logFilePath = (0, _path.resolve)(options.exportDir, options.contentFile);
|
@@ -64,12 +59,19 @@ function parseOptions(params) {
|
|
64
59
|
|
65
60
|
// Further processing
|
66
61
|
options.accessToken = options.managementToken;
|
67
|
-
if (
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
62
|
+
if (options.proxy) {
|
63
|
+
if (typeof options.proxy === 'string') {
|
64
|
+
const proxySimpleExp = /.+:\d+/;
|
65
|
+
const proxyAuthExp = /.+:.+@.+:\d+/;
|
66
|
+
if (!(proxySimpleExp.test(options.proxy) || proxyAuthExp.test(options.proxy))) {
|
67
|
+
throw new Error('Please provide the proxy config in the following format:\nhost:port or user:password@host:port');
|
68
|
+
}
|
69
|
+
options.proxy = (0, _contentfulBatchLibs.proxyStringToObject)(options.proxy);
|
70
|
+
}
|
71
|
+
if (!options.rawProxy) {
|
72
|
+
options.httpsAgent = (0, _contentfulBatchLibs.agentFromProxy)(options.proxy);
|
73
|
+
delete options.proxy;
|
74
|
+
}
|
73
75
|
}
|
74
76
|
if (options.queryEntries && options.queryEntries.length > 0) {
|
75
77
|
const querystr = options.queryEntries.join('&');
|
@@ -8,16 +8,24 @@ var _bluebird = _interopRequireDefault(require("bluebird"));
|
|
8
8
|
var _contentfulBatchLibs = require("contentful-batch-libs");
|
9
9
|
var _figures = _interopRequireDefault(require("figures"));
|
10
10
|
var _fs = require("fs");
|
11
|
-
var _nodeFetch = _interopRequireDefault(require("node-fetch"));
|
12
11
|
var _path = _interopRequireDefault(require("path"));
|
13
12
|
var _stream = require("stream");
|
14
13
|
var _util = require("util");
|
15
14
|
var _embargoedAssets = require("../utils/embargoedAssets");
|
15
|
+
var _axios = _interopRequireDefault(require("axios"));
|
16
16
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
17
17
|
const streamPipeline = (0, _util.promisify)(_stream.pipeline);
|
18
|
+
|
19
|
+
/**
|
20
|
+
* @param {Object} options - The options for downloading the asset.
|
21
|
+
* @param {string} options.url - The URL of the asset to download.
|
22
|
+
* @param {string} options.directory - The directory where the asset should be saved.
|
23
|
+
* @param {import('axios').AxiosInstance} options.httpClient - The HTTP client to use for downloading the asset.
|
24
|
+
*/
|
18
25
|
async function downloadAsset({
|
19
26
|
url,
|
20
|
-
directory
|
27
|
+
directory,
|
28
|
+
httpClient
|
21
29
|
}) {
|
22
30
|
// handle urls without protocol
|
23
31
|
if (url.startsWith('//')) {
|
@@ -33,22 +41,35 @@ async function downloadAsset({
|
|
33
41
|
recursive: true
|
34
42
|
});
|
35
43
|
const file = (0, _fs.createWriteStream)(localFile);
|
44
|
+
try {
|
45
|
+
// download asset
|
46
|
+
const assetRequest = await httpClient.get(url, {
|
47
|
+
responseType: 'blob'
|
48
|
+
});
|
36
49
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
50
|
+
// Wait for stream to be consumed before returning local file
|
51
|
+
await streamPipeline(assetRequest.data, file);
|
52
|
+
return localFile;
|
53
|
+
} catch (e) {
|
54
|
+
/**
|
55
|
+
* @type {import('axios').AxiosError}
|
56
|
+
*/
|
57
|
+
const axiosError = e;
|
58
|
+
throw new Error(`error response status: ${axiosError.response.status}`);
|
41
59
|
}
|
42
|
-
|
43
|
-
// Wait for stream to be consumed before returning local file
|
44
|
-
await streamPipeline(assetRequest.body, file);
|
45
|
-
return localFile;
|
46
60
|
}
|
47
61
|
function downloadAssets(options) {
|
48
62
|
return (ctx, task) => {
|
49
63
|
let successCount = 0;
|
50
64
|
let warningCount = 0;
|
51
65
|
let errorCount = 0;
|
66
|
+
const httpClient = _axios.default.create({
|
67
|
+
headers: options.headers,
|
68
|
+
timeout: options.timeout,
|
69
|
+
httpAgent: options.httpAgent,
|
70
|
+
httpsAgent: options.httpsAgent,
|
71
|
+
proxy: options.proxy
|
72
|
+
});
|
52
73
|
return _bluebird.default.map(ctx.data.assets, asset => {
|
53
74
|
if (!asset.fields.file) {
|
54
75
|
task.output = `${_figures.default.warning} asset ${(0, _contentfulBatchLibs.getEntityName)(asset)} has no file(s)`;
|
@@ -65,7 +86,8 @@ function downloadAssets(options) {
|
|
65
86
|
}
|
66
87
|
let startingPromise = _bluebird.default.resolve({
|
67
88
|
url,
|
68
|
-
directory: options.exportDir
|
89
|
+
directory: options.exportDir,
|
90
|
+
httpClient
|
69
91
|
});
|
70
92
|
if ((0, _embargoedAssets.isEmbargoedAsset)(url)) {
|
71
93
|
const {
|
@@ -75,9 +97,10 @@ function downloadAssets(options) {
|
|
75
97
|
environmentId
|
76
98
|
} = options;
|
77
99
|
const expiresAtMs = (0, _embargoedAssets.calculateExpiryTimestamp)();
|
78
|
-
startingPromise = (0, _embargoedAssets.signUrl)(host, accessToken, spaceId, environmentId, url, expiresAtMs).then(signedUrl => ({
|
100
|
+
startingPromise = (0, _embargoedAssets.signUrl)(host, accessToken, spaceId, environmentId, url, expiresAtMs, httpClient).then(signedUrl => ({
|
79
101
|
url: signedUrl,
|
80
|
-
directory: options.exportDir
|
102
|
+
directory: options.exportDir,
|
103
|
+
httpClient
|
81
104
|
}));
|
82
105
|
}
|
83
106
|
return startingPromise.then(downloadAsset).then(downLoadedFile => {
|
package/dist/usageParams.js
CHANGED
@@ -5,7 +5,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
5
5
|
});
|
6
6
|
exports.default = void 0;
|
7
7
|
var _yargs = _interopRequireDefault(require("yargs"));
|
8
|
-
var _package = _interopRequireDefault(require("../package"));
|
8
|
+
var _package = _interopRequireDefault(require("../package.json"));
|
9
9
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
10
10
|
var _default = exports.default = _yargs.default.version(_package.default.version || 'Version only available on installed package').usage('Usage: $0 [options]').option('space-id', {
|
11
11
|
describe: 'ID of Space with source data',
|
@@ -8,14 +8,22 @@ exports.isEmbargoedAsset = isEmbargoedAsset;
|
|
8
8
|
exports.shouldCreateNewCacheItem = void 0;
|
9
9
|
exports.signUrl = signUrl;
|
10
10
|
var _jsonwebtoken = _interopRequireDefault(require("jsonwebtoken"));
|
11
|
-
var _nodeFetch = _interopRequireDefault(require("node-fetch"));
|
12
11
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
13
12
|
const SIX_HOURS_IN_MS = 6 * 60 * 60 * 1000;
|
14
13
|
const assetKeyCache = new Map();
|
15
|
-
|
16
|
-
|
14
|
+
|
15
|
+
/**
|
16
|
+
* @param {string} host - The Contentful API host.
|
17
|
+
* @param {string} accessToken - The access token for the Contentful API.
|
18
|
+
* @param {string} spaceId - The ID of the Contentful space.
|
19
|
+
* @param {string} environmentId - The ID of the Contentful environment.
|
20
|
+
* @param {number} expiresAtMs - The expiration time in milliseconds.
|
21
|
+
* @param {import('axios').AxiosInstance} httpClient - The HTTP client to use for requests.
|
22
|
+
*/
|
23
|
+
function createAssetKey(host, accessToken, spaceId, environmentId, expiresAtMs, httpClient) {
|
24
|
+
return httpClient(`https://${host}/spaces/${spaceId}/environments/${environmentId}/asset_keys`, {
|
17
25
|
method: 'POST',
|
18
|
-
|
26
|
+
data: JSON.stringify({
|
19
27
|
expiresAt: Math.floor(expiresAtMs / 1000) // in seconds
|
20
28
|
}),
|
21
29
|
headers: {
|
@@ -26,7 +34,7 @@ function createAssetKey(host, accessToken, spaceId, environmentId, expiresAtMs)
|
|
26
34
|
}
|
27
35
|
const shouldCreateNewCacheItem = (cacheItem, currentExpiresAtMs) => !cacheItem || currentExpiresAtMs - cacheItem.expiresAtMs > SIX_HOURS_IN_MS;
|
28
36
|
exports.shouldCreateNewCacheItem = shouldCreateNewCacheItem;
|
29
|
-
async function createCachedAssetKey(host, accessToken, spaceId, environmentId, minExpiresAtMs) {
|
37
|
+
async function createCachedAssetKey(host, accessToken, spaceId, environmentId, minExpiresAtMs, httpClient) {
|
30
38
|
const cacheKey = `${host}:${spaceId}:${environmentId}`;
|
31
39
|
let cacheItem = assetKeyCache.get(cacheKey);
|
32
40
|
if (shouldCreateNewCacheItem(cacheItem, minExpiresAtMs)) {
|
@@ -35,12 +43,10 @@ async function createCachedAssetKey(host, accessToken, spaceId, environmentId, m
|
|
35
43
|
throw new Error(`Cannot fetch an asset key so far in the future: ${minExpiresAtMs} > ${expiresAtMs}`);
|
36
44
|
}
|
37
45
|
try {
|
38
|
-
const
|
39
|
-
const resolvedAssetKeyPromise = await assetKeyPromise;
|
40
|
-
const result = await resolvedAssetKeyPromise.json();
|
46
|
+
const assetKeyResponse = await createAssetKey(host, accessToken, spaceId, environmentId, expiresAtMs, httpClient);
|
41
47
|
cacheItem = {
|
42
48
|
expiresAtMs,
|
43
|
-
result
|
49
|
+
result: assetKeyResponse.data
|
44
50
|
};
|
45
51
|
assetKeyCache.set(cacheKey, cacheItem);
|
46
52
|
} catch (err) {
|
@@ -79,12 +85,22 @@ function isEmbargoedAsset(url) {
|
|
79
85
|
function calculateExpiryTimestamp() {
|
80
86
|
return Date.now() + SIX_HOURS_IN_MS;
|
81
87
|
}
|
82
|
-
|
88
|
+
|
89
|
+
/**
|
90
|
+
* @param {string} host - The Contentful API host.
|
91
|
+
* @param {string} accessToken - The access token for the Contentful API.
|
92
|
+
* @param {string} spaceId - The ID of the Contentful space.
|
93
|
+
* @param {string} environmentId - The ID of the Contentful environment.
|
94
|
+
* @param {string} url - The URL to be signed.
|
95
|
+
* @param {number} expiresAtMs - The expiration time in milliseconds.
|
96
|
+
* @param {import('axios').AxiosInstance} httpClient - The HTTP client to use for requests.
|
97
|
+
*/
|
98
|
+
function signUrl(host, accessToken, spaceId, environmentId, url, expiresAtMs, httpClient) {
|
83
99
|
// handle urls without protocol
|
84
100
|
if (url.startsWith('//')) {
|
85
101
|
url = 'https:' + url;
|
86
102
|
}
|
87
|
-
return createCachedAssetKey(host, accessToken, spaceId, environmentId, expiresAtMs).then(({
|
103
|
+
return createCachedAssetKey(host, accessToken, spaceId, environmentId, expiresAtMs, httpClient).then(({
|
88
104
|
policy,
|
89
105
|
secret
|
90
106
|
}) => generateSignedUrl(policy, secret, url, expiresAtMs));
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "contentful-export",
|
3
|
-
"version": "7.
|
3
|
+
"version": "7.21.0",
|
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",
|
@@ -11,8 +11,9 @@
|
|
11
11
|
"contentful-export": "./bin/contentful-export"
|
12
12
|
},
|
13
13
|
"scripts": {
|
14
|
-
"build": "npm run clean && babel lib --out-dir dist",
|
14
|
+
"build": "npm run clean && npm run check && babel lib --out-dir dist",
|
15
15
|
"build:watch": "babel lib --out-dir dist --watch",
|
16
|
+
"check": "tsc",
|
16
17
|
"clean": "rimraf dist && rimraf coverage",
|
17
18
|
"lint": "eslint lib bin/* types.d.ts",
|
18
19
|
"lint:fix": "npm run lint -- --fix",
|
@@ -44,6 +45,7 @@
|
|
44
45
|
"url": "https://github.com/contentful/contentful-export/issues"
|
45
46
|
},
|
46
47
|
"dependencies": {
|
48
|
+
"axios": "^1.7.8",
|
47
49
|
"bfj": "^8.0.0",
|
48
50
|
"bluebird": "^3.3.3",
|
49
51
|
"cli-table3": "^0.6.0",
|
@@ -58,7 +60,6 @@
|
|
58
60
|
"listr-verbose-renderer": "^0.6.0",
|
59
61
|
"lodash.startcase": "^4.4.0",
|
60
62
|
"mkdirp": "^2.0.0",
|
61
|
-
"node-fetch": "^2.6.7",
|
62
63
|
"yargs": "^17.1.1"
|
63
64
|
},
|
64
65
|
"devDependencies": {
|
@@ -136,5 +137,8 @@
|
|
136
137
|
"coveragePathIgnorePatterns": [
|
137
138
|
"usageParams.js"
|
138
139
|
]
|
140
|
+
},
|
141
|
+
"overrides": {
|
142
|
+
"cross-spawn": "^7.0.6"
|
139
143
|
}
|
140
144
|
}
|