gtx-cli 2.5.7 → 2.5.8
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 +6 -0
- package/dist/api/downloadFileBatch.js +5 -5
- package/dist/api/saveLocalEdits.js +4 -3
- package/dist/api/uploadFiles.d.ts +1 -1
- package/dist/api/uploadFiles.js +5 -4
- package/dist/cli/base.js +17 -16
- package/dist/cli/commands/stage.js +8 -7
- package/dist/cli/commands/translate.js +3 -5
- package/dist/cli/flags.js +2 -3
- package/dist/cli/react.js +16 -15
- package/dist/config/generateSettings.js +2 -2
- package/dist/config/validateSettings.d.ts +1 -1
- package/dist/config/validateSettings.js +4 -4
- package/dist/console/logger.d.ts +27 -0
- package/dist/console/logger.js +255 -0
- package/dist/console/logging.d.ts +1 -11
- package/dist/console/logging.js +24 -55
- package/dist/formats/files/save.js +2 -2
- package/dist/formats/files/translate.js +8 -8
- package/dist/formats/files/upload.js +7 -6
- package/dist/formats/gt/save.js +4 -3
- package/dist/formats/json/flattenJson.js +3 -3
- package/dist/formats/json/mergeJson.js +19 -18
- package/dist/formats/json/parseJson.js +14 -13
- package/dist/formats/json/utils.js +16 -15
- package/dist/formats/yaml/mergeYaml.js +6 -5
- package/dist/formats/yaml/parseYaml.js +4 -3
- package/dist/formats/yaml/utils.js +4 -3
- package/dist/fs/clearLocaleDirs.js +6 -6
- package/dist/fs/config/downloadedVersions.js +3 -3
- package/dist/fs/config/parseFilesConfig.js +2 -2
- package/dist/fs/config/setupConfig.js +2 -2
- package/dist/fs/config/updateConfig.js +2 -2
- package/dist/fs/config/updateVersions.js +3 -3
- package/dist/fs/copyFile.js +2 -2
- package/dist/fs/createLoadTranslationsFile.js +3 -3
- package/dist/fs/determineFramework.js +3 -3
- package/dist/fs/findFilepath.js +5 -4
- package/dist/hooks/postProcess.js +9 -9
- package/dist/next/parse/handleInitGT.js +2 -2
- package/dist/react/parse/addVitePlugin/index.js +4 -3
- package/dist/react/parse/addVitePlugin/installCompiler.js +2 -2
- package/dist/react/parse/addVitePlugin/updateViteConfig.js +9 -12
- package/dist/react/parse/createDictionaryUpdates.js +4 -3
- package/dist/react/parse/createInlineUpdates.js +2 -2
- package/dist/setup/wizard.js +17 -16
- package/dist/translation/parse.js +4 -3
- package/dist/translation/stage.js +4 -4
- package/dist/translation/validate.js +6 -6
- package/dist/utils/addExplicitAnchorIds.js +2 -2
- package/dist/utils/credentials.js +4 -3
- package/dist/utils/installPackage.js +11 -11
- package/dist/utils/packageJson.js +4 -3
- package/dist/workflow/BranchStep.js +5 -4
- package/dist/workflow/DownloadStep.js +5 -5
- package/dist/workflow/EnqueueStep.js +2 -2
- package/dist/workflow/PollJobsStep.js +3 -3
- package/dist/workflow/SetupStep.js +2 -2
- package/dist/workflow/UploadStep.js +3 -3
- package/dist/workflow/UserEditDiffsStep.js +2 -2
- package/dist/workflow/download.js +4 -3
- package/dist/workflow/stage.js +5 -4
- package/package.json +2 -2
- package/dist/utils/SpinnerManager.d.ts +0 -30
- package/dist/utils/SpinnerManager.js +0 -73
|
@@ -6,7 +6,7 @@ import traverseModule from '@babel/traverse';
|
|
|
6
6
|
const traverse = traverseModule.default || traverseModule;
|
|
7
7
|
const generate = generateModule.default || generateModule;
|
|
8
8
|
import * as t from '@babel/types';
|
|
9
|
-
import {
|
|
9
|
+
import { logger } from '../../console/logger.js';
|
|
10
10
|
import { needsCJS } from '../../utils/parse/needsCJS.js';
|
|
11
11
|
export async function handleInitGT(filepath, errors, warnings, filesUpdated, packageJson, tsconfigJson) {
|
|
12
12
|
const code = await fs.promises.readFile(filepath, 'utf8');
|
|
@@ -151,7 +151,7 @@ export async function handleInitGT(filepath, errors, warnings, filesUpdated, pac
|
|
|
151
151
|
filesUpdated.push(filepath);
|
|
152
152
|
}
|
|
153
153
|
catch (error) {
|
|
154
|
-
|
|
154
|
+
logger.error(`Error parsing file ${filepath}: ${error}`);
|
|
155
155
|
errors.push(`Failed to parse ${filepath}: ${error}`);
|
|
156
156
|
}
|
|
157
157
|
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import findFilepath from '../../../fs/findFilepath.js';
|
|
2
|
-
import {
|
|
2
|
+
import { logger } from '../../../console/logger.js';
|
|
3
3
|
import { installCompiler } from './installCompiler.js';
|
|
4
4
|
import { updateViteConfig } from './updateViteConfig.js';
|
|
5
|
+
import { exitSync } from '../../../console/logging.js';
|
|
5
6
|
const VITE_CONFIG_PATH_BASE = './vite.config.';
|
|
6
7
|
/**
|
|
7
8
|
* Adds the gt compiler plugin to the vite config file
|
|
@@ -17,13 +18,13 @@ export async function addVitePlugin({ errors, warnings, filesUpdated, packageJso
|
|
|
17
18
|
VITE_CONFIG_PATH_BASE + 'cts',
|
|
18
19
|
]);
|
|
19
20
|
if (!viteConfigPath) {
|
|
20
|
-
|
|
21
|
+
logger.error(`No ${VITE_CONFIG_PATH_BASE}[js|ts|mjs|mts|cjs|cts] file found. Please add the @generaltranslation/compiler plugin to your vite configuration file:
|
|
21
22
|
import { vite as gtCompiler } from '@generaltranslation/compiler';
|
|
22
23
|
export default defineConfig({
|
|
23
24
|
plugins: [gtCompiler()],
|
|
24
25
|
});
|
|
25
26
|
`);
|
|
26
|
-
|
|
27
|
+
exitSync(1);
|
|
27
28
|
}
|
|
28
29
|
// Install @generaltranslation/compiler if not installed
|
|
29
30
|
await installCompiler({ packageJson });
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { logger } from '../../../console/logger.js';
|
|
2
2
|
import { installPackage } from '../../../utils/installPackage.js';
|
|
3
3
|
import { isPackageInstalled } from '../../../utils/packageJson.js';
|
|
4
4
|
import { getPackageManager } from '../../../utils/packageManager.js';
|
|
@@ -12,7 +12,7 @@ export async function installCompiler({ packageJson, }) {
|
|
|
12
12
|
return;
|
|
13
13
|
}
|
|
14
14
|
// Animation
|
|
15
|
-
const spinner = createSpinner();
|
|
15
|
+
const spinner = logger.createSpinner();
|
|
16
16
|
spinner.start(`Installing @generaltranslation/compiler...`);
|
|
17
17
|
// Install
|
|
18
18
|
const packageManager = await getPackageManager();
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { logError } from '../../../console/logging.js';
|
|
1
|
+
import { logger } from '../../../console/logger.js';
|
|
3
2
|
import fs from 'node:fs';
|
|
4
3
|
import chalk from 'chalk';
|
|
5
4
|
import generateModule from '@babel/generator';
|
|
@@ -9,6 +8,7 @@ import { addCompilerImport } from './utils/addCompilerImport.js';
|
|
|
9
8
|
import { checkCompilerImport } from './utils/checkCompilerImport.js';
|
|
10
9
|
import { checkPluginInvocation } from './utils/checkPluginInvocation.js';
|
|
11
10
|
import { addPluginInvocation } from './utils/addPluginInvocation.js';
|
|
11
|
+
import { exitSync } from '../../../console/logging.js';
|
|
12
12
|
// Handle CommonJS/ESM interop
|
|
13
13
|
const generate = generateModule.default || generateModule;
|
|
14
14
|
/**
|
|
@@ -18,7 +18,7 @@ const generate = generateModule.default || generateModule;
|
|
|
18
18
|
*/
|
|
19
19
|
export async function updateViteConfig({ errors, warnings, filesUpdated, viteConfigPath, packageJson, tsconfigJson, }) {
|
|
20
20
|
// Animation
|
|
21
|
-
const spinner = createSpinner();
|
|
21
|
+
const spinner = logger.createSpinner();
|
|
22
22
|
spinner.start(`Adding gt compiler plugin to ${viteConfigPath}...`);
|
|
23
23
|
// Read the file
|
|
24
24
|
let code;
|
|
@@ -26,9 +26,8 @@ export async function updateViteConfig({ errors, warnings, filesUpdated, viteCon
|
|
|
26
26
|
code = await fs.promises.readFile(viteConfigPath, 'utf8');
|
|
27
27
|
}
|
|
28
28
|
catch (error) {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
return;
|
|
29
|
+
logger.error(`Error: Failed to read ${viteConfigPath}: ${error}`);
|
|
30
|
+
exitSync(1);
|
|
32
31
|
}
|
|
33
32
|
// Update the ast
|
|
34
33
|
let updatedCode, success;
|
|
@@ -43,9 +42,8 @@ export async function updateViteConfig({ errors, warnings, filesUpdated, viteCon
|
|
|
43
42
|
}));
|
|
44
43
|
}
|
|
45
44
|
catch (error) {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
return;
|
|
45
|
+
logger.error(`Error: Failed to update ${viteConfigPath}: ${error}`);
|
|
46
|
+
exitSync(1);
|
|
49
47
|
}
|
|
50
48
|
// Write the file
|
|
51
49
|
try {
|
|
@@ -53,9 +51,8 @@ export async function updateViteConfig({ errors, warnings, filesUpdated, viteCon
|
|
|
53
51
|
filesUpdated.push(viteConfigPath);
|
|
54
52
|
}
|
|
55
53
|
catch (error) {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
return;
|
|
54
|
+
logger.error(`Error: Failed to write ${viteConfigPath}: ${error}`);
|
|
55
|
+
exitSync(1);
|
|
59
56
|
}
|
|
60
57
|
// Animation
|
|
61
58
|
spinner.stop(success
|
|
@@ -6,10 +6,11 @@ import flattenDictionary from '../utils/flattenDictionary.js';
|
|
|
6
6
|
import loadJSON from '../../fs/loadJSON.js';
|
|
7
7
|
import { hashSource } from 'generaltranslation/id';
|
|
8
8
|
import getEntryAndMetadata from '../utils/getEntryAndMetadata.js';
|
|
9
|
-
import {
|
|
9
|
+
import { logger } from '../../console/logger.js';
|
|
10
10
|
import { randomUUID } from 'node:crypto';
|
|
11
11
|
import { isValidIcu } from '../jsx/evaluateJsx.js';
|
|
12
12
|
import { warnInvalidIcuSync } from '../../console/index.js';
|
|
13
|
+
import { exitSync } from '../../console/logging.js';
|
|
13
14
|
export async function createDictionaryUpdates(dictionaryPath, warnings, esbuildConfig) {
|
|
14
15
|
let dictionary;
|
|
15
16
|
// ---- HANDLE JSON STRING DICTIONARY ----- //
|
|
@@ -32,8 +33,8 @@ export async function createDictionaryUpdates(dictionaryPath, warnings, esbuildC
|
|
|
32
33
|
dictionaryModule = await import(tempFilePath);
|
|
33
34
|
}
|
|
34
35
|
catch (error) {
|
|
35
|
-
|
|
36
|
-
|
|
36
|
+
logger.error(`Failed to load the bundled dictionary code: ${error}`);
|
|
37
|
+
exitSync(1);
|
|
37
38
|
}
|
|
38
39
|
finally {
|
|
39
40
|
// Clean up the temporary file
|
|
@@ -3,7 +3,7 @@ import { parse } from '@babel/parser';
|
|
|
3
3
|
import { hashSource } from 'generaltranslation/id';
|
|
4
4
|
import { parseTranslationComponent } from '../jsx/utils/jsxParsing/parseJsx.js';
|
|
5
5
|
import { parseStrings } from '../jsx/utils/parseStringFunction.js';
|
|
6
|
-
import {
|
|
6
|
+
import { logger } from '../../console/logger.js';
|
|
7
7
|
import { matchFiles } from '../../fs/matchFiles.js';
|
|
8
8
|
import { DEFAULT_SRC_PATTERNS } from '../../config/generateSettings.js';
|
|
9
9
|
import { getPathsAndAliases } from '../jsx/utils/getPathsAndAliases.js';
|
|
@@ -23,7 +23,7 @@ export async function createInlineUpdates(pkg, validate, filePatterns, parsingOp
|
|
|
23
23
|
});
|
|
24
24
|
}
|
|
25
25
|
catch (error) {
|
|
26
|
-
|
|
26
|
+
logger.error(`Error parsing file ${file}: ${error}`);
|
|
27
27
|
continue;
|
|
28
28
|
}
|
|
29
29
|
// First pass: collect imports and process translation functions
|
package/dist/setup/wizard.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { detectFormatter } from '../hooks/postProcess.js';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { promptSelect } from '../console/logging.js';
|
|
3
|
+
import { logger } from '../console/logger.js';
|
|
4
4
|
import chalk from 'chalk';
|
|
5
5
|
import { promptConfirm } from '../console/logging.js';
|
|
6
6
|
import findFilepath from '../fs/findFilepath.js';
|
|
@@ -13,6 +13,7 @@ import { installPackage } from '../utils/installPackage.js';
|
|
|
13
13
|
import { createOrUpdateConfig } from '../fs/config/setupConfig.js';
|
|
14
14
|
import { loadConfig } from '../fs/config/loadConfig.js';
|
|
15
15
|
import { addVitePlugin } from '../react/parse/addVitePlugin/index.js';
|
|
16
|
+
import { exitSync } from '../console/logging.js';
|
|
16
17
|
export async function handleSetupReactCommand(options) {
|
|
17
18
|
// Ask user for confirmation using inquirer
|
|
18
19
|
const answer = await promptConfirm({
|
|
@@ -24,8 +25,8 @@ Make sure you have committed or stashed any changes. Do you want to continue?`),
|
|
|
24
25
|
cancelMessage: 'Operation cancelled. You can re-run this wizard with: npx gtx-cli setup',
|
|
25
26
|
});
|
|
26
27
|
if (!answer) {
|
|
27
|
-
|
|
28
|
-
|
|
28
|
+
logger.info('Operation cancelled. You can re-run this wizard with: npx gtx-cli setup');
|
|
29
|
+
exitSync(0);
|
|
29
30
|
}
|
|
30
31
|
const frameworkType = await promptSelect({
|
|
31
32
|
message: 'What framework are you using?',
|
|
@@ -41,9 +42,9 @@ Make sure you have committed or stashed any changes. Do you want to continue?`),
|
|
|
41
42
|
defaultValue: 'next-app',
|
|
42
43
|
});
|
|
43
44
|
if (frameworkType === 'other') {
|
|
44
|
-
|
|
45
|
+
logger.error(`Sorry, other React frameworks are not currently supported.
|
|
45
46
|
Please let us know what you would like to see supported at https://github.com/generaltranslation/gt/issues`);
|
|
46
|
-
|
|
47
|
+
exitSync(0);
|
|
47
48
|
}
|
|
48
49
|
// ----- Create a starter gt.config.json file -----
|
|
49
50
|
await createOrUpdateConfig(options.config || 'gt.config.json', {
|
|
@@ -51,14 +52,14 @@ Please let us know what you would like to see supported at https://github.com/ge
|
|
|
51
52
|
});
|
|
52
53
|
const packageJson = await getPackageJson();
|
|
53
54
|
if (!packageJson) {
|
|
54
|
-
|
|
55
|
-
|
|
55
|
+
logger.error(chalk.red('No package.json found in the current directory. Please run this command from the root of your project.'));
|
|
56
|
+
exitSync(1);
|
|
56
57
|
}
|
|
57
58
|
// Check if gt-next or gt-react is installed
|
|
58
59
|
if (frameworkType === 'next-app' &&
|
|
59
60
|
!isPackageInstalled('gt-next', packageJson)) {
|
|
60
61
|
const packageManager = await getPackageManager();
|
|
61
|
-
const spinner = createSpinner('timer');
|
|
62
|
+
const spinner = logger.createSpinner('timer');
|
|
62
63
|
spinner.start(`Installing gt-next with ${packageManager.name}...`);
|
|
63
64
|
await installPackage('gt-next', packageManager);
|
|
64
65
|
spinner.stop(chalk.green('Automatically installed gt-next.'));
|
|
@@ -66,7 +67,7 @@ Please let us know what you would like to see supported at https://github.com/ge
|
|
|
66
67
|
else if (['next-pages', 'react', 'redwood', 'vite', 'gatsby'].includes(frameworkType) &&
|
|
67
68
|
!isPackageInstalled('gt-react', packageJson)) {
|
|
68
69
|
const packageManager = await getPackageManager();
|
|
69
|
-
const spinner = createSpinner('timer');
|
|
70
|
+
const spinner = logger.createSpinner('timer');
|
|
70
71
|
spinner.start(`Installing gt-react with ${packageManager.name}...`);
|
|
71
72
|
await installPackage('gt-react', packageManager);
|
|
72
73
|
spinner.stop(chalk.green('Automatically installed gt-react.'));
|
|
@@ -86,8 +87,8 @@ Please let us know what you would like to see supported at https://github.com/ge
|
|
|
86
87
|
'./next.config.mts',
|
|
87
88
|
]);
|
|
88
89
|
if (!nextConfigPath) {
|
|
89
|
-
|
|
90
|
-
|
|
90
|
+
logger.error('No next.config.[js|ts|mjs|mts] file found.');
|
|
91
|
+
exitSync(1);
|
|
91
92
|
}
|
|
92
93
|
const mergeOptions = {
|
|
93
94
|
...options,
|
|
@@ -96,7 +97,7 @@ Please let us know what you would like to see supported at https://github.com/ge
|
|
|
96
97
|
skipTs: true,
|
|
97
98
|
addGTProvider: true,
|
|
98
99
|
};
|
|
99
|
-
const spinner = createSpinner();
|
|
100
|
+
const spinner = logger.createSpinner();
|
|
100
101
|
spinner.start('Wrapping JSX content with <T> tags...');
|
|
101
102
|
// Wrap all JSX elements in the src directory with a <T> tag, with unique ids
|
|
102
103
|
const { filesUpdated: filesUpdatedNext } = await wrapContentNext(mergeOptions, 'gt-next', errors, warnings);
|
|
@@ -104,7 +105,7 @@ Please let us know what you would like to see supported at https://github.com/ge
|
|
|
104
105
|
spinner.stop(chalk.green(`Success! Updated ${chalk.bold.cyan(filesUpdated.length)} files:\n`) + filesUpdated.map((file) => `${chalk.green('-')} ${file}`).join('\n'));
|
|
105
106
|
// Add the withGTConfig() function to the next.config.js file
|
|
106
107
|
await handleInitGT(nextConfigPath, errors, warnings, filesUpdated, packageJson, tsconfigJson);
|
|
107
|
-
|
|
108
|
+
logger.step(chalk.green(`Added withGTConfig() to your ${nextConfigPath} file.`));
|
|
108
109
|
}
|
|
109
110
|
// Add gt compiler plugin
|
|
110
111
|
if (frameworkType === 'vite') {
|
|
@@ -117,10 +118,10 @@ Please let us know what you would like to see supported at https://github.com/ge
|
|
|
117
118
|
});
|
|
118
119
|
}
|
|
119
120
|
if (errors.length > 0) {
|
|
120
|
-
|
|
121
|
+
logger.error(chalk.red('Failed to write files:\n') + errors.join('\n'));
|
|
121
122
|
}
|
|
122
123
|
if (warnings.length > 0) {
|
|
123
|
-
|
|
124
|
+
logger.warn(chalk.yellow('Warnings encountered:') +
|
|
124
125
|
'\n' +
|
|
125
126
|
warnings.map((warning) => `${chalk.yellow('-')} ${warning}`).join('\n'));
|
|
126
127
|
}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
|
-
import {
|
|
2
|
+
import { logger } from '../console/logger.js';
|
|
3
3
|
import loadJSON from '../fs/loadJSON.js';
|
|
4
4
|
import { createDictionaryUpdates } from '../react/parse/createDictionaryUpdates.js';
|
|
5
5
|
import { createInlineUpdates } from '../react/parse/createInlineUpdates.js';
|
|
6
6
|
import createESBuildConfig from '../react/config/createESBuildConfig.js';
|
|
7
7
|
import chalk from 'chalk';
|
|
8
|
+
import { exitSync } from '../console/logging.js';
|
|
8
9
|
/**
|
|
9
10
|
* Searches for gt-react or gt-next dictionary files and creates updates for them,
|
|
10
11
|
* as well as inline updates for <T> tags and useGT()/getGT() calls
|
|
@@ -33,8 +34,8 @@ export async function createUpdates(options, src, sourceDictionary, pkg, validat
|
|
|
33
34
|
if (options.jsconfig) {
|
|
34
35
|
const jsconfig = loadJSON(options.jsconfig);
|
|
35
36
|
if (!jsconfig) {
|
|
36
|
-
|
|
37
|
-
|
|
37
|
+
logger.error(`Failed to resolve jsconfig.json or tsconfig.json at provided filepath: "${options.jsconfig}"`);
|
|
38
|
+
exitSync(1);
|
|
38
39
|
}
|
|
39
40
|
esbuildConfig = createESBuildConfig(jsconfig);
|
|
40
41
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { logErrorAndExit } from '../console/logging.js';
|
|
2
2
|
import chalk from 'chalk';
|
|
3
3
|
import findFilepath from '../fs/findFilepath.js';
|
|
4
|
-
import {
|
|
4
|
+
import { logger } from '../console/logger.js';
|
|
5
5
|
import { createUpdates } from './parse.js';
|
|
6
6
|
export async function aggregateReactTranslations(options, settings, library) {
|
|
7
7
|
if (!options.dictionary) {
|
|
@@ -17,14 +17,14 @@ export async function aggregateReactTranslations(options, settings, library) {
|
|
|
17
17
|
// ---- CREATING UPDATES ---- //
|
|
18
18
|
const { updates, errors, warnings } = await createUpdates(options, settings.src, options.dictionary, library, false, settings.parsingOptions);
|
|
19
19
|
if (warnings.length > 0) {
|
|
20
|
-
|
|
20
|
+
logger.warn(chalk.yellow(`CLI tool encountered ${warnings.length} warnings while scanning for translatable content.\n` +
|
|
21
21
|
warnings
|
|
22
22
|
.map((warning) => chalk.yellow('• Warning: ') + chalk.white(warning))
|
|
23
23
|
.join('\n')));
|
|
24
24
|
}
|
|
25
25
|
if (errors.length > 0) {
|
|
26
26
|
if (options.ignoreErrors) {
|
|
27
|
-
|
|
27
|
+
logger.warn(chalk.yellow(`Warning: CLI tool encountered ${errors.length} syntax errors while scanning for translatable content. These components will not be translated.\n` +
|
|
28
28
|
errors
|
|
29
29
|
.map((error) => chalk.yellow('• ') + chalk.white(error) + '\n')
|
|
30
30
|
.join('')));
|
|
@@ -37,7 +37,7 @@ export async function aggregateReactTranslations(options, settings, library) {
|
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
39
|
if (updates.length == 0) {
|
|
40
|
-
|
|
40
|
+
logger.error(chalk.red(`No in-line content or dictionaries were found for ${chalk.green(library)}. Are you sure you're running this command in the right directory?`));
|
|
41
41
|
return updates;
|
|
42
42
|
}
|
|
43
43
|
return updates;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { logErrorAndExit
|
|
1
|
+
import { logErrorAndExit } from '../console/logging.js';
|
|
2
2
|
import chalk from 'chalk';
|
|
3
3
|
import findFilepath from '../fs/findFilepath.js';
|
|
4
|
-
import {
|
|
4
|
+
import { logger } from '../console/logger.js';
|
|
5
5
|
import { createUpdates } from './parse.js';
|
|
6
6
|
import { createInlineUpdates } from '../react/parse/createInlineUpdates.js';
|
|
7
7
|
export async function validateProject(settings, pkg, files) {
|
|
@@ -14,7 +14,7 @@ export async function validateProject(settings, pkg, files) {
|
|
|
14
14
|
.map((error) => chalk.red('• ') + chalk.white(error) + '\n')
|
|
15
15
|
.join('')));
|
|
16
16
|
}
|
|
17
|
-
|
|
17
|
+
logger.success(chalk.green(`Success! Found ${updates.length} translatable entries.`));
|
|
18
18
|
return;
|
|
19
19
|
}
|
|
20
20
|
if (!settings.dictionary) {
|
|
@@ -29,7 +29,7 @@ export async function validateProject(settings, pkg, files) {
|
|
|
29
29
|
}
|
|
30
30
|
const { updates, errors, warnings } = await createUpdates(settings, settings.src, settings.dictionary, pkg, true, settings.parsingOptions);
|
|
31
31
|
if (warnings.length > 0) {
|
|
32
|
-
|
|
32
|
+
logger.warn(chalk.yellow(`CLI tool encountered ${warnings.length} warnings while scanning for translatable content.`) +
|
|
33
33
|
'\n' +
|
|
34
34
|
warnings
|
|
35
35
|
.map((warning) => chalk.yellow('• ') + chalk.white(warning))
|
|
@@ -42,9 +42,9 @@ export async function validateProject(settings, pkg, files) {
|
|
|
42
42
|
.join('')));
|
|
43
43
|
}
|
|
44
44
|
if (updates.length === 0) {
|
|
45
|
-
|
|
45
|
+
logger.error(chalk.red(`No in-line content or dictionaries were found for ${chalk.green(pkg)}. Are you sure you're running this command in the right directory?`));
|
|
46
46
|
}
|
|
47
47
|
else {
|
|
48
|
-
|
|
48
|
+
logger.success(chalk.green(`Success! Found ${updates.length} translatable entries for ${chalk.green(pkg)}.`));
|
|
49
49
|
}
|
|
50
50
|
}
|
|
@@ -4,7 +4,7 @@ import remarkMdx from 'remark-mdx';
|
|
|
4
4
|
import remarkFrontmatter from 'remark-frontmatter';
|
|
5
5
|
import remarkStringify from 'remark-stringify';
|
|
6
6
|
import { visit } from 'unist-util-visit';
|
|
7
|
-
import {
|
|
7
|
+
import { logger } from '../console/logger.js';
|
|
8
8
|
import escapeHtmlInTextNodes from 'gt-remark';
|
|
9
9
|
/**
|
|
10
10
|
* Generates a slug from heading text
|
|
@@ -90,7 +90,7 @@ export function addExplicitAnchorIds(translatedContent, sourceHeadingMap, settin
|
|
|
90
90
|
const translatedFile = translatedPath
|
|
91
91
|
? `translated file: ${translatedPath}`
|
|
92
92
|
: 'translated file';
|
|
93
|
-
|
|
93
|
+
logger.warn(`Header count mismatch detected! ${sourceFile} has ${sourceHeadingMap.length} headers but ${translatedFile} has ${translatedHeadings.length} headers. ` +
|
|
94
94
|
`This likely means your source file was edited after translation was requested, causing a mismatch between ` +
|
|
95
95
|
`the number of headers in your source file vs the translated file. Please re-translate this file to resolve the issue.`);
|
|
96
96
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { logErrorAndExit } from '../console/logging.js';
|
|
2
|
+
import { logger } from '../console/logger.js';
|
|
2
3
|
import path from 'node:path';
|
|
3
4
|
import fs from 'node:fs';
|
|
4
5
|
import chalk from 'chalk';
|
|
@@ -10,8 +11,8 @@ export async function retrieveCredentials(settings, keyType) {
|
|
|
10
11
|
await import('open').then((open) => open.default(urlToOpen, {
|
|
11
12
|
wait: false,
|
|
12
13
|
}));
|
|
13
|
-
|
|
14
|
-
const spinner = createSpinner('dots');
|
|
14
|
+
logger.message(`${chalk.dim(`If the browser window didn't open automatically, please open the following link:`)}\n\n${chalk.cyan(urlToOpen)}`);
|
|
15
|
+
const spinner = logger.createSpinner('dots');
|
|
15
16
|
spinner.start('Waiting for response from dashboard...');
|
|
16
17
|
const credentials = await new Promise(async (resolve, reject) => {
|
|
17
18
|
const interval = setInterval(async () => {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
import { spawn } from 'child_process';
|
|
3
|
-
import {
|
|
3
|
+
import { logger } from '../console/logger.js';
|
|
4
4
|
export async function installPackage(packageName, packageManager, asDevDependency, cwd = process.cwd()) {
|
|
5
5
|
return new Promise((resolve, reject) => {
|
|
6
6
|
const command = packageManager.name;
|
|
@@ -19,8 +19,8 @@ export async function installPackage(packageName, packageManager, asDevDependenc
|
|
|
19
19
|
});
|
|
20
20
|
}
|
|
21
21
|
childProcess.on('error', (error) => {
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
logger.error(chalk.red(`Installation error: ${error.message}`));
|
|
23
|
+
logger.info(`Please manually install ${packageName} with: ${packageManager.name} ${packageManager.installCommand} ${packageName}`);
|
|
24
24
|
reject(error);
|
|
25
25
|
});
|
|
26
26
|
childProcess.on('close', (code) => {
|
|
@@ -28,11 +28,11 @@ export async function installPackage(packageName, packageManager, asDevDependenc
|
|
|
28
28
|
resolve();
|
|
29
29
|
}
|
|
30
30
|
else {
|
|
31
|
-
|
|
31
|
+
logger.error(chalk.red(`Installation failed with exit code ${code}`));
|
|
32
32
|
if (errorOutput) {
|
|
33
|
-
|
|
33
|
+
logger.error(chalk.red(`Error details: ${errorOutput}`));
|
|
34
34
|
}
|
|
35
|
-
|
|
35
|
+
logger.info(`Please manually install ${packageName} with: ${packageManager.name} ${packageManager.installCommand} ${packageName}`);
|
|
36
36
|
reject(new Error(`Process exited with code ${code}`));
|
|
37
37
|
}
|
|
38
38
|
});
|
|
@@ -56,8 +56,8 @@ export async function installPackageGlobal(packageName, version) {
|
|
|
56
56
|
});
|
|
57
57
|
}
|
|
58
58
|
childProcess.on('error', (error) => {
|
|
59
|
-
|
|
60
|
-
|
|
59
|
+
logger.error(chalk.red(`Installation error: ${error.message}`));
|
|
60
|
+
logger.info(`Please manually install ${packageName} with: npm install -g ${packageName}`);
|
|
61
61
|
reject(error);
|
|
62
62
|
});
|
|
63
63
|
childProcess.on('close', (code) => {
|
|
@@ -65,11 +65,11 @@ export async function installPackageGlobal(packageName, version) {
|
|
|
65
65
|
resolve();
|
|
66
66
|
}
|
|
67
67
|
else {
|
|
68
|
-
|
|
68
|
+
logger.error(chalk.red(`Installation failed with exit code ${code}`));
|
|
69
69
|
if (errorOutput) {
|
|
70
|
-
|
|
70
|
+
logger.error(chalk.red(`Error details: ${errorOutput}`));
|
|
71
71
|
}
|
|
72
|
-
|
|
72
|
+
logger.info(`Please manually install ${packageName} with: npm install -g ${packageName}`);
|
|
73
73
|
reject(new Error(`Process exited with code ${code}`));
|
|
74
74
|
}
|
|
75
75
|
});
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { logger } from '../console/logger.js';
|
|
2
2
|
import chalk from 'chalk';
|
|
3
3
|
import path from 'node:path';
|
|
4
4
|
import fs from 'node:fs';
|
|
5
5
|
import { fromPackageRoot } from '../fs/getPackageResource.js';
|
|
6
|
+
import { exitSync } from '../console/logging.js';
|
|
6
7
|
// search for package.json such that we can run init in non-js projects
|
|
7
8
|
export async function searchForPackageJson(cwd = process.cwd()) {
|
|
8
9
|
// Get the current working directory (where the CLI is being run)
|
|
@@ -48,8 +49,8 @@ export async function updatePackageJson(packageJson, cwd = process.cwd()) {
|
|
|
48
49
|
await fs.promises.writeFile(path.join(cwd, 'package.json'), JSON.stringify(packageJson, null, 2));
|
|
49
50
|
}
|
|
50
51
|
catch (error) {
|
|
51
|
-
|
|
52
|
-
|
|
52
|
+
logger.error(chalk.red('Error updating package.json: ' + String(error)));
|
|
53
|
+
exitSync(1);
|
|
53
54
|
}
|
|
54
55
|
}
|
|
55
56
|
// check if a package is installed in the package.json file
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { WorkflowStep } from './Workflow.js';
|
|
2
|
-
import {
|
|
2
|
+
import { logErrorAndExit } from '../console/logging.js';
|
|
3
|
+
import { logger } from '../console/logger.js';
|
|
3
4
|
import chalk from 'chalk';
|
|
4
5
|
import { getCurrentBranch, getIncomingBranches, getCheckedOutBranches, } from '../git/branches.js';
|
|
5
6
|
import { ApiError } from 'generaltranslation/errors';
|
|
6
7
|
// Step 1: Resolve the current branch id & update API with branch information
|
|
7
8
|
export class BranchStep extends WorkflowStep {
|
|
8
|
-
spinner = createSpinner('dots');
|
|
9
|
+
spinner = logger.createSpinner('dots');
|
|
9
10
|
branchData;
|
|
10
11
|
settings;
|
|
11
12
|
gt;
|
|
@@ -70,7 +71,7 @@ export class BranchStep extends WorkflowStep {
|
|
|
70
71
|
}
|
|
71
72
|
else {
|
|
72
73
|
if (!current) {
|
|
73
|
-
logErrorAndExit('Failed to determine the current branch. Please specify a custom branch or enable automatic branch detection.');
|
|
74
|
+
return logErrorAndExit('Failed to determine the current branch. Please specify a custom branch or enable automatic branch detection.');
|
|
74
75
|
}
|
|
75
76
|
const currentBranch = branchData.branches.find((b) => b.name === current.currentBranchName);
|
|
76
77
|
if (!currentBranch) {
|
|
@@ -83,7 +84,7 @@ export class BranchStep extends WorkflowStep {
|
|
|
83
84
|
}
|
|
84
85
|
catch (error) {
|
|
85
86
|
if (error instanceof ApiError && error.code === 403) {
|
|
86
|
-
|
|
87
|
+
logger.error('Failed to create branch. To enable branching, please upgrade your plan.');
|
|
87
88
|
// retry with default branch
|
|
88
89
|
const createBranchResult = await this.gt.createBranch({
|
|
89
90
|
branchName: 'main', // name doesn't matter for default branch
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
import { WorkflowStep } from './Workflow.js';
|
|
3
|
-
import {
|
|
3
|
+
import { logger } from '../console/logger.js';
|
|
4
4
|
import { downloadFileBatch, } from '../api/downloadFileBatch.js';
|
|
5
5
|
export class DownloadTranslationsStep extends WorkflowStep {
|
|
6
6
|
gt;
|
|
@@ -12,7 +12,7 @@ export class DownloadTranslationsStep extends WorkflowStep {
|
|
|
12
12
|
this.settings = settings;
|
|
13
13
|
}
|
|
14
14
|
async run({ fileTracker, resolveOutputPath, forceDownload, }) {
|
|
15
|
-
this.spinner = createProgressBar(fileTracker.completed.size);
|
|
15
|
+
this.spinner = logger.createProgressBar(fileTracker.completed.size);
|
|
16
16
|
this.spinner.start('Downloading files...');
|
|
17
17
|
// Download ready files
|
|
18
18
|
const success = await this.downloadFiles(fileTracker, resolveOutputPath, forceDownload);
|
|
@@ -73,7 +73,7 @@ export class DownloadTranslationsStep extends WorkflowStep {
|
|
|
73
73
|
const batchResult = await this.downloadFilesWithRetry(fileTracker, batchFiles, forceDownload);
|
|
74
74
|
this.spinner?.stop(chalk.green(`Downloaded ${batchResult.successful.length} files${batchResult.skipped.length > 0 ? `, skipped ${batchResult.skipped.length} files` : ''}`));
|
|
75
75
|
if (batchResult.failed.length > 0) {
|
|
76
|
-
|
|
76
|
+
logger.warn(`Failed to download ${batchResult.failed.length} files: ${batchResult.failed.map((f) => f.inputPath).join('\n')}`);
|
|
77
77
|
}
|
|
78
78
|
}
|
|
79
79
|
else {
|
|
@@ -83,7 +83,7 @@ export class DownloadTranslationsStep extends WorkflowStep {
|
|
|
83
83
|
}
|
|
84
84
|
catch (error) {
|
|
85
85
|
this.spinner?.stop(chalk.red('An error occurred while downloading translations'));
|
|
86
|
-
|
|
86
|
+
logger.error(chalk.red('Error: ') + error);
|
|
87
87
|
return false;
|
|
88
88
|
}
|
|
89
89
|
}
|
|
@@ -109,7 +109,7 @@ export class DownloadTranslationsStep extends WorkflowStep {
|
|
|
109
109
|
}
|
|
110
110
|
// Calculate exponential backoff delay
|
|
111
111
|
const delay = initialDelay * Math.pow(2, retryCount);
|
|
112
|
-
|
|
112
|
+
logger.error(chalk.yellow(`Retrying ${batchResult.failed.length} failed file(s) in ${delay}ms (attempt ${retryCount + 1}/${maxRetries})...`));
|
|
113
113
|
// Wait before retrying
|
|
114
114
|
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
115
115
|
remainingFiles = batchResult.failed;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { WorkflowStep } from './Workflow.js';
|
|
2
|
-
import {
|
|
2
|
+
import { logger } from '../console/logger.js';
|
|
3
3
|
import chalk from 'chalk';
|
|
4
4
|
export class EnqueueStep extends WorkflowStep {
|
|
5
5
|
gt;
|
|
6
6
|
settings;
|
|
7
7
|
force;
|
|
8
|
-
spinner = createSpinner('dots');
|
|
8
|
+
spinner = logger.createSpinner('dots');
|
|
9
9
|
result = null;
|
|
10
10
|
constructor(gt, settings, force) {
|
|
11
11
|
super();
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
import { WorkflowStep } from './Workflow.js';
|
|
3
|
-
import {
|
|
3
|
+
import { logger } from '../console/logger.js';
|
|
4
4
|
import { TEMPLATE_FILE_NAME } from '../cli/commands/stage.js';
|
|
5
5
|
export class PollTranslationJobsStep extends WorkflowStep {
|
|
6
6
|
gt;
|
|
@@ -12,7 +12,7 @@ export class PollTranslationJobsStep extends WorkflowStep {
|
|
|
12
12
|
}
|
|
13
13
|
async run({ fileTracker, fileQueryData, jobData, timeoutDuration, forceRetranslation, }) {
|
|
14
14
|
const startTime = Date.now();
|
|
15
|
-
this.spinner = createProgressBar(fileQueryData.length);
|
|
15
|
+
this.spinner = logger.createProgressBar(fileQueryData.length);
|
|
16
16
|
const spinnerMessage = forceRetranslation
|
|
17
17
|
? 'Waiting for retranslation...'
|
|
18
18
|
: 'Waiting for translation...';
|
|
@@ -144,7 +144,7 @@ export class PollTranslationJobsStep extends WorkflowStep {
|
|
|
144
144
|
}
|
|
145
145
|
}
|
|
146
146
|
catch (error) {
|
|
147
|
-
|
|
147
|
+
logger.error(chalk.red('Error checking job status: ') + error);
|
|
148
148
|
}
|
|
149
149
|
}, 5000);
|
|
150
150
|
}, msUntilNextInterval);
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { WorkflowStep } from './Workflow.js';
|
|
2
|
-
import {
|
|
2
|
+
import { logger } from '../console/logger.js';
|
|
3
3
|
import chalk from 'chalk';
|
|
4
4
|
export class SetupStep extends WorkflowStep {
|
|
5
5
|
gt;
|
|
6
6
|
settings;
|
|
7
7
|
timeoutMs;
|
|
8
|
-
spinner = createSpinner('dots');
|
|
8
|
+
spinner = logger.createSpinner('dots');
|
|
9
9
|
setupJobId = null;
|
|
10
10
|
files = null;
|
|
11
11
|
completed = false;
|