locize-cli 7.15.0 → 7.15.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 +8 -0
- package/download.js +39 -4
- package/package.json +2 -2
- package/request.js +32 -25
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,14 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
Project versioning adheres to [Semantic Versioning](http://semver.org/).
|
|
6
6
|
Change log format is based on [Keep a Changelog](http://keepachangelog.com/).
|
|
7
7
|
|
|
8
|
+
## [7.15.2](https://github.com/locize/locize-cli/compare/v7.15.1...v7.15.2) - 2023-01-06
|
|
9
|
+
|
|
10
|
+
- optimize --skip-empty false handling for download command
|
|
11
|
+
|
|
12
|
+
## [7.15.1](https://github.com/locize/locize-cli/compare/v7.15.0...v7.15.1) - 2023-12-19
|
|
13
|
+
|
|
14
|
+
- refactor retriable requests handling
|
|
15
|
+
|
|
8
16
|
## [7.15.0](https://github.com/locize/locize-cli/compare/v7.14.15...v7.15.0) - 2023-12-18
|
|
9
17
|
|
|
10
18
|
- locize sync: show publish mode advice if necessary
|
package/download.js
CHANGED
|
@@ -151,6 +151,43 @@ const handleError = (err, cb) => {
|
|
|
151
151
|
if (cb) cb(err);
|
|
152
152
|
};
|
|
153
153
|
|
|
154
|
+
const filterDownloads = (opt, downloads) => {
|
|
155
|
+
if (opt.skipEmpty) return downloads.filter((d) => d.size > 2);
|
|
156
|
+
if (downloads.length < 1) return downloads;
|
|
157
|
+
|
|
158
|
+
const allNamespaces = [];
|
|
159
|
+
const downloadMap = {};
|
|
160
|
+
downloads.forEach((d) => {
|
|
161
|
+
const splitted = d.key.split('/');
|
|
162
|
+
const p = splitted[d.isPrivate ? 1 : 0];
|
|
163
|
+
const v = splitted[d.isPrivate ? 2 : 1];
|
|
164
|
+
const l = splitted[d.isPrivate ? 3 : 2];
|
|
165
|
+
const n = splitted[d.isPrivate ? 4 : 3];
|
|
166
|
+
downloadMap[p] = downloadMap[p] || {};
|
|
167
|
+
downloadMap[p][v] = downloadMap[p][v] || {};
|
|
168
|
+
downloadMap[p][v][l] = downloadMap[p][v][l] || {};
|
|
169
|
+
downloadMap[p][v][l][n] = d;
|
|
170
|
+
if (allNamespaces.indexOf(n) < 0) allNamespaces.push(n);
|
|
171
|
+
});
|
|
172
|
+
Object.keys(downloadMap).forEach((projectId) => {
|
|
173
|
+
Object.keys(downloadMap[projectId]).forEach((version) => {
|
|
174
|
+
Object.keys(downloadMap[projectId][version]).forEach((language) => {
|
|
175
|
+
allNamespaces.forEach((namespace) => {
|
|
176
|
+
if (!downloadMap[projectId][version][language][namespace]) {
|
|
177
|
+
downloads.push({
|
|
178
|
+
url: `${opt.apiPath}/${projectId}/${version}/${language}/${namespace}`,
|
|
179
|
+
key: `${projectId}/${version}/${language}/${namespace}`,
|
|
180
|
+
lastModified: '1960-01-01T00:00:00.000Z',
|
|
181
|
+
size: 0
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
});
|
|
186
|
+
});
|
|
187
|
+
});
|
|
188
|
+
return downloads;
|
|
189
|
+
};
|
|
190
|
+
|
|
154
191
|
const download = (opt, cb) => {
|
|
155
192
|
opt.format = opt.format || 'json';
|
|
156
193
|
if (!reversedFileExtensionsMap[opt.format]) {
|
|
@@ -203,20 +240,18 @@ const download = (opt, cb) => {
|
|
|
203
240
|
'Authorization': opt.apiKey
|
|
204
241
|
} : undefined
|
|
205
242
|
}, (err, res, obj) => {
|
|
206
|
-
obj = obj || [];
|
|
207
243
|
if (res && res.status === 401) {
|
|
208
244
|
opt.apiKey = null;
|
|
209
245
|
request(url, {
|
|
210
246
|
method: 'get',
|
|
211
247
|
}, (err, res, obj) => {
|
|
212
|
-
obj = obj || [];
|
|
213
|
-
if (opt.skipEmpty) obj = obj.filter((d) => d.size > 2);
|
|
248
|
+
obj = filterDownloads(opt, obj || []);
|
|
214
249
|
handleDownload(opt, url, err, res, obj, cb);
|
|
215
250
|
});
|
|
216
251
|
return;
|
|
217
252
|
}
|
|
218
253
|
|
|
219
|
-
|
|
254
|
+
obj = filterDownloads(opt, obj || []);
|
|
220
255
|
handleDownload(opt, url, err, res, obj, cb);
|
|
221
256
|
});
|
|
222
257
|
return;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "locize-cli",
|
|
3
|
-
"version": "7.15.
|
|
3
|
+
"version": "7.15.2",
|
|
4
4
|
"description": "locize cli to import locales",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"xlsx": "https://cdn.sheetjs.com/xlsx-0.20.0/xlsx-0.20.0.tgz"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
|
-
"eslint": "8.
|
|
37
|
+
"eslint": "8.56.0",
|
|
38
38
|
"gh-release": "7.0.2",
|
|
39
39
|
"pkg": "5.8.1"
|
|
40
40
|
},
|
package/request.js
CHANGED
|
@@ -8,6 +8,28 @@ cacheable.install(https.globalAgent);
|
|
|
8
8
|
|
|
9
9
|
const httpProxy = process.env.http_proxy || process.env.HTTP_PROXY || process.env.https_proxy || process.env.HTTPS_PROXY;
|
|
10
10
|
|
|
11
|
+
const isRetriableError = (err) => {
|
|
12
|
+
return err && err.message && (
|
|
13
|
+
err.message.indexOf('ETIMEDOUT') > -1 || // on timeout retry
|
|
14
|
+
// on dns errors
|
|
15
|
+
err.message.indexOf('ENOTFOUND') > -1 ||
|
|
16
|
+
err.message.indexOf('ENODATA') > -1 ||
|
|
17
|
+
err.message.indexOf('ENOENT') > -1 // Windows: name exists, but not this record type
|
|
18
|
+
);
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const isJSONResponse = (res) => res.headers.get('content-type') && res.headers.get('content-type').indexOf('json') > 0;
|
|
22
|
+
|
|
23
|
+
const handleResponse = (res) => {
|
|
24
|
+
if (isJSONResponse(res)) {
|
|
25
|
+
return new Promise((resolve, reject) => res.json().then((obj) => resolve({ res, obj })).catch(reject));
|
|
26
|
+
} else {
|
|
27
|
+
return { res };
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const handleSuccessful = (callback) => (ret) => callback(null, ret.res, ret.obj);
|
|
32
|
+
|
|
11
33
|
module.exports = (url, options, callback) => {
|
|
12
34
|
if (httpProxy) {
|
|
13
35
|
const httpsProxyAgent = new HttpsProxyAgent(httpProxy);
|
|
@@ -25,31 +47,16 @@ module.exports = (url, options, callback) => {
|
|
|
25
47
|
}
|
|
26
48
|
}
|
|
27
49
|
if (options.headers['Authorization'] === undefined) delete options.headers['Authorization'];
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
}
|
|
34
|
-
}).then((ret) => callback(null, ret.res, ret.obj)).catch((err) => {
|
|
35
|
-
if (err && err.message && (
|
|
36
|
-
err.message.indexOf('ETIMEDOUT') > -1 || // on timeout retry
|
|
37
|
-
// on dns errors
|
|
38
|
-
err.message.indexOf('ENOTFOUND') > -1 ||
|
|
39
|
-
err.message.indexOf('ENODATA') > -1 ||
|
|
40
|
-
err.message.indexOf('ENOENT') > -1 // Windows: name exists, but not this record type
|
|
41
|
-
)) {
|
|
50
|
+
|
|
51
|
+
function retriableFetch(maxRetries) {
|
|
52
|
+
fetch(url, options).then(handleResponse).then(handleSuccessful(callback)).catch((err) => {
|
|
53
|
+
if (maxRetries < 1) return callback(err);
|
|
54
|
+
if (!isRetriableError(err)) return callback(err);
|
|
42
55
|
setTimeout(() => {
|
|
43
|
-
|
|
44
|
-
if (res.headers.get('content-type') && res.headers.get('content-type').indexOf('json') > 0) {
|
|
45
|
-
return new Promise((resolve, reject) => res.json().then((obj) => resolve({ res, obj })).catch(reject));
|
|
46
|
-
} else {
|
|
47
|
-
return { res };
|
|
48
|
-
}
|
|
49
|
-
}).then((ret) => callback(null, ret.res, ret.obj)).catch(callback);
|
|
56
|
+
retriableFetch(--maxRetries);
|
|
50
57
|
}, 5000);
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
retriableFetch(3);
|
|
55
62
|
};
|