gtx-cli 2.3.5 → 2.3.6-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.
Files changed (191) hide show
  1. package/package.json +23 -18
  2. package/dist/api/checkFileTranslations.d.ts +0 -23
  3. package/dist/api/checkFileTranslations.js +0 -236
  4. package/dist/api/downloadFileBatch.d.ts +0 -20
  5. package/dist/api/downloadFileBatch.js +0 -113
  6. package/dist/api/sendFiles.d.ts +0 -17
  7. package/dist/api/sendFiles.js +0 -115
  8. package/dist/api/uploadFiles.d.ts +0 -27
  9. package/dist/api/uploadFiles.js +0 -40
  10. package/dist/cli/base.d.ts +0 -32
  11. package/dist/cli/base.js +0 -335
  12. package/dist/cli/commands/stage.d.ts +0 -5
  13. package/dist/cli/commands/stage.js +0 -100
  14. package/dist/cli/commands/translate.d.ts +0 -6
  15. package/dist/cli/commands/translate.js +0 -63
  16. package/dist/cli/flags.d.ts +0 -3
  17. package/dist/cli/flags.js +0 -38
  18. package/dist/cli/next.d.ts +0 -11
  19. package/dist/cli/next.js +0 -20
  20. package/dist/cli/react.d.ts +0 -18
  21. package/dist/cli/react.js +0 -175
  22. package/dist/config/generateSettings.d.ts +0 -9
  23. package/dist/config/generateSettings.js +0 -176
  24. package/dist/config/optionPresets.d.ts +0 -2
  25. package/dist/config/optionPresets.js +0 -56
  26. package/dist/config/resolveConfig.d.ts +0 -4
  27. package/dist/config/resolveConfig.js +0 -19
  28. package/dist/config/utils.d.ts +0 -2
  29. package/dist/config/utils.js +0 -4
  30. package/dist/config/validateSettings.d.ts +0 -3
  31. package/dist/config/validateSettings.js +0 -32
  32. package/dist/console/colors.d.ts +0 -5
  33. package/dist/console/colors.js +0 -16
  34. package/dist/console/index.d.ts +0 -21
  35. package/dist/console/index.js +0 -24
  36. package/dist/console/logging.d.ts +0 -53
  37. package/dist/console/logging.js +0 -185
  38. package/dist/formats/files/fileMapping.d.ts +0 -11
  39. package/dist/formats/files/fileMapping.js +0 -82
  40. package/dist/formats/files/save.d.ts +0 -5
  41. package/dist/formats/files/save.js +0 -17
  42. package/dist/formats/files/supportedFiles.d.ts +0 -10
  43. package/dist/formats/files/supportedFiles.js +0 -18
  44. package/dist/formats/files/translate.d.ts +0 -4
  45. package/dist/formats/files/translate.js +0 -119
  46. package/dist/formats/files/upload.d.ts +0 -13
  47. package/dist/formats/files/upload.js +0 -136
  48. package/dist/formats/gt/save.d.ts +0 -9
  49. package/dist/formats/gt/save.js +0 -26
  50. package/dist/formats/json/flattenJson.d.ts +0 -14
  51. package/dist/formats/json/flattenJson.js +0 -64
  52. package/dist/formats/json/mergeJson.d.ts +0 -13
  53. package/dist/formats/json/mergeJson.js +0 -257
  54. package/dist/formats/json/parseJson.d.ts +0 -2
  55. package/dist/formats/json/parseJson.js +0 -108
  56. package/dist/formats/json/utils.d.ts +0 -47
  57. package/dist/formats/json/utils.js +0 -149
  58. package/dist/formats/utils.d.ts +0 -2
  59. package/dist/formats/utils.js +0 -24
  60. package/dist/formats/yaml/mergeYaml.d.ts +0 -5
  61. package/dist/formats/yaml/mergeYaml.js +0 -55
  62. package/dist/formats/yaml/parseYaml.d.ts +0 -5
  63. package/dist/formats/yaml/parseYaml.js +0 -23
  64. package/dist/formats/yaml/utils.d.ts +0 -2
  65. package/dist/formats/yaml/utils.js +0 -22
  66. package/dist/fs/config/loadConfig.d.ts +0 -1
  67. package/dist/fs/config/loadConfig.js +0 -9
  68. package/dist/fs/config/parseFilesConfig.d.ts +0 -27
  69. package/dist/fs/config/parseFilesConfig.js +0 -129
  70. package/dist/fs/config/setupConfig.d.ts +0 -17
  71. package/dist/fs/config/setupConfig.js +0 -50
  72. package/dist/fs/config/updateConfig.d.ts +0 -10
  73. package/dist/fs/config/updateConfig.js +0 -36
  74. package/dist/fs/config/updateVersions.d.ts +0 -10
  75. package/dist/fs/config/updateVersions.js +0 -30
  76. package/dist/fs/copyFile.d.ts +0 -7
  77. package/dist/fs/copyFile.js +0 -39
  78. package/dist/fs/createLoadTranslationsFile.d.ts +0 -1
  79. package/dist/fs/createLoadTranslationsFile.js +0 -36
  80. package/dist/fs/determineFramework.d.ts +0 -5
  81. package/dist/fs/determineFramework.js +0 -46
  82. package/dist/fs/findFilepath.d.ts +0 -36
  83. package/dist/fs/findFilepath.js +0 -89
  84. package/dist/fs/getPackageResource.d.ts +0 -1
  85. package/dist/fs/getPackageResource.js +0 -6
  86. package/dist/fs/index.d.ts +0 -1
  87. package/dist/fs/index.js +0 -1
  88. package/dist/fs/loadJSON.d.ts +0 -6
  89. package/dist/fs/loadJSON.js +0 -17
  90. package/dist/fs/matchFiles.d.ts +0 -1
  91. package/dist/fs/matchFiles.js +0 -8
  92. package/dist/fs/saveJSON.d.ts +0 -1
  93. package/dist/fs/saveJSON.js +0 -7
  94. package/dist/fs/utils.d.ts +0 -1
  95. package/dist/fs/utils.js +0 -16
  96. package/dist/hooks/postProcess.d.ts +0 -4
  97. package/dist/hooks/postProcess.js +0 -110
  98. package/dist/index.d.ts +0 -4
  99. package/dist/index.js +0 -20
  100. package/dist/main.d.ts +0 -2
  101. package/dist/main.js +0 -9
  102. package/dist/next/config/parseNextConfig.d.ts +0 -10
  103. package/dist/next/config/parseNextConfig.js +0 -53
  104. package/dist/next/jsx/utils.d.ts +0 -7
  105. package/dist/next/jsx/utils.js +0 -42
  106. package/dist/next/parse/handleInitGT.d.ts +0 -7
  107. package/dist/next/parse/handleInitGT.js +0 -208
  108. package/dist/next/parse/wrapContent.d.ts +0 -11
  109. package/dist/next/parse/wrapContent.js +0 -163
  110. package/dist/react/config/createESBuildConfig.d.ts +0 -2
  111. package/dist/react/config/createESBuildConfig.js +0 -119
  112. package/dist/react/data-_gt/addGTIdentifierToSyntaxTree.d.ts +0 -8
  113. package/dist/react/data-_gt/addGTIdentifierToSyntaxTree.js +0 -111
  114. package/dist/react/jsx/evaluateJsx.d.ts +0 -17
  115. package/dist/react/jsx/evaluateJsx.js +0 -85
  116. package/dist/react/jsx/trimJsxStringChildren.d.ts +0 -7
  117. package/dist/react/jsx/trimJsxStringChildren.js +0 -95
  118. package/dist/react/jsx/utils/constants.d.ts +0 -10
  119. package/dist/react/jsx/utils/constants.js +0 -31
  120. package/dist/react/jsx/utils/parseAst.d.ts +0 -30
  121. package/dist/react/jsx/utils/parseAst.js +0 -277
  122. package/dist/react/jsx/utils/parseJsx.d.ts +0 -21
  123. package/dist/react/jsx/utils/parseJsx.js +0 -244
  124. package/dist/react/jsx/utils/parseStringFunction.d.ts +0 -16
  125. package/dist/react/jsx/utils/parseStringFunction.js +0 -411
  126. package/dist/react/jsx/utils/validateStringFunction.d.ts +0 -7
  127. package/dist/react/jsx/utils/validateStringFunction.js +0 -31
  128. package/dist/react/jsx/wrapJsx.d.ts +0 -51
  129. package/dist/react/jsx/wrapJsx.js +0 -387
  130. package/dist/react/parse/createDictionaryUpdates.d.ts +0 -3
  131. package/dist/react/parse/createDictionaryUpdates.js +0 -169
  132. package/dist/react/parse/createInlineUpdates.d.ts +0 -6
  133. package/dist/react/parse/createInlineUpdates.js +0 -122
  134. package/dist/react/parse/wrapContent.d.ts +0 -11
  135. package/dist/react/parse/wrapContent.js +0 -162
  136. package/dist/react/utils/flattenDictionary.d.ts +0 -20
  137. package/dist/react/utils/flattenDictionary.js +0 -75
  138. package/dist/react/utils/getEntryAndMetadata.d.ts +0 -5
  139. package/dist/react/utils/getEntryAndMetadata.js +0 -11
  140. package/dist/react/utils/getVariableName.d.ts +0 -25
  141. package/dist/react/utils/getVariableName.js +0 -37
  142. package/dist/setup/userInput.d.ts +0 -4
  143. package/dist/setup/userInput.js +0 -29
  144. package/dist/setup/wizard.d.ts +0 -2
  145. package/dist/setup/wizard.js +0 -127
  146. package/dist/translation/parse.d.ts +0 -15
  147. package/dist/translation/parse.js +0 -76
  148. package/dist/translation/stage.d.ts +0 -2
  149. package/dist/translation/stage.js +0 -44
  150. package/dist/translation/validate.d.ts +0 -2
  151. package/dist/translation/validate.js +0 -50
  152. package/dist/types/data/json.d.ts +0 -6
  153. package/dist/types/data/json.js +0 -1
  154. package/dist/types/data.d.ts +0 -30
  155. package/dist/types/data.js +0 -1
  156. package/dist/types/files.d.ts +0 -1
  157. package/dist/types/files.js +0 -1
  158. package/dist/types/index.d.ts +0 -173
  159. package/dist/types/index.js +0 -1
  160. package/dist/utils/addExplicitAnchorIds.d.ts +0 -24
  161. package/dist/utils/addExplicitAnchorIds.js +0 -260
  162. package/dist/utils/constants.d.ts +0 -2
  163. package/dist/utils/constants.js +0 -2
  164. package/dist/utils/credentials.d.ts +0 -12
  165. package/dist/utils/credentials.js +0 -119
  166. package/dist/utils/flattenJsonFiles.d.ts +0 -2
  167. package/dist/utils/flattenJsonFiles.js +0 -36
  168. package/dist/utils/gt.d.ts +0 -2
  169. package/dist/utils/gt.js +0 -2
  170. package/dist/utils/hash.d.ts +0 -6
  171. package/dist/utils/hash.js +0 -11
  172. package/dist/utils/headers.d.ts +0 -1
  173. package/dist/utils/headers.js +0 -14
  174. package/dist/utils/installPackage.d.ts +0 -3
  175. package/dist/utils/installPackage.js +0 -77
  176. package/dist/utils/localizeStaticImports.d.ts +0 -15
  177. package/dist/utils/localizeStaticImports.js +0 -341
  178. package/dist/utils/localizeStaticUrls.d.ts +0 -19
  179. package/dist/utils/localizeStaticUrls.js +0 -432
  180. package/dist/utils/packageInfo.d.ts +0 -3
  181. package/dist/utils/packageInfo.js +0 -17
  182. package/dist/utils/packageJson.d.ts +0 -6
  183. package/dist/utils/packageJson.js +0 -76
  184. package/dist/utils/packageManager.d.ts +0 -28
  185. package/dist/utils/packageManager.js +0 -269
  186. package/dist/utils/processAnchorIds.d.ts +0 -6
  187. package/dist/utils/processAnchorIds.js +0 -47
  188. package/dist/utils/sanitizeFileContent.d.ts +0 -6
  189. package/dist/utils/sanitizeFileContent.js +0 -29
  190. package/dist/utils/validateMdx.d.ts +0 -10
  191. package/dist/utils/validateMdx.js +0 -25
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gtx-cli",
3
- "version": "2.3.5",
3
+ "version": "2.3.6-alpha.2",
4
4
  "main": "dist/index.js",
