gtx-cli 1.2.4 → 1.2.5-alpha.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/dist/api/checkFileTranslations.js +107 -118
- package/dist/api/downloadFile.js +38 -47
- package/dist/api/downloadFileBatch.js +69 -77
- package/dist/api/fetchTranslations.js +17 -25
- package/dist/api/sendFiles.js +47 -56
- package/dist/api/sendUpdates.js +48 -45
- package/dist/api/waitForUpdates.js +15 -21
- package/dist/cli/base.js +133 -148
- package/dist/cli/react.js +149 -166
- package/dist/config/generateSettings.js +71 -83
- package/dist/config/validateSettings.js +1 -2
- package/dist/console/logging.d.ts +1 -1
- package/dist/console/logging.js +62 -115
- package/dist/formats/files/save.js +10 -21
- package/dist/formats/files/translate.js +127 -136
- package/dist/formats/gt/save.js +16 -27
- package/dist/fs/config/parseFilesConfig.js +6 -8
- package/dist/fs/config/setupConfig.js +32 -36
- package/dist/fs/config/updateConfig.js +27 -30
- package/dist/fs/determineFramework.js +4 -1
- package/dist/fs/findFilepath.js +1 -2
- package/dist/fs/index.d.ts +1 -0
- package/dist/fs/index.js +1 -0
- package/dist/fs/saveJSON.js +4 -15
- package/dist/hooks/postProcess.js +97 -107
- package/dist/next/config/parseNextConfig.js +44 -51
- package/dist/next/parse/handleInitGT.js +101 -112
- package/dist/next/parse/wrapContent.js +108 -112
- package/dist/react/config/createESBuildConfig.js +3 -12
- package/dist/react/data-_gt/addGTIdentifierToSyntaxTree.js +11 -19
- package/dist/react/jsx/parse/parseStringFunction.js +3 -5
- package/dist/react/jsx/trimJsxStringChildren.js +5 -2
- package/dist/react/jsx/utils/parseAst.js +5 -6
- package/dist/react/jsx/utils/parseJsx.js +1 -1
- package/dist/react/jsx/utils/parseStringFunction.js +3 -5
- package/dist/react/parse/createDictionaryUpdates.js +58 -56
- package/dist/react/parse/createInlineUpdates.js +111 -118
- package/dist/react/parse/wrapContent.js +124 -128
- package/dist/react/utils/getVariableName.js +1 -2
- package/dist/setup/userInput.js +22 -33
- package/dist/setup/wizard.js +133 -134
- package/dist/translation/parse.js +52 -63
- package/dist/translation/stage.js +61 -68
- package/dist/translation/translate.js +13 -24
- package/dist/utils/credentials.js +75 -89
- package/dist/utils/installPackage.js +30 -41
- package/dist/utils/packageJson.js +49 -58
- package/dist/utils/packageManager.js +82 -54
- package/package.json +28 -11
- package/tsconfig.json +3 -3
|
@@ -1,13 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
2
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
4
|
};
|
|
@@ -28,43 +19,41 @@ const downloadFileBatch_1 = require("./downloadFileBatch");
|
|
|
28
19
|
* @param timeoutDuration - The timeout duration for the wait in seconds
|
|
29
20
|
* @returns True if all translations are deployed, false otherwise
|
|
30
21
|
*/
|
|
31
|
-
function checkFileTranslations(apiKey, baseUrl, data, locales, timeoutDuration, resolveOutputPath, downloadStatus) {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
resolve(true);
|
|
59
|
-
}
|
|
60
|
-
else {
|
|
61
|
-
spinner.fail(chalk_1.default.red('Timed out waiting for translations'));
|
|
62
|
-
resolve(false);
|
|
63
|
-
}
|
|
22
|
+
async function checkFileTranslations(apiKey, baseUrl, data, locales, timeoutDuration, resolveOutputPath, downloadStatus) {
|
|
23
|
+
const startTime = Date.now();
|
|
24
|
+
console.log();
|
|
25
|
+
const spinner = await (0, console_1.createOraSpinner)();
|
|
26
|
+
spinner.start('Waiting for translation...');
|
|
27
|
+
// Initialize the query data
|
|
28
|
+
const fileQueryData = prepareFileQueryData(data, locales);
|
|
29
|
+
// Do first check immediately
|
|
30
|
+
const initialCheck = await checkTranslationDeployment(baseUrl, apiKey, fileQueryData, downloadStatus, spinner, resolveOutputPath);
|
|
31
|
+
if (initialCheck) {
|
|
32
|
+
spinner.succeed(chalk_1.default.green('Files translated!'));
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
// Calculate time until next 5-second interval since startTime
|
|
36
|
+
const msUntilNextInterval = Math.max(0, 5000 - ((Date.now() - startTime) % 5000));
|
|
37
|
+
return new Promise((resolve) => {
|
|
38
|
+
let intervalCheck;
|
|
39
|
+
// Start the interval aligned with the original request time
|
|
40
|
+
setTimeout(() => {
|
|
41
|
+
intervalCheck = setInterval(async () => {
|
|
42
|
+
const isDeployed = await checkTranslationDeployment(baseUrl, apiKey, fileQueryData, downloadStatus, spinner, resolveOutputPath);
|
|
43
|
+
const elapsed = Date.now() - startTime;
|
|
44
|
+
if (isDeployed || elapsed >= timeoutDuration * 1000) {
|
|
45
|
+
clearInterval(intervalCheck);
|
|
46
|
+
if (isDeployed) {
|
|
47
|
+
spinner.succeed(chalk_1.default.green('All files translated!'));
|
|
48
|
+
resolve(true);
|
|
64
49
|
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
50
|
+
else {
|
|
51
|
+
spinner.fail(chalk_1.default.red('Timed out waiting for translations'));
|
|
52
|
+
resolve(false);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}, 5000);
|
|
56
|
+
}, msUntilNextInterval);
|
|
68
57
|
});
|
|
69
58
|
}
|
|
70
59
|
/**
|
|
@@ -90,7 +79,6 @@ function prepareFileQueryData(data, locales) {
|
|
|
90
79
|
* @returns Formatted status text
|
|
91
80
|
*/
|
|
92
81
|
function generateStatusSuffixText(downloadStatus, fileQueryData) {
|
|
93
|
-
var _a;
|
|
94
82
|
// Simple progress indicator
|
|
95
83
|
const progressText = chalk_1.default.green(`[${downloadStatus.downloaded.size + downloadStatus.failed.size}/${fileQueryData.length}]`) + ` translations completed`;
|
|
96
84
|
// Get terminal height to adapt our output
|
|
@@ -112,7 +100,7 @@ function generateStatusSuffixText(downloadStatus, fileQueryData) {
|
|
|
112
100
|
});
|
|
113
101
|
}
|
|
114
102
|
else {
|
|
115
|
-
|
|
103
|
+
fileStatus.get(item.fileName)?.pending.add(item.locale);
|
|
116
104
|
}
|
|
117
105
|
}
|
|
118
106
|
// Mark which ones are completed or failed
|
|
@@ -174,82 +162,83 @@ function generateStatusSuffixText(downloadStatus, fileQueryData) {
|
|
|
174
162
|
/**
|
|
175
163
|
* Checks translation status and downloads ready files
|
|
176
164
|
*/
|
|
177
|
-
function checkTranslationDeployment(baseUrl, apiKey, fileQueryData, downloadStatus, spinner, resolveOutputPath) {
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
downloadStatus.failed.add(fileLocale);
|
|
224
|
-
}
|
|
225
|
-
});
|
|
226
|
-
}
|
|
227
|
-
else if (batchFiles.length === 1) {
|
|
228
|
-
// For a single file, use the original downloadFile method
|
|
229
|
-
const file = batchFiles[0];
|
|
230
|
-
const result = yield (0, downloadFile_1.downloadFile)(baseUrl, apiKey, file.translationId, file.outputPath);
|
|
231
|
-
if (result) {
|
|
232
|
-
downloadStatus.downloaded.add(file.fileLocale);
|
|
165
|
+
async function checkTranslationDeployment(baseUrl, apiKey, fileQueryData, downloadStatus, spinner, resolveOutputPath) {
|
|
166
|
+
try {
|
|
167
|
+
// Only query for files that haven't been downloaded yet
|
|
168
|
+
const currentQueryData = fileQueryData.filter((item) => !downloadStatus.downloaded.has(`${item.fileName}:${item.locale}`) &&
|
|
169
|
+
!downloadStatus.failed.has(`${item.fileName}:${item.locale}`));
|
|
170
|
+
// If all files have been downloaded, we're done
|
|
171
|
+
if (currentQueryData.length === 0) {
|
|
172
|
+
return true;
|
|
173
|
+
}
|
|
174
|
+
const response = await fetch(`${baseUrl}/v1/project/translations/files/retrieve`, {
|
|
175
|
+
method: 'POST',
|
|
176
|
+
headers: {
|
|
177
|
+
'Content-Type': 'application/json',
|
|
178
|
+
...(apiKey && { 'x-gt-api-key': apiKey }),
|
|
179
|
+
},
|
|
180
|
+
body: JSON.stringify({ files: currentQueryData }),
|
|
181
|
+
});
|
|
182
|
+
if (response.ok) {
|
|
183
|
+
const responseData = await response.json();
|
|
184
|
+
const translations = responseData.translations || [];
|
|
185
|
+
// Filter for ready translations
|
|
186
|
+
const readyTranslations = translations.filter((translation) => translation.isReady && translation.fileName);
|
|
187
|
+
if (readyTranslations.length > 0) {
|
|
188
|
+
// Prepare batch download data
|
|
189
|
+
const batchFiles = readyTranslations.map((translation) => {
|
|
190
|
+
const locale = translation.locale;
|
|
191
|
+
const fileName = translation.fileName;
|
|
192
|
+
const translationId = translation.id;
|
|
193
|
+
const outputPath = resolveOutputPath(fileName, locale);
|
|
194
|
+
return {
|
|
195
|
+
translationId,
|
|
196
|
+
outputPath,
|
|
197
|
+
fileLocale: `${fileName}:${locale}`,
|
|
198
|
+
};
|
|
199
|
+
});
|
|
200
|
+
// Use batch download if there are multiple files
|
|
201
|
+
if (batchFiles.length > 1) {
|
|
202
|
+
const batchResult = await (0, downloadFileBatch_1.downloadFileBatch)(baseUrl, apiKey, batchFiles.map(({ translationId, outputPath }) => ({
|
|
203
|
+
translationId,
|
|
204
|
+
outputPath,
|
|
205
|
+
})));
|
|
206
|
+
// Process results
|
|
207
|
+
batchFiles.forEach((file) => {
|
|
208
|
+
const { translationId, fileLocale } = file;
|
|
209
|
+
if (batchResult.successful.includes(translationId)) {
|
|
210
|
+
downloadStatus.downloaded.add(fileLocale);
|
|
233
211
|
}
|
|
234
|
-
else {
|
|
235
|
-
downloadStatus.failed.add(
|
|
212
|
+
else if (batchResult.failed.includes(translationId)) {
|
|
213
|
+
downloadStatus.failed.add(fileLocale);
|
|
236
214
|
}
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
else if (batchFiles.length === 1) {
|
|
218
|
+
// For a single file, use the original downloadFile method
|
|
219
|
+
const file = batchFiles[0];
|
|
220
|
+
const result = await (0, downloadFile_1.downloadFile)(baseUrl, apiKey, file.translationId, file.outputPath);
|
|
221
|
+
if (result) {
|
|
222
|
+
downloadStatus.downloaded.add(file.fileLocale);
|
|
223
|
+
}
|
|
224
|
+
else {
|
|
225
|
+
downloadStatus.failed.add(file.fileLocale);
|
|
237
226
|
}
|
|
238
227
|
}
|
|
239
|
-
// Force a refresh of the spinner display
|
|
240
|
-
const statusText = generateStatusSuffixText(downloadStatus, fileQueryData);
|
|
241
|
-
// Clear and reapply the suffix to force a refresh
|
|
242
|
-
spinner.text = statusText;
|
|
243
|
-
}
|
|
244
|
-
if (downloadStatus.downloaded.size + downloadStatus.failed.size ===
|
|
245
|
-
fileQueryData.length) {
|
|
246
|
-
return true;
|
|
247
228
|
}
|
|
248
|
-
|
|
229
|
+
// Force a refresh of the spinner display
|
|
230
|
+
const statusText = generateStatusSuffixText(downloadStatus, fileQueryData);
|
|
231
|
+
// Clear and reapply the suffix to force a refresh
|
|
232
|
+
spinner.text = statusText;
|
|
249
233
|
}
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
return
|
|
234
|
+
if (downloadStatus.downloaded.size + downloadStatus.failed.size ===
|
|
235
|
+
fileQueryData.length) {
|
|
236
|
+
return true;
|
|
253
237
|
}
|
|
254
|
-
|
|
238
|
+
return false;
|
|
239
|
+
}
|
|
240
|
+
catch (error) {
|
|
241
|
+
(0, console_1.logError)(chalk_1.default.red('Error checking translation status: ') + error);
|
|
242
|
+
return false;
|
|
243
|
+
}
|
|
255
244
|
}
|
package/dist/api/downloadFile.js
CHANGED
|
@@ -32,61 +32,52 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
32
32
|
return result;
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
36
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
37
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
38
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
39
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
40
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
41
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
42
|
-
});
|
|
43
|
-
};
|
|
44
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
36
|
exports.downloadFile = downloadFile;
|
|
46
37
|
const fs = __importStar(require("fs"));
|
|
47
38
|
const path = __importStar(require("path"));
|
|
48
39
|
const console_1 = require("../console/console");
|
|
49
40
|
// Helper function to download a file
|
|
50
|
-
function downloadFile(
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
}
|
|
65
|
-
// Get the file data as an ArrayBuffer
|
|
66
|
-
const fileData = yield downloadResponse.arrayBuffer();
|
|
67
|
-
// Write the file to disk
|
|
68
|
-
yield fs.promises.writeFile(outputPath, Buffer.from(fileData));
|
|
69
|
-
return true;
|
|
41
|
+
async function downloadFile(baseUrl, apiKey, translationId, outputPath, maxRetries = 3, retryDelay = 1000) {
|
|
42
|
+
let retries = 0;
|
|
43
|
+
while (retries <= maxRetries) {
|
|
44
|
+
try {
|
|
45
|
+
const downloadResponse = await fetch(`${baseUrl}/v1/project/translations/files/${translationId}/download`, {
|
|
46
|
+
method: 'GET',
|
|
47
|
+
headers: {
|
|
48
|
+
...(apiKey && { 'x-gt-api-key': apiKey }),
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
if (downloadResponse.ok) {
|
|
52
|
+
// Ensure the directory exists
|
|
53
|
+
const dir = path.dirname(outputPath);
|
|
54
|
+
if (!fs.existsSync(dir)) {
|
|
55
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
70
56
|
}
|
|
71
|
-
//
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
// Increment retry counter and wait before next attempt
|
|
77
|
-
retries++;
|
|
78
|
-
yield new Promise((resolve) => setTimeout(resolve, retryDelay));
|
|
57
|
+
// Get the file data as an ArrayBuffer
|
|
58
|
+
const fileData = await downloadResponse.arrayBuffer();
|
|
59
|
+
// Write the file to disk
|
|
60
|
+
await fs.promises.writeFile(outputPath, Buffer.from(fileData));
|
|
61
|
+
return true;
|
|
79
62
|
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
return false;
|
|
85
|
-
}
|
|
86
|
-
retries++;
|
|
87
|
-
yield new Promise((resolve) => setTimeout(resolve, retryDelay));
|
|
63
|
+
// If we get here, the response was not OK
|
|
64
|
+
if (retries >= maxRetries) {
|
|
65
|
+
(0, console_1.logError)(`Failed to download file ${outputPath}. Status: ${downloadResponse.status} after ${maxRetries + 1} attempts.`);
|
|
66
|
+
return false;
|
|
88
67
|
}
|
|
68
|
+
// Increment retry counter and wait before next attempt
|
|
69
|
+
retries++;
|
|
70
|
+
await new Promise((resolve) => setTimeout(resolve, retryDelay));
|
|
89
71
|
}
|
|
90
|
-
|
|
91
|
-
|
|
72
|
+
catch (error) {
|
|
73
|
+
if (retries >= maxRetries) {
|
|
74
|
+
(0, console_1.logError)(`Error downloading file ${outputPath} after ${maxRetries + 1} attempts: ` +
|
|
75
|
+
error);
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
retries++;
|
|
79
|
+
await new Promise((resolve) => setTimeout(resolve, retryDelay));
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return false;
|
|
92
83
|
}
|
|
@@ -32,15 +32,6 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
32
32
|
return result;
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
36
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
37
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
38
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
39
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
40
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
41
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
42
|
-
});
|
|
43
|
-
};
|
|
44
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
36
|
exports.downloadFileBatch = downloadFileBatch;
|
|
46
37
|
const fs = __importStar(require("fs"));
|
|
@@ -55,81 +46,82 @@ const console_1 = require("../console/console");
|
|
|
55
46
|
* @param retryDelay - Delay between retries in milliseconds
|
|
56
47
|
* @returns Object containing successful and failed file IDs
|
|
57
48
|
*/
|
|
58
|
-
function downloadFileBatch(
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
const dir = path.dirname(outputPath);
|
|
87
|
-
if (!fs.existsSync(dir)) {
|
|
88
|
-
fs.mkdirSync(dir, { recursive: true });
|
|
89
|
-
}
|
|
90
|
-
// Write the file to disk
|
|
91
|
-
yield fs.promises.writeFile(outputPath, file.data);
|
|
92
|
-
result.successful.push(translationId);
|
|
49
|
+
async function downloadFileBatch(baseUrl, apiKey, files, maxRetries = 3, retryDelay = 1000) {
|
|
50
|
+
let retries = 0;
|
|
51
|
+
const fileIds = files.map((file) => file.translationId);
|
|
52
|
+
const result = { successful: [], failed: [] };
|
|
53
|
+
// Create a map of translationId to outputPath for easier lookup
|
|
54
|
+
const outputPathMap = new Map(files.map((file) => [file.translationId, file.outputPath]));
|
|
55
|
+
while (retries <= maxRetries) {
|
|
56
|
+
try {
|
|
57
|
+
const response = await fetch(`${baseUrl}/v1/project/translations/files/batch-download`, {
|
|
58
|
+
method: 'POST',
|
|
59
|
+
headers: {
|
|
60
|
+
'Content-Type': 'application/json',
|
|
61
|
+
...(apiKey && { 'x-gt-api-key': apiKey }),
|
|
62
|
+
},
|
|
63
|
+
body: JSON.stringify({ fileIds }),
|
|
64
|
+
});
|
|
65
|
+
if (response.ok) {
|
|
66
|
+
const responseData = await response.json();
|
|
67
|
+
const downloadedFiles = responseData.files || [];
|
|
68
|
+
// Process each file in the response
|
|
69
|
+
for (const file of downloadedFiles) {
|
|
70
|
+
try {
|
|
71
|
+
const translationId = file.id;
|
|
72
|
+
const outputPath = outputPathMap.get(translationId);
|
|
73
|
+
if (!outputPath) {
|
|
74
|
+
(0, console_1.logWarning)(`No output path found for file: ${translationId}`);
|
|
75
|
+
result.failed.push(translationId);
|
|
76
|
+
continue;
|
|
93
77
|
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
78
|
+
// Ensure the directory exists
|
|
79
|
+
const dir = path.dirname(outputPath);
|
|
80
|
+
if (!fs.existsSync(dir)) {
|
|
81
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
97
82
|
}
|
|
83
|
+
// Write the file to disk
|
|
84
|
+
await fs.promises.writeFile(outputPath, file.data);
|
|
85
|
+
result.successful.push(translationId);
|
|
98
86
|
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
if (!downloadedIds.has(fileId) && !result.failed.includes(fileId)) {
|
|
103
|
-
result.failed.push(fileId);
|
|
104
|
-
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
(0, console_1.logError)(`Error saving file ${file.id}: ` + error);
|
|
89
|
+
result.failed.push(file.id);
|
|
105
90
|
}
|
|
106
|
-
return result;
|
|
107
91
|
}
|
|
108
|
-
//
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
92
|
+
// Add any files that weren't in the response to the failed list
|
|
93
|
+
const downloadedIds = new Set(downloadedFiles.map((file) => file.id));
|
|
94
|
+
for (const fileId of fileIds) {
|
|
95
|
+
if (!downloadedIds.has(fileId) && !result.failed.includes(fileId)) {
|
|
96
|
+
result.failed.push(fileId);
|
|
97
|
+
}
|
|
114
98
|
}
|
|
115
|
-
|
|
116
|
-
retries++;
|
|
117
|
-
yield new Promise((resolve) => setTimeout(resolve, retryDelay));
|
|
99
|
+
return result;
|
|
118
100
|
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
return result;
|
|
126
|
-
}
|
|
127
|
-
retries++;
|
|
128
|
-
yield new Promise((resolve) => setTimeout(resolve, retryDelay));
|
|
101
|
+
// If we get here, the response was not OK
|
|
102
|
+
if (retries >= maxRetries) {
|
|
103
|
+
(0, console_1.logError)(`Failed to download files in batch. Status: ${response.status} after ${maxRetries + 1} attempts.`);
|
|
104
|
+
// Mark all files as failed
|
|
105
|
+
result.failed = [...fileIds];
|
|
106
|
+
return result;
|
|
129
107
|
}
|
|
108
|
+
// Increment retry counter and wait before next attempt
|
|
109
|
+
retries++;
|
|
110
|
+
await new Promise((resolve) => setTimeout(resolve, retryDelay));
|
|
130
111
|
}
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
112
|
+
catch (error) {
|
|
113
|
+
if (retries >= maxRetries) {
|
|
114
|
+
(0, console_1.logError)(`Error downloading files in batch after ${maxRetries + 1} attempts: ` +
|
|
115
|
+
error);
|
|
116
|
+
// Mark all files as failed
|
|
117
|
+
result.failed = [...fileIds];
|
|
118
|
+
return result;
|
|
119
|
+
}
|
|
120
|
+
retries++;
|
|
121
|
+
await new Promise((resolve) => setTimeout(resolve, retryDelay));
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
// Mark all files as failed if we get here
|
|
125
|
+
result.failed = [...fileIds];
|
|
126
|
+
return result;
|
|
135
127
|
}
|
|
@@ -1,13 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
2
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
4
|
};
|
|
@@ -23,21 +14,22 @@ const errors_1 = require("../console/errors");
|
|
|
23
14
|
* @param translationsDir - The directory to save the translations to
|
|
24
15
|
* @param fileType - The file type to save the translations as (file extension)
|
|
25
16
|
*/
|
|
26
|
-
function fetchTranslations(baseUrl, apiKey, versionId) {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
const data = yield response.json();
|
|
35
|
-
const translations = data.translations;
|
|
36
|
-
return translations;
|
|
37
|
-
}
|
|
38
|
-
else {
|
|
39
|
-
(0, errors_1.logError)(chalk_1.default.red('Failed to fetch translations'));
|
|
40
|
-
}
|
|
41
|
-
return [];
|
|
17
|
+
async function fetchTranslations(baseUrl, apiKey, versionId) {
|
|
18
|
+
// First fetch the translations from the API
|
|
19
|
+
const response = await fetch(`${baseUrl}/v1/project/translations/info/${encodeURIComponent(versionId)}`, {
|
|
20
|
+
method: 'GET',
|
|
21
|
+
headers: {
|
|
22
|
+
'Content-Type': 'application/json',
|
|
23
|
+
...(apiKey && { 'x-gt-api-key': apiKey }),
|
|
24
|
+
},
|
|
42
25
|
});
|
|
26
|
+
if (response.ok) {
|
|
27
|
+
const data = await response.json();
|
|
28
|
+
const translations = data.translations;
|
|
29
|
+
return translations;
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
(0, errors_1.logError)(chalk_1.default.red('Failed to fetch translations'));
|
|
33
|
+
}
|
|
34
|
+
return [];
|
|
43
35
|
}
|