gt 2.7.0 → 2.7.1
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 +13 -0
- package/dist/cli/base.d.ts +2 -1
- package/dist/cli/base.js +32 -20
- package/dist/cli/commands/upload.js +1 -1
- package/dist/cli/flags.js +1 -1
- package/dist/cli/react.js +1 -1
- package/dist/config/generateSettings.js +2 -2
- package/dist/config/validateSettings.js +1 -1
- package/dist/console/index.d.ts +10 -10
- package/dist/console/index.js +11 -11
- package/dist/console/logging.js +1 -1
- package/dist/formats/files/aggregateFiles.js +1 -1
- package/dist/formats/json/mergeJson.js +1 -1
- package/dist/formats/json/parseJson.js +1 -1
- package/dist/fs/determineFramework.js +1 -1
- package/dist/generated/version.d.ts +1 -1
- package/dist/generated/version.js +1 -1
- package/dist/locadex/setupFlow.js +1 -1
- package/dist/react/parse/addVitePlugin/index.js +1 -1
- package/dist/react/parse/addVitePlugin/updateViteConfig.js +1 -1
- package/dist/setup/userInput.js +3 -3
- package/dist/setup/wizard.js +1 -1
- package/dist/translation/stage.js +1 -1
- package/dist/translation/validate.js +1 -1
- package/dist/utils/addExplicitAnchorIds.js +1 -1
- package/dist/utils/calculateTimeoutMs.d.ts +4 -0
- package/dist/utils/calculateTimeoutMs.js +8 -0
- package/dist/utils/constants.d.ts +1 -0
- package/dist/utils/constants.js +1 -0
- package/dist/utils/credentials.d.ts +8 -4
- package/dist/utils/credentials.js +15 -19
- package/dist/utils/fetch.d.ts +11 -0
- package/dist/utils/fetch.js +22 -0
- package/dist/utils/installPackage.js +4 -4
- package/dist/utils/packageManager.js +1 -1
- package/dist/workflows/setupProject.js +2 -8
- package/dist/workflows/stage.js +2 -8
- package/dist/workflows/steps/BranchStep.js +3 -3
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# gtx-cli
|
|
2
2
|
|
|
3
|
+
## 2.7.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#1085](https://github.com/generaltranslation/gt/pull/1085) [`dad7824`](https://github.com/generaltranslation/gt/commit/dad78246d164b201d4fc14c89213cc04f21c8b76) Thanks [@brian-lou](https://github.com/brian-lou)! - feat: Auth wizard supports both types of key creation
|
|
8
|
+
|
|
9
|
+
- [#1082](https://github.com/generaltranslation/gt/pull/1082) [`3cb3bbd`](https://github.com/generaltranslation/gt/commit/3cb3bbd13046e6c1f6f9d4b5286669b96b4a85b2) Thanks [@fernando-aviles](https://github.com/fernando-aviles)! - Bumping CLI timeouts
|
|
10
|
+
|
|
11
|
+
- [#1076](https://github.com/generaltranslation/gt/pull/1076) [`19ae4eb`](https://github.com/generaltranslation/gt/commit/19ae4eb0baf7e6f15d19f9fad384621d38d73d57) Thanks [@moss-bryophyta](https://github.com/moss-bryophyta)! - Apply style guide to error messages and warnings: remove "Please", simplify verbose phrasing, fix `in-line` → `inline`.
|
|
12
|
+
|
|
13
|
+
- Updated dependencies [[`dad7824`](https://github.com/generaltranslation/gt/commit/dad78246d164b201d4fc14c89213cc04f21c8b76)]:
|
|
14
|
+
- generaltranslation@8.1.14
|
|
15
|
+
|
|
3
16
|
## 2.7.0
|
|
4
17
|
|
|
5
18
|
### Minor Changes
|
package/dist/cli/base.d.ts
CHANGED
|
@@ -7,7 +7,8 @@ export type UploadOptions = {
|
|
|
7
7
|
defaultLocale?: string;
|
|
8
8
|
};
|
|
9
9
|
export type LoginOptions = {
|
|
10
|
-
|
|
10
|
+
config?: string;
|
|
11
|
+
keyType?: 'development' | 'production' | 'all';
|
|
11
12
|
};
|
|
12
13
|
export declare class BaseCLI {
|
|
13
14
|
protected library: SupportedLibraries;
|
package/dist/cli/base.js
CHANGED
|
@@ -205,29 +205,31 @@ export class BaseCLI {
|
|
|
205
205
|
setupLoginCommand() {
|
|
206
206
|
this.program
|
|
207
207
|
.command('auth')
|
|
208
|
-
.description('Generate
|
|
208
|
+
.description('Generate General Translation API keys and project ID')
|
|
209
209
|
.option('-c, --config <path>', 'Filepath to config file, by default gt.config.json', findFilepath(['gt.config.json']))
|
|
210
|
-
.option('-t, --key-type <type>', 'Type of key to generate, production | development')
|
|
210
|
+
.option('-t, --key-type <type>', 'Type of key to generate, production | development | all')
|
|
211
211
|
.action(async (options) => {
|
|
212
212
|
displayHeader('Authenticating with General Translation...');
|
|
213
213
|
if (!options.keyType) {
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
214
|
+
options.keyType = await promptSelect({
|
|
215
|
+
message: 'What type of API key would you like to generate?',
|
|
216
|
+
options: [
|
|
217
|
+
{ value: 'development', label: 'Development' },
|
|
218
|
+
{ value: 'production', label: 'Production' },
|
|
219
|
+
{ value: 'all', label: 'Both' },
|
|
220
|
+
],
|
|
221
|
+
defaultValue: 'all',
|
|
222
|
+
});
|
|
222
223
|
}
|
|
223
224
|
else {
|
|
224
225
|
if (options.keyType !== 'development' &&
|
|
225
|
-
options.keyType !== 'production'
|
|
226
|
-
|
|
226
|
+
options.keyType !== 'production' &&
|
|
227
|
+
options.keyType !== 'all') {
|
|
228
|
+
logErrorAndExit('Invalid key type, must be development, production, or all');
|
|
227
229
|
}
|
|
228
230
|
}
|
|
229
231
|
await this.handleLoginCommand(options);
|
|
230
|
-
logger.endCommand(`Done!
|
|
232
|
+
logger.endCommand(`Done! ${options.keyType} keys have been generated and saved to your .env.local file.`);
|
|
231
233
|
});
|
|
232
234
|
}
|
|
233
235
|
setupInitCommand() {
|
|
@@ -403,7 +405,7 @@ See https://generaltranslation.com/en/docs/next/guides/local-tx`);
|
|
|
403
405
|
const files = {};
|
|
404
406
|
for (const fileExtension of fileExtensions) {
|
|
405
407
|
const paths = await promptText({
|
|
406
|
-
message: `${chalk.cyan(FILE_EXT_TO_EXT_LABEL[fileExtension])}:
|
|
408
|
+
message: `${chalk.cyan(FILE_EXT_TO_EXT_LABEL[fileExtension])}: Enter a space-separated list of glob patterns matching the location of the ${FILE_EXT_TO_EXT_LABEL[fileExtension]} files you would like to translate.\nMake sure to include [locale] in the patterns.\nSee https://generaltranslation.com/docs/cli/reference/config#include for more information.`,
|
|
407
409
|
defaultValue: `./**/[locale]/*.${fileExtension}`,
|
|
408
410
|
});
|
|
409
411
|
files[fileExtension] = {
|
|
@@ -444,22 +446,32 @@ See https://generaltranslation.com/en/docs/next/guides/local-tx`);
|
|
|
444
446
|
const loginQuestion = useDefaults
|
|
445
447
|
? true
|
|
446
448
|
: await promptConfirm({
|
|
447
|
-
message:
|
|
449
|
+
message: 'Would you like the wizard to automatically generate API keys and a project ID for you?',
|
|
448
450
|
defaultValue: true,
|
|
449
451
|
});
|
|
450
452
|
if (loginQuestion) {
|
|
451
453
|
const settings = await generateSettings({});
|
|
452
|
-
const keyType =
|
|
454
|
+
const keyType = useDefaults
|
|
455
|
+
? 'all'
|
|
456
|
+
: await promptSelect({
|
|
457
|
+
message: 'What type of API key would you like to generate?',
|
|
458
|
+
options: [
|
|
459
|
+
{ value: 'development', label: 'Development' },
|
|
460
|
+
{ value: 'production', label: 'Production' },
|
|
461
|
+
{ value: 'all', label: 'Both' },
|
|
462
|
+
],
|
|
463
|
+
defaultValue: 'all',
|
|
464
|
+
});
|
|
453
465
|
const credentials = await retrieveCredentials(settings, keyType);
|
|
454
|
-
await setCredentials(credentials,
|
|
466
|
+
await setCredentials(credentials, settings.framework);
|
|
455
467
|
}
|
|
456
468
|
}
|
|
457
469
|
}
|
|
458
470
|
async handleLoginCommand(options) {
|
|
459
|
-
const settings = await generateSettings({});
|
|
460
|
-
const keyType = options.keyType || '
|
|
471
|
+
const settings = await generateSettings({ config: options.config });
|
|
472
|
+
const keyType = options.keyType || 'all';
|
|
461
473
|
const credentials = await retrieveCredentials(settings, keyType);
|
|
462
|
-
await setCredentials(credentials,
|
|
474
|
+
await setCredentials(credentials, settings.framework);
|
|
463
475
|
}
|
|
464
476
|
setupUpdateInstructionsCommand() {
|
|
465
477
|
this.program
|
|
@@ -89,7 +89,7 @@ export async function upload(filePaths, placeholderPaths, transformPaths, dataFo
|
|
|
89
89
|
}
|
|
90
90
|
}
|
|
91
91
|
if (allFiles.length === 0) {
|
|
92
|
-
logger.error('No files to upload were found.
|
|
92
|
+
logger.error('No files to upload were found. Check your configuration and try again.');
|
|
93
93
|
return;
|
|
94
94
|
}
|
|
95
95
|
if (!settings.defaultLocale) {
|
package/dist/cli/flags.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import findFilepath from '../fs/findFilepath.js';
|
|
2
2
|
import { DEFAULT_GIT_REMOTE_NAME } from '../utils/constants.js';
|
|
3
|
-
const DEFAULT_TIMEOUT =
|
|
3
|
+
const DEFAULT_TIMEOUT = 900;
|
|
4
4
|
export function attachSharedFlags(command) {
|
|
5
5
|
command
|
|
6
6
|
.option('-c, --config <path>', 'Filepath to config file, by default gt.config.json', findFilepath(['gt.config.json']))
|
package/dist/cli/react.js
CHANGED
|
@@ -59,7 +59,7 @@ export class ReactCLI extends InlineCLI {
|
|
|
59
59
|
logger.success(`Success! Added <T> tags and updated ${chalk.bold.cyan(filesUpdated.length)} files:\n` +
|
|
60
60
|
filesUpdated.map((file) => `${chalk.green('-')} ${file}`).join('\n'));
|
|
61
61
|
if (filesUpdated.length > 0) {
|
|
62
|
-
logger.step(chalk.green('
|
|
62
|
+
logger.step(chalk.green('Verify the changes before committing.'));
|
|
63
63
|
}
|
|
64
64
|
if (warnings.length > 0) {
|
|
65
65
|
logger.warn(chalk.yellow('Warnings encountered:') +
|
|
@@ -53,12 +53,12 @@ export async function generateSettings(flags, cwd = process.cwd()) {
|
|
|
53
53
|
if (gtConfig.projectId &&
|
|
54
54
|
flags.projectId &&
|
|
55
55
|
gtConfig.projectId !== flags.projectId) {
|
|
56
|
-
logErrorAndExit(`Project ID mismatch between ${chalk.green(gtConfig.projectId)} and ${chalk.green(flags.projectId)}!
|
|
56
|
+
logErrorAndExit(`Project ID mismatch between ${chalk.green(gtConfig.projectId)} and ${chalk.green(flags.projectId)}! Use the same projectId in all configs.`);
|
|
57
57
|
}
|
|
58
58
|
else if (gtConfig.projectId &&
|
|
59
59
|
projectIdEnv &&
|
|
60
60
|
gtConfig.projectId !== projectIdEnv) {
|
|
61
|
-
logErrorAndExit(`Project ID mismatch between ${chalk.green(gtConfig.projectId)} and ${chalk.green(projectIdEnv)}!
|
|
61
|
+
logErrorAndExit(`Project ID mismatch between ${chalk.green(gtConfig.projectId)} and ${chalk.green(projectIdEnv)}! Use the same projectId in all configs.`);
|
|
62
62
|
}
|
|
63
63
|
if (flags.options?.docsUrlPattern &&
|
|
64
64
|
!flags.options?.docsUrlPattern.includes('[locale]')) {
|
|
@@ -18,7 +18,7 @@ export function validateSettings(settings) {
|
|
|
18
18
|
settings.locales.some((locale) => isSupersetLocale(settings.defaultLocale, locale) &&
|
|
19
19
|
!isSupersetLocale(locale, settings.defaultLocale))) {
|
|
20
20
|
const locale = settings.locales.find((locale) => isSupersetLocale(settings.defaultLocale, locale));
|
|
21
|
-
return logErrorAndExit(`defaultLocale: ${settings.defaultLocale} is a superset of another locale (${locale})!
|
|
21
|
+
return logErrorAndExit(`defaultLocale: ${settings.defaultLocale} is a superset of another locale (${locale})! Change the defaultLocale to a more specific locale.`);
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
24
|
export function validateConfigExists() {
|
package/dist/console/index.d.ts
CHANGED
|
@@ -22,13 +22,13 @@ export declare const warnDataAttrOnBranch: (file: string, attrName: string, loca
|
|
|
22
22
|
export declare const warnRecursiveFunctionCallSync: (file: string, functionName: string, location?: string) => string;
|
|
23
23
|
export declare const warnDeclareStaticNotWrappedSync: (file: string, functionName: string, location?: string) => string;
|
|
24
24
|
export declare const warnDeclareStaticNoResultsSync: (file: string, functionName: string, location?: string) => string;
|
|
25
|
-
export declare const noLocalesError = "No locales found!
|
|
26
|
-
export declare const noDefaultLocaleError = "No default locale found!
|
|
27
|
-
export declare const noFilesError = "Incorrect or missing files configuration!
|
|
28
|
-
export declare const noSourceFileError = "No source file found!
|
|
29
|
-
export declare const noSupportedFormatError = "Unsupported data format!
|
|
30
|
-
export declare const noApiKeyError = "No API key found!
|
|
31
|
-
export declare const devApiKeyError = "
|
|
32
|
-
export declare const noProjectIdError = "No project ID found!
|
|
33
|
-
export declare const noVersionIdError = "No version ID found!
|
|
34
|
-
export declare const invalidConfigurationError = "Invalid files configuration!
|
|
25
|
+
export declare const noLocalesError = "No locales found! Provide a list of locales for translation, or specify them in your gt.config.json file.";
|
|
26
|
+
export declare const noDefaultLocaleError = "No default locale found! Provide a default locale, or specify it in your gt.config.json file.";
|
|
27
|
+
export declare const noFilesError = "Incorrect or missing files configuration! Make sure your files are configured correctly in your gt.config.json file.";
|
|
28
|
+
export declare const noSourceFileError = "No source file found! Double-check your translations directory and default locale.";
|
|
29
|
+
export declare const noSupportedFormatError = "Unsupported data format! Make sure your translationsDir parameter ends with a supported file extension.";
|
|
30
|
+
export declare const noApiKeyError = "No API key found! Provide an API key using the --api-key flag or set the GT_API_KEY environment variable.";
|
|
31
|
+
export declare const devApiKeyError = "Development API keys cannot be used with the General Translation API. Use a production API key instead.\nGenerate a production API key with: npx gt auth -t production";
|
|
32
|
+
export declare const noProjectIdError = "No project ID found! Provide a project ID using the --project-id flag, specify it in your gt.config.json file, or set the GT_PROJECT_ID environment variable.";
|
|
33
|
+
export declare const noVersionIdError = "No version ID found! Provide a version ID using the --version-id flag or specify it in your gt.config.json file as the _versionId property.";
|
|
34
|
+
export declare const invalidConfigurationError = "Invalid files configuration! Provide a valid configuration to download local translations or set the --publish flag to true to upload translations to the CDN.";
|
package/dist/console/index.js
CHANGED
|
@@ -6,7 +6,7 @@ const withWillErrorInNextVersion = (message) => `${message} (This will become an
|
|
|
6
6
|
const withStaticError = (message) => `<Static> rules violation: ${message}`;
|
|
7
7
|
const withDeclareStaticError = (message) => `declareStatic() rules violation: ${message}`;
|
|
8
8
|
// Synchronous wrappers for backward compatibility
|
|
9
|
-
export const warnApiKeyInConfigSync = (optionsFilepath) => `${colorizeFilepath(optionsFilepath)}: Your API key is exposed!
|
|
9
|
+
export const warnApiKeyInConfigSync = (optionsFilepath) => `${colorizeFilepath(optionsFilepath)}: Your API key is exposed! Remove it from the file and include it as an environment variable.`;
|
|
10
10
|
export const warnVariablePropSync = (file, attrName, value, location) => withLocation(file, `${colorizeComponent('<T>')} component has dynamic attribute ${colorizeIdString(attrName)} with value: ${colorizeContent(value)}. Change ${colorizeIdString(attrName)} to ensure this content is translated.`, location);
|
|
11
11
|
export const warnInvalidReturnSync = (file, functionName, expression, location) => withLocation(file, withStaticError(`Function ${colorizeFunctionName(functionName)} does not return a static expression. ${colorizeFunctionName(functionName)} must return either (1) a static string literal, (2) another static function invocation, (3) static JSX content, or (4) a ternary expression. Instead got:\n${colorizeContent(expression)}`), location);
|
|
12
12
|
// TODO: this is temporary until we handle implicit returns
|
|
@@ -34,13 +34,13 @@ export const warnRecursiveFunctionCallSync = (file, functionName, location) => w
|
|
|
34
34
|
export const warnDeclareStaticNotWrappedSync = (file, functionName, location) => withLocation(file, withDeclareStaticError(`Could not resolve ${colorizeFunctionName(formatCodeClamp(functionName))}. This call is not wrapped in declareStatic(). Ensure the function is properly wrapped with declareStatic() and does not have circular import dependencies.`), location);
|
|
35
35
|
export const warnDeclareStaticNoResultsSync = (file, functionName, location) => withLocation(file, withDeclareStaticError(`Could not resolve ${colorizeFunctionName(formatCodeClamp(functionName))}. DeclareStatic can only receive function invocations and cannot use undefined values or looped calls to construct its result.`), location);
|
|
36
36
|
// Re-export error messages
|
|
37
|
-
export const noLocalesError = `No locales found!
|
|
38
|
-
export const noDefaultLocaleError = `No default locale found!
|
|
39
|
-
export const noFilesError = `Incorrect or missing files configuration!
|
|
40
|
-
export const noSourceFileError = `No source file found!
|
|
41
|
-
export const noSupportedFormatError = `Unsupported data format!
|
|
42
|
-
export const noApiKeyError = `No API key found!
|
|
43
|
-
export const devApiKeyError = `
|
|
44
|
-
export const noProjectIdError = `No project ID found!
|
|
45
|
-
export const noVersionIdError = `No version ID found!
|
|
46
|
-
export const invalidConfigurationError = `Invalid files configuration!
|
|
37
|
+
export const noLocalesError = `No locales found! Provide a list of locales for translation, or specify them in your gt.config.json file.`;
|
|
38
|
+
export const noDefaultLocaleError = `No default locale found! Provide a default locale, or specify it in your gt.config.json file.`;
|
|
39
|
+
export const noFilesError = `Incorrect or missing files configuration! Make sure your files are configured correctly in your gt.config.json file.`;
|
|
40
|
+
export const noSourceFileError = `No source file found! Double-check your translations directory and default locale.`;
|
|
41
|
+
export const noSupportedFormatError = `Unsupported data format! Make sure your translationsDir parameter ends with a supported file extension.`;
|
|
42
|
+
export const noApiKeyError = `No API key found! Provide an API key using the --api-key flag or set the GT_API_KEY environment variable.`;
|
|
43
|
+
export const devApiKeyError = `Development API keys cannot be used with the General Translation API. Use a production API key instead.\nGenerate a production API key with: npx gt auth -t production`;
|
|
44
|
+
export const noProjectIdError = `No project ID found! Provide a project ID using the --project-id flag, specify it in your gt.config.json file, or set the GT_PROJECT_ID environment variable.`;
|
|
45
|
+
export const noVersionIdError = `No version ID found! Provide a version ID using the --version-id flag or specify it in your gt.config.json file as the _versionId property.`;
|
|
46
|
+
export const invalidConfigurationError = `Invalid files configuration! Provide a valid configuration to download local translations or set the --publish flag to true to upload translations to the CDN.`;
|
package/dist/console/logging.js
CHANGED
|
@@ -128,7 +128,7 @@ export async function promptConfirm({ message, defaultValue = true, cancelMessag
|
|
|
128
128
|
// Warning display functions
|
|
129
129
|
export function warnApiKeyInConfig(optionsFilepath) {
|
|
130
130
|
logger.warn(`Found ${chalk.cyan('apiKey')} in "${chalk.green(optionsFilepath)}". ` +
|
|
131
|
-
chalk.white('Your API key is exposed!
|
|
131
|
+
chalk.white('Your API key is exposed! Remove it from the file and include it as an environment variable.'));
|
|
132
132
|
}
|
|
133
133
|
export function warnVariableProp(file, attrName, value) {
|
|
134
134
|
logger.warn(`Found ${chalk.green('<T>')} component in ${chalk.cyan(file)} with variable ${attrName}: "${chalk.white(value)}". ` +
|
|
@@ -150,7 +150,7 @@ export async function aggregateFiles(settings) {
|
|
|
150
150
|
}
|
|
151
151
|
}
|
|
152
152
|
if (allFiles.length === 0 && !settings.publish) {
|
|
153
|
-
logger.error('No files to translate were found.
|
|
153
|
+
logger.error('No files to translate were found. Check your configuration and try again.');
|
|
154
154
|
}
|
|
155
155
|
return allFiles;
|
|
156
156
|
}
|
|
@@ -69,7 +69,7 @@ export function mergeJson(originalContent, inputPath, options, targets, defaultL
|
|
|
69
69
|
// Get source item for default locale
|
|
70
70
|
const matchingDefaultLocaleItems = findMatchingItemArray(canonicalDefaultLocale, sourceObjectOptions, sourceObjectPointer, sourceObjectValue);
|
|
71
71
|
if (!Object.keys(matchingDefaultLocaleItems).length) {
|
|
72
|
-
logger.warn(`Matching sourceItems not found at path: ${sourceObjectPointer}.
|
|
72
|
+
logger.warn(`Matching sourceItems not found at path: ${sourceObjectPointer}. Check that your JSON file includes the key field. Skipping this target`);
|
|
73
73
|
continue;
|
|
74
74
|
}
|
|
75
75
|
const matchingDefaultLocaleItemKeys = new Set(Object.keys(matchingDefaultLocaleItems));
|
|
@@ -47,7 +47,7 @@ export function parseJson(content, filePath, options, defaultLocale) {
|
|
|
47
47
|
// Find matching source items
|
|
48
48
|
const matchingItems = findMatchingItemArray(defaultLocale, sourceObjectOptions, sourceObjectPointer, sourceObjectValue);
|
|
49
49
|
if (!Object.keys(matchingItems).length) {
|
|
50
|
-
logger.error(`Matching sourceItem not found at path: ${sourceObjectPointer} for locale: ${defaultLocale}.
|
|
50
|
+
logger.error(`Matching sourceItem not found at path: ${sourceObjectPointer} for locale: ${defaultLocale}. Check your JSON schema`);
|
|
51
51
|
return exitSync(1);
|
|
52
52
|
}
|
|
53
53
|
// Construct lvl 3
|
|
@@ -12,7 +12,7 @@ export function determineLibrary() {
|
|
|
12
12
|
const packageJsonPath = path.join(cwd, 'package.json');
|
|
13
13
|
// Check if package.json exists
|
|
14
14
|
if (!fs.existsSync(packageJsonPath)) {
|
|
15
|
-
logger.warn(chalk.yellow('No package.json found in the current directory.
|
|
15
|
+
logger.warn(chalk.yellow('No package.json found in the current directory. Run this command from the root of your project.'));
|
|
16
16
|
return { library: 'base', additionalModules: [] };
|
|
17
17
|
}
|
|
18
18
|
// Read and parse package.json
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const PACKAGE_VERSION = "2.7.
|
|
1
|
+
export declare const PACKAGE_VERSION = "2.7.1";
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// This file is auto-generated. Do not edit manually.
|
|
2
|
-
export const PACKAGE_VERSION = '2.7.
|
|
2
|
+
export const PACKAGE_VERSION = '2.7.1';
|
|
@@ -5,5 +5,5 @@ export async function setupLocadex(settings) {
|
|
|
5
5
|
await import('open').then((open) => open.default(urlToOpen, {
|
|
6
6
|
wait: false,
|
|
7
7
|
}));
|
|
8
|
-
logger.message(`${chalk.dim(`If the browser window didn't open automatically,
|
|
8
|
+
logger.message(`${chalk.dim(`If the browser window didn't open automatically, open the following link:`)}\n\n${chalk.cyan(urlToOpen)}`);
|
|
9
9
|
}
|
|
@@ -18,7 +18,7 @@ export async function addVitePlugin({ errors, warnings, filesUpdated, packageJso
|
|
|
18
18
|
VITE_CONFIG_PATH_BASE + 'cts',
|
|
19
19
|
]);
|
|
20
20
|
if (!viteConfigPath) {
|
|
21
|
-
logger.error(`No ${VITE_CONFIG_PATH_BASE}[js|ts|mjs|mts|cjs|cts] file found.
|
|
21
|
+
logger.error(`No ${VITE_CONFIG_PATH_BASE}[js|ts|mjs|mts|cjs|cts] file found. Add the @generaltranslation/compiler plugin to your vite configuration file:
|
|
22
22
|
import { vite as gtCompiler } from '@generaltranslation/compiler';
|
|
23
23
|
export default defineConfig({
|
|
24
24
|
plugins: [gtCompiler()],
|
|
@@ -102,7 +102,7 @@ async function updateViteConfigAst({ code, warnings, viteConfigPath, packageJson
|
|
|
102
102
|
if (!pluginAlreadyPresent) {
|
|
103
103
|
success = addPluginInvocation({ ast, alias, namespaces });
|
|
104
104
|
if (!success) {
|
|
105
|
-
warnings.push(`Failed to add gt compiler plugin to ${viteConfigPath}.
|
|
105
|
+
warnings.push(`Failed to add gt compiler plugin to ${viteConfigPath}. Add the plugin manually:
|
|
106
106
|
import { vite as gtCompiler } from '@generaltranslation/compiler';
|
|
107
107
|
export default defineConfig({
|
|
108
108
|
plugins: [gtCompiler()],
|
package/dist/setup/userInput.js
CHANGED
|
@@ -15,14 +15,14 @@ export async function getDesiredLocales() {
|
|
|
15
15
|
validate: (input) => {
|
|
16
16
|
const localeList = input.split(' ');
|
|
17
17
|
if (localeList.length === 0) {
|
|
18
|
-
return '
|
|
18
|
+
return 'Enter at least one locale';
|
|
19
19
|
}
|
|
20
20
|
if (localeList.some((locale) => !locale.trim())) {
|
|
21
|
-
return '
|
|
21
|
+
return 'Enter a valid locale (e.g., es fr de)';
|
|
22
22
|
}
|
|
23
23
|
for (const locale of localeList) {
|
|
24
24
|
if (!gt.isValidLocale(locale)) {
|
|
25
|
-
return '
|
|
25
|
+
return 'Enter a valid locale (e.g., es fr de)';
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
28
|
return true;
|
package/dist/setup/wizard.js
CHANGED
|
@@ -58,7 +58,7 @@ Please let us know what you would like to see added at https://github.com/genera
|
|
|
58
58
|
});
|
|
59
59
|
const packageJson = await getPackageJson();
|
|
60
60
|
if (!packageJson) {
|
|
61
|
-
logger.error(chalk.red('No package.json found in the current directory.
|
|
61
|
+
logger.error(chalk.red('No package.json found in the current directory. Run this command from the root of your project.'));
|
|
62
62
|
exitSync(1);
|
|
63
63
|
}
|
|
64
64
|
// Check if gt-next or gt-react is installed
|
|
@@ -37,7 +37,7 @@ export async function aggregateInlineTranslations(options, settings, library) {
|
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
39
|
if (updates.length == 0) {
|
|
40
|
-
logger.error(chalk.red(`No
|
|
40
|
+
logger.error(chalk.red(`No inline 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;
|
|
@@ -92,7 +92,7 @@ export async function validateProject(settings, pkg, files) {
|
|
|
92
92
|
.join('')));
|
|
93
93
|
}
|
|
94
94
|
if (updates.length === 0) {
|
|
95
|
-
logger.error(chalk.red(`No
|
|
95
|
+
logger.error(chalk.red(`No inline content or dictionaries were found for ${chalk.green(pkg)}. Are you sure you're running this command in the right directory?`));
|
|
96
96
|
}
|
|
97
97
|
else {
|
|
98
98
|
logger.success(chalk.green(`Success! Found ${updates.length} translatable entries for ${chalk.green(pkg)}.`));
|
|
@@ -151,7 +151,7 @@ export function addExplicitAnchorIds(translatedContent, sourceHeadingMap, settin
|
|
|
151
151
|
: 'translated file';
|
|
152
152
|
logger.warn(`Header count mismatch detected! ${sourceFile} has ${sourceHeadingMap.length} headers but ${translatedFile} has ${translatedHeadings.length} headers. ` +
|
|
153
153
|
`This likely means your source file was edited after translation was requested, causing a mismatch between ` +
|
|
154
|
-
`the number of headers in your source file vs the translated file.
|
|
154
|
+
`the number of headers in your source file vs the translated file. Re-translate this file to resolve the issue.`);
|
|
155
155
|
}
|
|
156
156
|
// Create ID mapping based on positional matching
|
|
157
157
|
const idMappings = new Map();
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { DEFAULT_TIMEOUT_SECONDS } from './constants.js';
|
|
2
|
+
/**
|
|
3
|
+
* Calculate timeout in ms with validation
|
|
4
|
+
*/
|
|
5
|
+
export function calculateTimeoutMs(timeout) {
|
|
6
|
+
const value = timeout !== undefined ? Number(timeout) : DEFAULT_TIMEOUT_SECONDS;
|
|
7
|
+
return (Number.isFinite(value) ? value : DEFAULT_TIMEOUT_SECONDS) * 1000;
|
|
8
|
+
}
|
|
@@ -3,3 +3,4 @@ export declare const GT_CONFIG_SCHEMA_URL = "https://assets.gtx.dev/config-schem
|
|
|
3
3
|
export declare const TEMPLATE_FILE_NAME = "__INTERNAL_GT_TEMPLATE_NAME__";
|
|
4
4
|
export declare const TEMPLATE_FILE_ID: string;
|
|
5
5
|
export declare const DEFAULT_GIT_REMOTE_NAME = "origin";
|
|
6
|
+
export declare const DEFAULT_TIMEOUT_SECONDS = 900;
|
package/dist/utils/constants.js
CHANGED
|
@@ -4,3 +4,4 @@ export const GT_CONFIG_SCHEMA_URL = 'https://assets.gtx.dev/config-schema.json';
|
|
|
4
4
|
export const TEMPLATE_FILE_NAME = '__INTERNAL_GT_TEMPLATE_NAME__';
|
|
5
5
|
export const TEMPLATE_FILE_ID = hashStringSync(TEMPLATE_FILE_NAME);
|
|
6
6
|
export const DEFAULT_GIT_REMOTE_NAME = 'origin';
|
|
7
|
+
export const DEFAULT_TIMEOUT_SECONDS = 900;
|
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import { Settings, SupportedFrameworks } from '../types/index.js';
|
|
2
2
|
type Credentials = {
|
|
3
|
-
|
|
3
|
+
apiKeys: ApiKey[];
|
|
4
4
|
projectId: string;
|
|
5
5
|
};
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
type ApiKey = {
|
|
7
|
+
key: string;
|
|
8
|
+
type: 'development' | 'production';
|
|
9
|
+
};
|
|
10
|
+
export declare function retrieveCredentials(settings: Settings, keyType: 'development' | 'production' | 'all'): Promise<Credentials>;
|
|
11
|
+
export declare function generateCredentialsSession(url: string, keyType: 'development' | 'production' | 'all'): Promise<{
|
|
8
12
|
sessionId: string;
|
|
9
13
|
}>;
|
|
10
14
|
export declare function areCredentialsSet(): string | undefined;
|
|
11
|
-
export declare function setCredentials(credentials: Credentials,
|
|
15
|
+
export declare function setCredentials(credentials: Credentials, framework?: SupportedFrameworks, cwd?: string): Promise<void>;
|
|
12
16
|
export {};
|
|
@@ -3,6 +3,7 @@ import { logger } from '../console/logger.js';
|
|
|
3
3
|
import path from 'node:path';
|
|
4
4
|
import fs from 'node:fs';
|
|
5
5
|
import chalk from 'chalk';
|
|
6
|
+
import apiRequest from './fetch.js';
|
|
6
7
|
// Fetches project ID and API key by opening the dashboard in the browser
|
|
7
8
|
export async function retrieveCredentials(settings, keyType) {
|
|
8
9
|
// Generate a session ID
|
|
@@ -18,15 +19,13 @@ export async function retrieveCredentials(settings, keyType) {
|
|
|
18
19
|
const interval = setInterval(async () => {
|
|
19
20
|
// Ping the dashboard to see if the credentials are set
|
|
20
21
|
try {
|
|
21
|
-
const res = await
|
|
22
|
-
method: 'GET',
|
|
23
|
-
});
|
|
22
|
+
const res = await apiRequest(settings.baseUrl, `/cli/wizard/${sessionId}`, { method: 'GET' });
|
|
24
23
|
if (res.status === 200) {
|
|
25
24
|
const data = await res.json();
|
|
26
25
|
resolve(data);
|
|
27
26
|
clearInterval(interval);
|
|
28
27
|
clearTimeout(timeout);
|
|
29
|
-
|
|
28
|
+
apiRequest(settings.baseUrl, `/cli/wizard/${sessionId}`, {
|
|
30
29
|
method: 'DELETE',
|
|
31
30
|
});
|
|
32
31
|
}
|
|
@@ -46,14 +45,8 @@ export async function retrieveCredentials(settings, keyType) {
|
|
|
46
45
|
return credentials;
|
|
47
46
|
}
|
|
48
47
|
export async function generateCredentialsSession(url, keyType) {
|
|
49
|
-
const res = await
|
|
50
|
-
|
|
51
|
-
headers: {
|
|
52
|
-
'Content-Type': 'application/json',
|
|
53
|
-
},
|
|
54
|
-
body: JSON.stringify({
|
|
55
|
-
keyType,
|
|
56
|
-
}),
|
|
48
|
+
const res = await apiRequest(url, '/cli/wizard/session', {
|
|
49
|
+
body: { keyType },
|
|
57
50
|
});
|
|
58
51
|
if (!res.ok) {
|
|
59
52
|
logErrorAndExit('Failed to generate credentials session');
|
|
@@ -62,10 +55,11 @@ export async function generateCredentialsSession(url, keyType) {
|
|
|
62
55
|
}
|
|
63
56
|
// Checks if the credentials are set in the environment variables
|
|
64
57
|
export function areCredentialsSet() {
|
|
65
|
-
return process.env.GT_PROJECT_ID &&
|
|
58
|
+
return (process.env.GT_PROJECT_ID &&
|
|
59
|
+
(process.env.GT_API_KEY || process.env.GT_DEV_API_KEY));
|
|
66
60
|
}
|
|
67
61
|
// Sets the credentials in .env.local file
|
|
68
|
-
export async function setCredentials(credentials,
|
|
62
|
+
export async function setCredentials(credentials, framework, cwd = process.cwd()) {
|
|
69
63
|
const envFile = path.join(cwd, '.env.local');
|
|
70
64
|
let envContent = '';
|
|
71
65
|
// Check if .env.local exists, create it if it doesn't
|
|
@@ -107,11 +101,13 @@ export async function setCredentials(credentials, type, framework, cwd = process
|
|
|
107
101
|
prefix = 'REDWOOD_ENV_';
|
|
108
102
|
}
|
|
109
103
|
envContent += `\n${prefix}GT_PROJECT_ID=${credentials.projectId}\n`;
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
104
|
+
for (const apiKey of credentials.apiKeys) {
|
|
105
|
+
if (apiKey.type === 'development') {
|
|
106
|
+
envContent += `${prefix || ''}GT_DEV_API_KEY=${apiKey.key}\n`;
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
envContent += `${prefix || ''}GT_API_KEY=${apiKey.key}\n`;
|
|
110
|
+
}
|
|
115
111
|
}
|
|
116
112
|
// Ensure we don't have excessive newlines
|
|
117
113
|
envContent = envContent.replace(/\n{3,}/g, '\n\n').trim() + '\n';
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @internal
|
|
3
|
+
*
|
|
4
|
+
* Makes an API request to the General Translation API.
|
|
5
|
+
*
|
|
6
|
+
* Encapsulates URL construction, headers, and JSON parsing.
|
|
7
|
+
*/
|
|
8
|
+
export default function apiRequest<T>(baseUrl: string, endpoint: string, options?: {
|
|
9
|
+
body?: unknown;
|
|
10
|
+
method?: 'GET' | 'POST' | 'DELETE';
|
|
11
|
+
}): Promise<Response>;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { API_VERSION } from 'generaltranslation';
|
|
2
|
+
/**
|
|
3
|
+
* @internal
|
|
4
|
+
*
|
|
5
|
+
* Makes an API request to the General Translation API.
|
|
6
|
+
*
|
|
7
|
+
* Encapsulates URL construction, headers, and JSON parsing.
|
|
8
|
+
*/
|
|
9
|
+
export default async function apiRequest(baseUrl, endpoint, options) {
|
|
10
|
+
const method = options?.method ?? 'POST';
|
|
11
|
+
const requestInit = {
|
|
12
|
+
method,
|
|
13
|
+
headers: {
|
|
14
|
+
'Content-Type': 'application/json',
|
|
15
|
+
'gt-api-version': API_VERSION,
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
if (options?.body !== undefined) {
|
|
19
|
+
requestInit.body = JSON.stringify(options.body);
|
|
20
|
+
}
|
|
21
|
+
return fetch(`${baseUrl}${endpoint}`, requestInit);
|
|
22
|
+
}
|
|
@@ -20,7 +20,7 @@ export async function installPackage(packageName, packageManager, asDevDependenc
|
|
|
20
20
|
}
|
|
21
21
|
childProcess.on('error', (error) => {
|
|
22
22
|
logger.error(chalk.red(`Installation error: ${error.message}`));
|
|
23
|
-
logger.info(`
|
|
23
|
+
logger.info(`Manually install ${packageName} with: ${packageManager.name} ${packageManager.installCommand} ${packageName}`);
|
|
24
24
|
reject(error);
|
|
25
25
|
});
|
|
26
26
|
childProcess.on('close', (code) => {
|
|
@@ -32,7 +32,7 @@ export async function installPackage(packageName, packageManager, asDevDependenc
|
|
|
32
32
|
if (errorOutput) {
|
|
33
33
|
logger.error(chalk.red(`Error details: ${errorOutput}`));
|
|
34
34
|
}
|
|
35
|
-
logger.info(`
|
|
35
|
+
logger.info(`Manually install ${packageName} with: ${packageManager.name} ${packageManager.installCommand} ${packageName}`);
|
|
36
36
|
reject(new Error(`Process exited with code ${code}`));
|
|
37
37
|
}
|
|
38
38
|
});
|
|
@@ -57,7 +57,7 @@ export async function installPackageGlobal(packageName, version) {
|
|
|
57
57
|
}
|
|
58
58
|
childProcess.on('error', (error) => {
|
|
59
59
|
logger.error(chalk.red(`Installation error: ${error.message}`));
|
|
60
|
-
logger.info(`
|
|
60
|
+
logger.info(`Manually install ${packageName} with: npm install -g ${packageName}`);
|
|
61
61
|
reject(error);
|
|
62
62
|
});
|
|
63
63
|
childProcess.on('close', (code) => {
|
|
@@ -69,7 +69,7 @@ export async function installPackageGlobal(packageName, version) {
|
|
|
69
69
|
if (errorOutput) {
|
|
70
70
|
logger.error(chalk.red(`Error details: ${errorOutput}`));
|
|
71
71
|
}
|
|
72
|
-
logger.info(`
|
|
72
|
+
logger.info(`Manually install ${packageName} with: npm install -g ${packageName}`);
|
|
73
73
|
reject(new Error(`Process exited with code ${code}`));
|
|
74
74
|
}
|
|
75
75
|
});
|
|
@@ -258,7 +258,7 @@ export async function getPackageManager(cwd = process.cwd(), specifiedPackageMan
|
|
|
258
258
|
throw new NoPackageManagerError('No package manager found');
|
|
259
259
|
}
|
|
260
260
|
const selectedPackageManager = await promptSelect({
|
|
261
|
-
message: '
|
|
261
|
+
message: 'Select your package manager.',
|
|
262
262
|
options: packageManagers.map((packageManager) => ({
|
|
263
263
|
value: packageManager,
|
|
264
264
|
label: packageManager.label,
|
|
@@ -4,13 +4,7 @@ import { UploadSourcesStep } from './steps/UploadSourcesStep.js';
|
|
|
4
4
|
import { SetupStep } from './steps/SetupStep.js';
|
|
5
5
|
import { BranchStep } from './steps/BranchStep.js';
|
|
6
6
|
import { logCollectedFiles } from '../console/logging.js';
|
|
7
|
-
|
|
8
|
-
* Helper: Calculate timeout with validation
|
|
9
|
-
*/
|
|
10
|
-
function calculateTimeout(timeout) {
|
|
11
|
-
const value = timeout !== undefined ? Number(timeout) : 600;
|
|
12
|
-
return (Number.isFinite(value) ? value : 600) * 1000;
|
|
13
|
-
}
|
|
7
|
+
import { calculateTimeoutMs } from '../utils/calculateTimeoutMs.js';
|
|
14
8
|
/**
|
|
15
9
|
* Sets up a project by uploading files running the setup step
|
|
16
10
|
* @param files - Array of file objects to upload
|
|
@@ -23,7 +17,7 @@ export async function runSetupProjectWorkflow(files, options, settings) {
|
|
|
23
17
|
// Log files to be translated
|
|
24
18
|
logCollectedFiles(files);
|
|
25
19
|
// Calculate timeout for setup step
|
|
26
|
-
const timeoutMs =
|
|
20
|
+
const timeoutMs = calculateTimeoutMs(options.timeout);
|
|
27
21
|
// Create workflow with steps
|
|
28
22
|
const branchStep = new BranchStep(gt, settings);
|
|
29
23
|
const uploadStep = new UploadSourcesStep(gt, settings);
|
package/dist/workflows/stage.js
CHANGED
|
@@ -5,13 +5,7 @@ import { SetupStep } from './steps/SetupStep.js';
|
|
|
5
5
|
import { EnqueueStep } from './steps/EnqueueStep.js';
|
|
6
6
|
import { BranchStep } from './steps/BranchStep.js';
|
|
7
7
|
import { UserEditDiffsStep } from './steps/UserEditDiffsStep.js';
|
|
8
|
-
|
|
9
|
-
* Helper: Calculate timeout with validation
|
|
10
|
-
*/
|
|
11
|
-
function calculateTimeout(timeout) {
|
|
12
|
-
const value = timeout !== undefined ? Number(timeout) : 600;
|
|
13
|
-
return (Number.isFinite(value) ? value : 600) * 1000;
|
|
14
|
-
}
|
|
8
|
+
import { calculateTimeoutMs } from '../utils/calculateTimeoutMs.js';
|
|
15
9
|
/**
|
|
16
10
|
* Sends multiple files for translation to the API using a workflow pattern
|
|
17
11
|
* @param files - Array of file objects to translate
|
|
@@ -24,7 +18,7 @@ export async function runStageFilesWorkflow({ files, options, settings, }) {
|
|
|
24
18
|
// Log files to be translated
|
|
25
19
|
logCollectedFiles(files);
|
|
26
20
|
// Calculate timeout for setup step
|
|
27
|
-
const timeoutMs =
|
|
21
|
+
const timeoutMs = calculateTimeoutMs(options.timeout);
|
|
28
22
|
// Create workflow with steps
|
|
29
23
|
const branchStep = new BranchStep(gt, settings);
|
|
30
24
|
const uploadStep = new UploadSourcesStep(gt, settings);
|
|
@@ -90,7 +90,7 @@ export class BranchStep extends WorkflowStep {
|
|
|
90
90
|
}
|
|
91
91
|
else {
|
|
92
92
|
if (!current) {
|
|
93
|
-
return logErrorAndExit('Failed to determine the current branch.
|
|
93
|
+
return logErrorAndExit('Failed to determine the current branch. Specify a custom branch or enable automatic branch detection.');
|
|
94
94
|
}
|
|
95
95
|
const currentBranch = branchData.branches.find((b) => b.name === current.currentBranchName);
|
|
96
96
|
if (!currentBranch) {
|
|
@@ -103,7 +103,7 @@ export class BranchStep extends WorkflowStep {
|
|
|
103
103
|
}
|
|
104
104
|
catch (error) {
|
|
105
105
|
if (error instanceof ApiError && error.code === 403) {
|
|
106
|
-
logger.warn('To enable translation branching,
|
|
106
|
+
logger.warn('To enable translation branching, upgrade your plan. Falling back to default branch.');
|
|
107
107
|
// retry with default branch
|
|
108
108
|
try {
|
|
109
109
|
const createBranchResult = await this.gt.createBranch({
|
|
@@ -121,7 +121,7 @@ export class BranchStep extends WorkflowStep {
|
|
|
121
121
|
}
|
|
122
122
|
}
|
|
123
123
|
if (this.branchData.currentBranch.id === '') {
|
|
124
|
-
return logErrorAndExit('Something went wrong while resolving branch information.
|
|
124
|
+
return logErrorAndExit('Something went wrong while resolving branch information. Try again.');
|
|
125
125
|
}
|
|
126
126
|
// Now set the incoming and checked out branches (first one that exists)
|
|
127
127
|
this.branchData.incomingBranch =
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gt",
|
|
3
|
-
"version": "2.7.
|
|
3
|
+
"version": "2.7.1",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"bin": "dist/main.js",
|
|
6
6
|
"files": [
|
|
@@ -109,7 +109,7 @@
|
|
|
109
109
|
"unified": "^11.0.5",
|
|
110
110
|
"unist-util-visit": "^5.0.0",
|
|
111
111
|
"yaml": "^2.8.0",
|
|
112
|
-
"generaltranslation": "8.1.
|
|
112
|
+
"generaltranslation": "8.1.14",
|
|
113
113
|
"gt-remark": "1.0.5"
|
|
114
114
|
},
|
|
115
115
|
"devDependencies": {
|