5
5
  "bin": "dist/main.js",
6
6
  "files": [
@@ -8,19 +8,6 @@
8
8
  "CHANGELOG.md"
9
9
  ],
10
10
  "type": "module",
11
- "scripts": {
12
- "build": "tsc",
13
- "build:clean": "rm -rf dist; npm run build",
14
- "build:release": "npm run build:clean",
15
- "lint": "eslint \"src/**/*.{js,ts}\" \"./**/__tests__/**/*.{js,ts}\"",
16
- "lint:fix": "eslint \"src/**/*.{js,ts}\" \"./**/__tests__/**/*.{js,ts}\" --fix",
17
- "test": "vitest run --config=./vitest.config.ts",
18
- "test:watch": "vitest --config=./vitest.config.ts",
19
- "release": "npm run build:clean && npm publish",
20
- "release:alpha": "npm run build:clean && npm publish --tag alpha",
21
- "release:beta": "npm run build:clean && npm publish --tag beta",
22
- "release:latest": "npm run build:clean && npm publish --tag latest"
23
- },
24
11
  "exports": {
25
12
  ".": {
26
13
  "import": "./dist/index.js"
@@ -87,7 +74,6 @@
87
74
  "esbuild": "^0.25.4",
88
75
  "fast-glob": "^3.3.3",
89
76
  "form-data": "^4.0.4",
90
- "generaltranslation": "^7.6.2",
91
77
  "gt-remark": "^1.0.1",
92
78
  "json-pointer": "^0.6.2",
93
79
  "jsonpath-plus": "^10.3.0",
@@ -104,22 +90,41 @@
104
90
  "tsconfig-paths": "^4.2.0",
105
91
  "unified": "^11.0.5",
106
92
  "unist-util-visit": "^5.0.0",
107
- "yaml": "^2.8.0"
93
+ "yaml": "^2.8.0",
94
+ "generaltranslation": "7.6.4-alpha.1"
108
95
  },
109
96
  "devDependencies": {
97
+ "@babel/types": "^7.28.4",
110
98
  "@biomejs/biome": "^1.9.4",
111
99
  "@types/babel__generator": "^7.27.0",
112
100
  "@types/babel__traverse": "^7.20.6",
113
101
  "@types/figlet": "^1.7.0",
102
+ "@types/mdast": "^4.0.0",
103
+ "@types/micromatch": "^4.0.9",
114
104
  "@types/mock-require": "^2.0.3",
115
105
  "@types/node": "^22.5.1",
116
106
  "@types/react": "^18.3.4",
117
107
  "@types/resolve": "^1.20.2",
118
108
  "eslint": "^9.20.0",
119
109
  "esm": "^3.2.25",
120
- "mdast": "^3.0.0",
110
+ "mdast-util-mdx-jsx": "^3.2.0",
111
+ "mdast-util-mdxjs-esm": "^2.0.1",
121
112
  "prettier": "^3.4.2",
122
113
  "ts-node": "^10.9.2",
114
+ "tslib": "^2.8.1",
123
115
  "typescript": "^5.5.4"
116
+ },
117
+ "scripts": {
118
+ "build": "tsc",
119
+ "build:clean": "rm -rf dist; pnpm run build",
120
+ "build:release": "pnpm run build:clean",
121
+ "lint": "eslint \"src/**/*.{js,ts}\" \"./**/__tests__/**/*.{js,ts}\"",
122
+ "lint:fix": "eslint \"src/**/*.{js,ts}\" \"./**/__tests__/**/*.{js,ts}\" --fix",
123
+ "test": "vitest run --config=./vitest.config.ts",
124
+ "test:watch": "vitest --config=./vitest.config.ts",
125
+ "release": "pnpm run build:clean && pnpm publish",
126
+ "release:alpha": "pnpm run build:clean && pnpm publish --tag alpha",
127
+ "release:beta": "pnpm run build:clean && pnpm publish --tag beta",
128
+ "release:latest": "pnpm run build:clean && pnpm publish --tag latest"
124
129
  }
125
- }
130
+ }
@@ -1,23 +0,0 @@
1
- import { Settings } from '../types/index.js';
2
- export type CheckFileTranslationData = {
3
- [key: string]: {
4
- versionId: string;
5
- fileName: string;
6
- };
7
- };
8
- /**
9
- * Checks the status of translations for a given version ID
10
- * @param apiKey - The API key for the General Translation API
11
- * @param baseUrl - The base URL for the General Translation API
12
- * @param versionId - The version ID of the project
13
- * @param locales - The locales to wait for
14
- * @param startTime - The start time of the wait
15
- * @param timeoutDuration - The timeout duration for the wait in seconds
16
- * @returns True if all translations are deployed, false otherwise
17
- */
18
- export declare function checkFileTranslations(data: {
19
- [key: string]: {
20
- versionId: string;
21
- fileName: string;
22
- };
23
- }, locales: string[], timeoutDuration: number, resolveOutputPath: (sourcePath: string, locale: string) => string | null, options: Settings, forceRetranslation?: boolean): Promise<boolean>;
@@ -1,236 +0,0 @@
1
- import chalk from 'chalk';
2
- import { createOraSpinner, logError } from '../console/logging.js';
3
- import { getLocaleProperties } from 'generaltranslation';
4
- import { downloadFileBatch } from './downloadFileBatch.js';
5
- import { gt } from '../utils/gt.js';
6
- import { TEMPLATE_FILE_NAME } from '../cli/commands/stage.js';
7
- /**
8
- * Checks the status of translations for a given version ID
9
- * @param apiKey - The API key for the General Translation API
10
- * @param baseUrl - The base URL for the General Translation API
11
- * @param versionId - The version ID of the project
12
- * @param locales - The locales to wait for
13
- * @param startTime - The start time of the wait
14
- * @param timeoutDuration - The timeout duration for the wait in seconds
15
- * @returns True if all translations are deployed, false otherwise
16
- */
17
- export async function checkFileTranslations(data, locales, timeoutDuration, resolveOutputPath, options, forceRetranslation) {
18
- const startTime = Date.now();
19
- console.log();
20
- const spinner = await createOraSpinner();
21
- const spinnerMessage = forceRetranslation
22
- ? 'Waiting for retranslation...'
23
- : 'Waiting for translation...';
24
- spinner.start(spinnerMessage);
25
- // Initialize the query data
26
- const fileQueryData = prepareFileQueryData(data, locales);
27
- const downloadStatus = {
28
- downloaded: new Set(),
29
- failed: new Set(),
30
- skipped: new Set(),
31
- };
32
- // Do first check immediately, but skip if force retranslation is enabled
33
- if (!forceRetranslation) {
34
- const initialCheck = await checkTranslationDeployment(fileQueryData, downloadStatus, spinner, resolveOutputPath, options);
35
- if (initialCheck) {
36
- spinner.succeed(chalk.green('Files translated!'));
37
- return true;
38
- }
39
- }
40
- // Calculate time until next 5-second interval since startTime
41
- const msUntilNextInterval = Math.max(0, 5000 - ((Date.now() - startTime) % 5000));
42
- return new Promise((resolve) => {
43
- let intervalCheck;
44
- // Start the interval aligned with the original request time
45
- setTimeout(() => {
46
- intervalCheck = setInterval(async () => {
47
- const isDeployed = await checkTranslationDeployment(fileQueryData, downloadStatus, spinner, resolveOutputPath, options);
48
- const elapsed = Date.now() - startTime;
49
- if (isDeployed || elapsed >= timeoutDuration * 1000) {
50
- clearInterval(intervalCheck);
51
- if (isDeployed) {
52
- spinner.succeed(chalk.green('All files translated!'));
53
- resolve(true);
54
- }
55
- else {
56
- spinner.fail(chalk.red('Timed out waiting for translations'));
57
- resolve(false);
58
- }
59
- }
60
- }, 5000);
61
- }, msUntilNextInterval);
62
- });
63
- }
64
- /**
65
- * Prepares the file query data from input data and locales
66
- */
67
- function prepareFileQueryData(data, locales) {
68
- const fileQueryData = [];
69
- for (const file in data) {
70
- for (const locale of locales) {
71
- fileQueryData.push({
72
- versionId: data[file].versionId,
73
- fileName: data[file].fileName,
74
- locale,
75
- });
76
- }
77
- }
78
- return fileQueryData;
79
- }
80
- /**
81
- * Generates a formatted status text showing translation progress
82
- * @param downloadedFiles - Set of downloaded file+locale combinations
83
- * @param fileQueryData - Array of file query data objects
84
- * @returns Formatted status text
85
- */
86
- function generateStatusSuffixText(downloadStatus, fileQueryData) {
87
- // Simple progress indicator
88
- const progressText = chalk.green(`[${downloadStatus.downloaded.size + downloadStatus.failed.size}/${fileQueryData.length}]`) + ` translations completed`;
89
- // Get terminal height to adapt our output
90
- const terminalHeight = process.stdout.rows || 24; // Default to 24 if undefined
91
- // If terminal is very small, just show the basic progress
92
- if (terminalHeight < 6) {
93
- return `${progressText}`;
94
- }
95
- const newSuffixText = [`${progressText}`];
96
- // Organize data by filename
97
- const fileStatus = new Map();
98
- // Initialize with all files and locales from fileQueryData
99
- for (const item of fileQueryData) {
100
- if (!fileStatus.has(item.fileName)) {
101
- fileStatus.set(item.fileName, {
102
- completed: new Set(),
103
- pending: new Set([item.locale]),
104
- failed: new Set(),
105
- });
106
- }
107
- else {
108
- fileStatus.get(item.fileName)?.pending.add(item.locale);
109
- }
110
- }
111
- // Mark which ones are completed or failed
112
- for (const fileLocale of downloadStatus.downloaded) {
113
- const [fileName, locale] = fileLocale.split(':');
114
- const status = fileStatus.get(fileName);
115
- if (status) {
116
- status.pending.delete(locale);
117
- status.completed.add(locale);
118
- }
119
- }
120
- for (const fileLocale of downloadStatus.failed) {
121
- const [fileName, locale] = fileLocale.split(':');
122
- const status = fileStatus.get(fileName);
123
- if (status) {
124
- status.pending.delete(locale);
125
- status.failed.add(locale);
126
- }
127
- }
128
- // Calculate how many files we can show based on terminal height
129
- const filesArray = Array.from(fileStatus.entries());
130
- const maxFilesToShow = Math.min(filesArray.length, terminalHeight - 3 // Header + progress + buffer
131
- );
132
- // Display each file with its status on a single line
133
- for (let i = 0; i < maxFilesToShow; i++) {
134
- const [fileName, status] = filesArray[i];
135
- // Create condensed locale status
136
- const localeStatuses = [];
137
- // Add completed locales
138
- if (status.completed.size > 0) {
139
- const completedCodes = Array.from(status.completed)
140
- .map((locale) => getLocaleProperties(locale).code)
141
- .join(', ');
142
- localeStatuses.push(chalk.green(`${completedCodes}`));
143
- }
144
- // Add failed locales
145
- if (status.failed.size > 0) {
146
- const failedCodes = Array.from(status.failed)
147
- .map((locale) => getLocaleProperties(locale).code)
148
- .join(', ');
149
- localeStatuses.push(chalk.red(`${failedCodes}`));
150
- }
151
- // Add pending locales
152
- if (status.pending.size > 0) {
153
- const pendingCodes = Array.from(status.pending)
154
- .map((locale) => getLocaleProperties(locale).code)
155
- .join(', ');
156
- localeStatuses.push(chalk.yellow(`${pendingCodes}`));
157
- }
158
- // Format the line
159
- const prettyFileName = fileName === TEMPLATE_FILE_NAME ? '<React Elements>' : fileName;
160
- newSuffixText.push(`${chalk.bold(prettyFileName)} [${localeStatuses.join(', ')}]`);
161
- }
162
- // If we couldn't show all files, add an indicator
163
- if (filesArray.length > maxFilesToShow) {
164
- newSuffixText.push(`... and ${filesArray.length - maxFilesToShow} more files`);
165
- }
166
- return newSuffixText.join('\n');
167
- }
168
- /**
169
- * Checks translation status and downloads ready files
170
- */
171
- async function checkTranslationDeployment(fileQueryData, downloadStatus, spinner, resolveOutputPath, options) {
172
- try {
173
- // Only query for files that haven't been downloaded yet
174
- const currentQueryData = fileQueryData.filter((item) => !downloadStatus.downloaded.has(`${item.fileName}:${item.locale}`) &&
175
- !downloadStatus.failed.has(`${item.fileName}:${item.locale}`) &&
176
- !downloadStatus.skipped.has(`${item.fileName}:${item.locale}`));
177
- // If all files have been downloaded, we're done
178
- if (currentQueryData.length === 0) {
179
- return true;
180
- }
181
- // Check for translations
182
- const responseData = await gt.checkFileTranslations(currentQueryData);
183
- const translations = responseData.translations || [];
184
- // Filter for ready translations
185
- const readyTranslations = translations.filter((translation) => translation.isReady && translation.fileName);
186
- if (readyTranslations.length > 0) {
187
- // Prepare batch download data
188
- const batchFiles = readyTranslations
189
- .map((translation) => {
190
- const locale = gt.resolveAliasLocale(translation.locale);
191
- const fileName = translation.fileName;
192
- const translationId = translation.id;
193
- const outputPath = resolveOutputPath(fileName, locale);
194
- // Skip downloading GTJSON files that are not in the files configuration
195
- if (outputPath === null) {
196
- downloadStatus.skipped.add(`${fileName}:${locale}`);
197
- return null;
198
- }
199
- return {
200
- translationId,
201
- inputPath: fileName,
202
- outputPath,
203
- locale,
204
- fileLocale: `${fileName}:${locale}`,
205
- };
206
- })
207
- .filter((file) => file !== null);
208
- const batchResult = await downloadFileBatch(batchFiles, options);
209
- // Process results
210
- batchFiles.forEach((file) => {
211
- const { translationId, fileLocale } = file;
212
- if (batchResult.successful.includes(translationId)) {
213
- downloadStatus.downloaded.add(fileLocale);
214
- }
215
- else if (batchResult.failed.includes(translationId)) {
216
- downloadStatus.failed.add(fileLocale);
217
- }
218
- });
219
- }
220
- // Force a refresh of the spinner display
221
- const statusText = generateStatusSuffixText(downloadStatus, fileQueryData);
222
- // Clear and reapply the suffix to force a refresh
223
- spinner.text = statusText;
224
- // If all files have been downloaded, we're done
225
- if (downloadStatus.downloaded.size +
226
- downloadStatus.failed.size +
227
- downloadStatus.skipped.size ===
228
- fileQueryData.length) {
229
- return true;
230
- }
231
- }
232
- catch (error) {
233
- logError(chalk.red('Error checking translation status: ') + error);
234
- }
235
- return false;
236
- }
@@ -1,20 +0,0 @@
1
- import { Settings } from '../types/index.js';
2
- export type BatchedFiles = Array<{
3
- translationId: string;
4
- outputPath: string;
5
- inputPath: string;
6
- locale: string;
7
- fileLocale: string;
8
- }>;
9
- export type DownloadFileBatchResult = {
10
- successful: string[];
11
- failed: string[];
12
- };
13
- /**
14
- * Downloads multiple translation files in a single batch request
15
- * @param files - Array of files to download with their output paths
16
- * @param maxRetries - Maximum number of retry attempts
17
- * @param retryDelay - Delay between retries in milliseconds
18
- * @returns Object containing successful and failed file IDs
19
- */
20
- export declare function downloadFileBatch(files: BatchedFiles, options: Settings, maxRetries?: number, retryDelay?: number): Promise<DownloadFileBatchResult>;
@@ -1,113 +0,0 @@
1
- import * as fs from 'fs';
2
- import * as path from 'path';
3
- import { logError, logWarning } from '../console/logging.js';
4
- import { gt } from '../utils/gt.js';
5
- import { validateJsonSchema } from '../formats/json/utils.js';
6
- import { validateYamlSchema } from '../formats/yaml/utils.js';
7
- import { mergeJson } from '../formats/json/mergeJson.js';
8
- import mergeYaml from '../formats/yaml/mergeYaml.js';
9
- /**
10
- * Downloads multiple translation files in a single batch request
11
- * @param files - Array of files to download with their output paths
12
- * @param maxRetries - Maximum number of retry attempts
13
- * @param retryDelay - Delay between retries in milliseconds
14
- * @returns Object containing successful and failed file IDs
15
- */
16
- export async function downloadFileBatch(files, options, maxRetries = 3, retryDelay = 1000) {
17
- let retries = 0;
18
- const fileIds = files.map((file) => file.translationId);
19
- const result = { successful: [], failed: [] };
20
- // Create a map of translationId to outputPath for easier lookup
21
- const outputPathMap = new Map(files.map((file) => [file.translationId, file.outputPath]));
22
- const inputPathMap = new Map(files.map((file) => [file.translationId, file.inputPath]));
23
- const localeMap = new Map(files.map((file) => [
24
- file.translationId,
25
- gt.resolveAliasLocale(file.locale),
26
- ]));
27
- while (retries <= maxRetries) {
28
- try {
29
- // Download the files
30
- const responseData = await gt.downloadFileBatch(fileIds);
31
- const downloadedFiles = responseData.files || [];
32
- // Process each file in the response
33
- for (const file of downloadedFiles) {
34
- try {
35
- const translationId = file.id;
36
- const outputPath = outputPathMap.get(translationId);
37
- const inputPath = inputPathMap.get(translationId);
38
- const locale = localeMap.get(translationId);
39
- if (!outputPath || !inputPath) {
40
- logWarning(`No input/output path found for file: ${translationId}`);
41
- result.failed.push(translationId);
42
- continue;
43
- }
44
- // Ensure the directory exists
45
- const dir = path.dirname(outputPath);
46
- if (!fs.existsSync(dir)) {
47
- fs.mkdirSync(dir, { recursive: true });
48
- }
49
- let data = file.data;
50
- if (options.options?.jsonSchema && locale) {
51
- const jsonSchema = validateJsonSchema(options.options, inputPath);
52
- if (jsonSchema) {
53
- const originalContent = fs.readFileSync(inputPath, 'utf8');
54
- if (originalContent) {
55
- data = mergeJson(originalContent, inputPath, options.options, [
56
- {
57
- translatedContent: file.data,
58
- targetLocale: locale,
59
- },
60
- ], options.defaultLocale)[0];
61
- }
62
- }
63
- }
64
- if (options.options?.yamlSchema && locale) {
65
- const yamlSchema = validateYamlSchema(options.options, inputPath);
66
- if (yamlSchema) {
67
- const originalContent = fs.readFileSync(inputPath, 'utf8');
68
- if (originalContent) {
69
- data = mergeYaml(originalContent, inputPath, options.options, [
70
- {
71
- translatedContent: file.data,
72
- targetLocale: locale,
73
- },
74
- ])[0];
75
- }
76
- }
77
- }
78
- // Write the file to disk
79
- await fs.promises.writeFile(outputPath, data);
80
- result.successful.push(translationId);
81
- }
82
- catch (error) {
83
- logError(`Error saving file ${file.id}: ` + error);
84
- result.failed.push(file.id);
85
- }
86
- }
87
- // Add any files that weren't in the response to the failed list
88
- const downloadedIds = new Set(downloadedFiles.map((file) => file.id));
89
- for (const fileId of fileIds) {
90
- if (!downloadedIds.has(fileId) && !result.failed.includes(fileId)) {
91
- result.failed.push(fileId);
92
- }
93
- }
94
- return result;
95
- }
96
- catch (error) {
97
- // If we've retried too many times, log an error and return false
98
- if (retries >= maxRetries) {
99
- logError(`Error downloading files in batch after ${maxRetries + 1} attempts: ` +
100
- error);
101
- // Mark all files as failed
102
- result.failed = [...fileIds];
103
- return result;
104
- }
105
- // Increment retry counter and wait before next attempt
106
- retries++;
107
- await new Promise((resolve) => setTimeout(resolve, retryDelay));
108
- }
109
- }
110
- // Mark all files as failed if we get here
111
- result.failed = [...fileIds];
112
- return result;
113
- }
@@ -1,17 +0,0 @@
1
- import { Settings, TranslateFlags } from '../types/index.js';
2
- import { CompletedFileTranslationData, FileToTranslate } from 'generaltranslation/types';
3
- export type SendFilesResult = {
4
- data: Record<string, {
5
- fileName: string;
6
- versionId: string;
7
- }>;
8
- locales: string[];
9
- translations: CompletedFileTranslationData[];
10
- };
11
- /**
12
- * Sends multiple files for translation to the API
13
- * @param files - Array of file objects to translate
14
- * @param options - The options for the API call
15
- * @returns The translated content or version ID
16
- */
17
- export declare function sendFiles(files: FileToTranslate[], options: TranslateFlags, settings: Settings): Promise<SendFilesResult>;
@@ -1,115 +0,0 @@
1
- import chalk from 'chalk';
2
- import { createSpinner, logError, logMessage, logSuccess, } from '../console/logging.js';
3
- import { gt } from '../utils/gt.js';
4
- import { TEMPLATE_FILE_NAME } from '../cli/commands/stage.js';
5
- /**
6
- * Sends multiple files for translation to the API
7
- * @param files - Array of file objects to translate
8
- * @param options - The options for the API call
9
- * @returns The translated content or version ID
10
- */
11
- export async function sendFiles(files, options, settings) {
12
- // Keep track of the most recent spinner so we can stop it on error
13
- let currentSpinner = null;
14
- logMessage(chalk.cyan('Files to translate:') +
15
- '\n' +
16
- files
17
- .map((file) => {
18
- if (file.fileName === TEMPLATE_FILE_NAME) {
19
- return `- <React Elements>`;
20
- }
21
- return `- ${file.fileName}`;
22
- })
23
- .join('\n'));
24
- try {
25
- // Step 1: Upload files (get references)
26
- const uploadSpinner = createSpinner('dots');
27
- currentSpinner = uploadSpinner;
28
- uploadSpinner.start(`Uploading ${files.length} file${files.length !== 1 ? 's' : ''} to General Translation API...`);
29
- const sourceLocale = settings.defaultLocale;
30
- if (!sourceLocale) {
31
- uploadSpinner.stop(chalk.red('Missing default source locale'));
32
- throw new Error('sendFiles: settings.defaultLocale is required to upload source files');
33
- }
34
- // Convert FileToTranslate[] -> { source: FileUpload }[]
35
- const uploads = files.map(({ content, fileName, fileFormat, dataFormat }) => ({
36
- source: {
37
- content,
38
- fileName,
39
- fileFormat,
40
- dataFormat,
41
- locale: sourceLocale,
42
- },
43
- }));
44
- const upload = await gt.uploadSourceFiles(uploads, {
45
- sourceLocale,
46
- modelProvider: settings.modelProvider,
47
- });
48
- uploadSpinner.stop(chalk.green('Files uploaded successfully'));
49
- // Check if setup is needed
50
- const setupDecision = await Promise.resolve(gt.shouldSetupProject?.())
51
- .then((v) => v)
52
- .catch(() => ({ shouldSetupProject: false }));
53
- const shouldSetupProject = Boolean(setupDecision?.shouldSetupProject);
54
- // Step 2: Setup if needed and poll until complete
55
- if (shouldSetupProject) {
56
- // Calculate timeout once for setup fetching
57
- // Accept number or numeric string, default to 600s
58
- const timeoutVal = options?.timeout !== undefined ? Number(options.timeout) : 600;
59
- const setupTimeoutMs = (Number.isFinite(timeoutVal) ? timeoutVal : 600) * 1000;
60
- const { setupJobId } = await gt.setupProject(upload.uploadedFiles);
61
- const setupSpinner = createSpinner('dots');
62
- currentSpinner = setupSpinner;
63
- setupSpinner.start('Setting up project...');
64
- const start = Date.now();
65
- const pollInterval = 2000;
66
- let setupCompleted = false;
67
- let setupFailedMessage = null;
68
- while (true) {
69
- const status = await gt.checkSetupStatus(setupJobId);
70
- if (status.status === 'completed') {
71
- setupCompleted = true;
72
- break;
73
- }
74
- if (status.status === 'failed') {
75
- setupFailedMessage = status.error?.message || 'Unknown error';
76
- break;
77
- }
78
- if (Date.now() - start > setupTimeoutMs) {
79
- setupFailedMessage = 'Timed out while waiting for setup generation';
80
- break;
81
- }
82
- await new Promise((r) => setTimeout(r, pollInterval));
83
- }
84
- if (setupCompleted) {
85
- setupSpinner.stop(chalk.green('Setup successfully completed'));
86
- }
87
- else {
88
- setupSpinner.stop(chalk.yellow(`Setup ${setupFailedMessage ? 'failed' : 'timed out'} — proceeding without setup${setupFailedMessage ? ` (${setupFailedMessage})` : ''}`));
89
- }
90
- }
91
- // Step 3: Enqueue translations by reference
92
- const enqueueSpinner = createSpinner('dots');
93
- currentSpinner = enqueueSpinner;
94
- enqueueSpinner.start('Enqueuing translations...');
95
- const enqueueResult = await gt.enqueueFiles(upload.uploadedFiles, {
96
- sourceLocale: settings.defaultLocale,
97
- targetLocales: settings.locales,
98
- publish: settings.publish,
99
- requireApproval: settings.stageTranslations,
100
- modelProvider: settings.modelProvider,
101
- force: options?.force,
102
- });
103
- const { data, message, locales, translations } = enqueueResult;
104
- enqueueSpinner.stop(chalk.green('Files for translation uploaded successfully'));
105
- logSuccess(message);
106
- return { data, locales, translations };
107
- }
108
- catch (error) {
109
- if (currentSpinner) {
110
- currentSpinner.stop(chalk.red('Failed to send files for translation'));
111
- }
112
- logError('Failed to send files for translation');
113
- throw error;
114
- }
115
- }
@@ -1,27 +0,0 @@
1
- import { Settings } from '../types/index.js';
2
- import { DataFormat, FileFormat } from '../types/data.js';
3
- export type FileUpload = {
4
- content: string;
5
- fileName: string;
6
- fileFormat: FileFormat;
7
- dataFormat?: DataFormat;
8
- locale: string;
9
- };
10
- export type UploadData = {
11
- data: {
12
- source: FileUpload;
13
- translations: FileUpload[];
14
- }[];
15
- sourceLocale: string;
16
- modelProvider?: string;
17
- };
18
- /**
19
- * Uploads multiple files to the API
20
- * @param files - Array of file objects to upload
21
- * @param options - The options for the API call
22
- * @returns The uploaded content or version ID
23
- */
24
- export declare function uploadFiles(files: {
25
- source: FileUpload;
26
- translations: FileUpload[];
27
- }[], options: Settings): Promise<void>;
@@ -1,40 +0,0 @@
1
- import chalk from 'chalk';
2
- import { createSpinner, exit, logMessage } from '../console/logging.js';
3
- import { gt } from '../utils/gt.js';
4
- /**
5
- * Uploads multiple files to the API
6
- * @param files - Array of file objects to upload
7
- * @param options - The options for the API call
8
- * @returns The uploaded content or version ID
9
- */
10
- export async function uploadFiles(files, options) {
11
- logMessage(chalk.cyan('Files to upload:') +
12
- '\n' +
13
- files
14
- .map((file) => ` - ${chalk.bold(file.source.fileName)} -> ${file.translations
15
- .map((t) => t.locale)
16
- .join(', ')}`)
17
- .join('\n'));
18
- const spinner = createSpinner('dots');
19
- spinner.start(`Uploading ${files.length} file${files.length !== 1 ? 's' : ''} to General Translation...`);
20
- try {
21
- // Upload sources
22
- await gt.uploadSourceFiles(files, {
23
- ...options,
24
- sourceLocale: options.defaultLocale,
25
- });
26
- // Upload translations (if any exist)
27
- const withTranslations = files.filter((f) => f.translations.length > 0);
28
- if (withTranslations.length > 0) {
29
- await gt.uploadTranslations(withTranslations, {
30
- ...options,
31
- sourceLocale: options.defaultLocale, // optional, safe to include
32
- });
33
- }
34
- spinner.stop(chalk.green('Files uploaded successfully'));
35
- }
36
- catch {
37
- spinner.stop(chalk.red('An unexpected error occurred while uploading files'));
38
- exit(1);
39
- }
40
- }