gtx-cli 0.0.1 → 0.0.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 (84) hide show
  1. package/README.md +4 -7
  2. package/dist/api/waitForUpdates.d.ts +1 -0
  3. package/dist/api/waitForUpdates.js +89 -0
  4. package/dist/cli/base.d.ts +3 -0
  5. package/dist/cli/base.js +11 -0
  6. package/dist/cli/next.d.ts +18 -0
  7. package/dist/cli/next.js +162 -0
  8. package/dist/cli/react.d.ts +29 -0
  9. package/dist/cli/react.js +550 -0
  10. package/dist/console/console.d.ts +8 -0
  11. package/dist/console/console.js +65 -0
  12. package/dist/console/errors.d.ts +1 -0
  13. package/dist/console/errors.js +4 -0
  14. package/dist/console/index.d.ts +1 -0
  15. package/dist/console/index.js +2 -0
  16. package/dist/console/warnings.d.ts +7 -0
  17. package/dist/console/warnings.js +47 -0
  18. package/dist/fs/config/loadConfig.d.ts +1 -0
  19. package/dist/fs/config/loadConfig.js +15 -0
  20. package/dist/fs/config/setupConfig.d.ts +8 -0
  21. package/dist/fs/config/setupConfig.js +37 -0
  22. package/dist/fs/config/updateConfig.d.ts +10 -0
  23. package/dist/fs/config/updateConfig.js +33 -0
  24. package/dist/fs/findFilepath.d.ts +15 -0
  25. package/dist/fs/findFilepath.js +49 -0
  26. package/dist/fs/findJsxFilepath.d.ts +7 -0
  27. package/dist/fs/findJsxFilepath.js +36 -0
  28. package/dist/fs/index.d.ts +1 -0
  29. package/dist/fs/index.js +2 -0
  30. package/dist/fs/loadJSON.d.ts +6 -0
  31. package/dist/fs/loadJSON.js +23 -0
  32. package/dist/fs/saveTranslations.d.ts +3 -0
  33. package/dist/fs/saveTranslations.js +57 -0
  34. package/dist/hooks/postProcess.d.ts +4 -0
  35. package/dist/hooks/postProcess.js +101 -0
  36. package/dist/index.d.ts +3 -0
  37. package/dist/index.js +84 -0
  38. package/dist/main.d.ts +2 -0
  39. package/dist/main.js +11 -0
  40. package/dist/next/config/parseNextConfig.d.ts +10 -0
  41. package/dist/next/config/parseNextConfig.js +55 -0
  42. package/dist/next/jsx/utils.d.ts +7 -0
  43. package/dist/next/jsx/utils.js +82 -0
  44. package/dist/next/parse/handleInitGT.d.ts +5 -0
  45. package/dist/next/parse/handleInitGT.js +167 -0
  46. package/dist/next/parse/index.d.ts +4 -0
  47. package/dist/next/parse/index.js +14 -0
  48. package/dist/next/parse/scanForContent.d.ts +13 -0
  49. package/dist/next/parse/scanForContent.js +189 -0
  50. package/dist/react/config/createESBuildConfig.d.ts +2 -0
  51. package/dist/react/config/createESBuildConfig.js +134 -0
  52. package/dist/react/data-_gt/addGTIdentifierToSyntaxTree.d.ts +1 -0
  53. package/dist/react/data-_gt/addGTIdentifierToSyntaxTree.js +92 -0
  54. package/dist/react/jsx/evaluateJsx.d.ts +17 -0
  55. package/dist/react/jsx/evaluateJsx.js +133 -0
  56. package/dist/react/jsx/trimJsxStringChildren.d.ts +7 -0
  57. package/dist/react/jsx/trimJsxStringChildren.js +97 -0
  58. package/dist/react/jsx/utils/parseAst.d.ts +30 -0
  59. package/dist/react/jsx/utils/parseAst.js +320 -0
  60. package/dist/react/jsx/utils/parseJsx.d.ts +13 -0
  61. package/dist/react/jsx/utils/parseJsx.js +236 -0
  62. package/dist/react/jsx/utils/parseStringFunction.d.ts +12 -0
  63. package/dist/react/jsx/utils/parseStringFunction.js +120 -0
  64. package/dist/react/jsx/wrapJsx.d.ts +51 -0
  65. package/dist/react/jsx/wrapJsx.js +407 -0
  66. package/dist/react/parse/createDictionaryUpdates.d.ts +5 -0
  67. package/dist/react/parse/createDictionaryUpdates.js +77 -0
  68. package/dist/react/parse/createInlineUpdates.d.ts +5 -0
  69. package/dist/react/parse/createInlineUpdates.js +141 -0
  70. package/dist/react/parse/index.d.ts +3 -0
  71. package/dist/react/parse/index.js +12 -0
  72. package/dist/react/parse/scanForContent.d.ts +13 -0
  73. package/dist/react/parse/scanForContent.js +200 -0
  74. package/dist/react/types.d.ts +13 -0
  75. package/dist/react/types.js +2 -0
  76. package/dist/react/utils/flattenDictionary.d.ts +10 -0
  77. package/dist/react/utils/flattenDictionary.js +38 -0
  78. package/dist/react/utils/getEntryAndMetadata.d.ts +5 -0
  79. package/dist/react/utils/getEntryAndMetadata.js +14 -0
  80. package/dist/react/utils/getVariableName.d.ts +2 -0
  81. package/dist/react/utils/getVariableName.js +20 -0
  82. package/dist/types.d.ts +58 -0
  83. package/dist/types.js +2 -0
  84. package/package.json +9 -2
package/README.md CHANGED
@@ -4,25 +4,22 @@
4
4
  </a>
5
5
  </p>
6
6
 
7
- # gt-react-cli: Command-line tool for gt-react
7
+ # gtx-cli: General Purpose CLI Tool for General Translation
8
8
 
9
- gt-react-cli is a command-line tool used to push `gt-react` dictionaries and `<T>` components to be translated.
10
-
11
- Additionally, it can scan your project for all content that needs to be translated, and automatically wrap them in `<T>` and `<Var>` components.
9
+ gtx-cli is a command-line tool used to interface with General Translation's AI-powered i18n platform.
12
10
 
13
11
  See our [docs](https://generaltranslation.com/docs) for more information including guides, examples, and API references.
14
12
 
15
13
  ## Installation
16
14
 
17
15
  ```bash
18
- npm install gt-react-cli
16
+ npm install gtx-cli
19
17
  ```
20
18
 
21
19
  ## Usage
22
20
 
23
21
  ```bash
24
- npx gt-react-cli translate
25
- npx gt-react-cli setup
22
+ npx gtx-cli translate
26
23
  ```
27
24
 
28
25
  ## Documentation
@@ -0,0 +1 @@
1
+ export declare const waitForUpdates: (apiKey: string, baseUrl: string, versionId: string, locales: string[], startTime: number, timeoutDuration: number) => Promise<boolean>;
@@ -0,0 +1,89 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.waitForUpdates = void 0;
16
+ const chalk_1 = __importDefault(require("chalk"));
17
+ const console_1 = require("../console/console");
18
+ const generaltranslation_1 = require("generaltranslation");
19
+ const waitForUpdates = (apiKey, baseUrl, versionId, locales, startTime, timeoutDuration) => __awaiter(void 0, void 0, void 0, function* () {
20
+ const spinner = yield (0, console_1.displayLoadingAnimation)('Waiting for translation...');
21
+ const availableLocales = [];
22
+ const checkDeployment = () => __awaiter(void 0, void 0, void 0, function* () {
23
+ try {
24
+ const response = yield fetch(`${baseUrl}/v1/project/translations/status/${encodeURIComponent(versionId)}`, {
25
+ method: 'GET',
26
+ headers: Object.assign({ 'Content-Type': 'application/json' }, (apiKey && { 'x-gt-api-key': apiKey })),
27
+ });
28
+ if (response.ok) {
29
+ const data = yield response.json();
30
+ if (data.availableLocales) {
31
+ data.availableLocales.forEach((locale) => {
32
+ if (!availableLocales.includes(locale) &&
33
+ locales.includes(locale)) {
34
+ availableLocales.push(locale);
35
+ }
36
+ });
37
+ const newSuffixText = [
38
+ `\n\n` +
39
+ chalk_1.default.green(`${availableLocales.length}/${locales.length}`) +
40
+ ` translations completed`,
41
+ ...availableLocales.map((locale) => {
42
+ const localeProperties = (0, generaltranslation_1.getLocaleProperties)(locale);
43
+ return `Translation completed for ${chalk_1.default.green(localeProperties.name)} (${chalk_1.default.green(localeProperties.code)})`;
44
+ }),
45
+ ];
46
+ spinner.suffixText = newSuffixText.join('\n');
47
+ }
48
+ if (locales.every((locale) => availableLocales.includes(locale))) {
49
+ return true;
50
+ }
51
+ }
52
+ return false;
53
+ }
54
+ catch (error) {
55
+ return false;
56
+ }
57
+ });
58
+ // Calculate time until next 5-second interval since startTime
59
+ const msUntilNextInterval = Math.max(0, 5000 - ((Date.now() - startTime) % 5000));
60
+ // Do first check immediately
61
+ const initialCheck = yield checkDeployment();
62
+ if (initialCheck) {
63
+ spinner.succeed(chalk_1.default.green('All translations are live!'));
64
+ return true;
65
+ }
66
+ return new Promise((resolve) => {
67
+ let intervalCheck;
68
+ // Start the interval aligned with the original request time
69
+ setTimeout(() => {
70
+ intervalCheck = setInterval(() => __awaiter(void 0, void 0, void 0, function* () {
71
+ const isDeployed = yield checkDeployment();
72
+ const elapsed = Date.now() - startTime;
73
+ if (isDeployed || elapsed >= timeoutDuration) {
74
+ process.stdout.write('\n');
75
+ clearInterval(intervalCheck);
76
+ if (isDeployed) {
77
+ spinner.succeed(chalk_1.default.green('All translations are live!'));
78
+ resolve(true);
79
+ }
80
+ else {
81
+ spinner.fail(chalk_1.default.red('Timed out waiting for translations'));
82
+ resolve(false);
83
+ }
84
+ }
85
+ }), 5000);
86
+ }, msUntilNextInterval);
87
+ });
88
+ });
89
+ exports.waitForUpdates = waitForUpdates;
@@ -0,0 +1,3 @@
1
+ export declare class BaseCLI {
2
+ constructor();
3
+ }
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BaseCLI = void 0;
4
+ // packages/gt-cli-core/src/BaseCLI.ts
5
+ const commander_1 = require("commander");
6
+ class BaseCLI {
7
+ constructor() {
8
+ commander_1.program.parse();
9
+ }
10
+ }
11
+ exports.BaseCLI = BaseCLI;
@@ -0,0 +1,18 @@
1
+ import { WrapOptions, Options, Updates, SetupOptions, SupportedFrameworks } from 'gt-react-cli/types';
2
+ import { ReactCLI } from './react';
3
+ export declare class NextCLI extends ReactCLI {
4
+ constructor();
5
+ protected scanForContent(options: WrapOptions, framework: SupportedFrameworks): Promise<{
6
+ errors: string[];
7
+ filesUpdated: string[];
8
+ warnings: string[];
9
+ }>;
10
+ protected createDictionaryUpdates(options: Options & {
11
+ dictionary: string;
12
+ }, esbuildConfig: any): Promise<Updates>;
13
+ protected createInlineUpdates(options: Options): Promise<{
14
+ updates: Updates;
15
+ errors: string[];
16
+ }>;
17
+ protected handleSetupCommand(options: SetupOptions): Promise<void>;
18
+ }
@@ -0,0 +1,162 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.NextCLI = void 0;
16
+ const console_1 = require("gt-react-cli/console/console");
17
+ const chalk_1 = __importDefault(require("chalk"));
18
+ const prompts_1 = require("@inquirer/prompts");
19
+ const setupConfig_1 = __importDefault(require("gt-react-cli/fs/config/setupConfig"));
20
+ const postProcess_1 = require("gt-react-cli/hooks/postProcess");
21
+ const findFilepath_1 = __importDefault(require("gt-react-cli/fs/findFilepath"));
22
+ const scanForContent_1 = __importDefault(require("../next/parse/scanForContent"));
23
+ const createDictionaryUpdates_1 = __importDefault(require("gt-react-cli/updates/createDictionaryUpdates"));
24
+ const createInlineUpdates_1 = __importDefault(require("gt-react-cli/updates/createInlineUpdates"));
25
+ const handleInitGT_1 = __importDefault(require("../next/parse/handleInitGT"));
26
+ const react_1 = require("./react");
27
+ const pkg = 'gt-next';
28
+ class NextCLI extends react_1.ReactCLI {
29
+ constructor() {
30
+ super();
31
+ this.setupTranslateCommand();
32
+ this.setupSetupCommand();
33
+ this.setupScanCommand();
34
+ this.setupGenerateSourceCommand();
35
+ }
36
+ scanForContent(options, framework) {
37
+ return (0, scanForContent_1.default)(options, pkg, framework);
38
+ }
39
+ createDictionaryUpdates(options, esbuildConfig) {
40
+ return (0, createDictionaryUpdates_1.default)(options, esbuildConfig);
41
+ }
42
+ createInlineUpdates(options) {
43
+ return (0, createInlineUpdates_1.default)(options, pkg);
44
+ }
45
+ handleSetupCommand(options) {
46
+ return __awaiter(this, void 0, void 0, function* () {
47
+ (0, console_1.displayAsciiTitle)();
48
+ (0, console_1.displayInitializingText)();
49
+ // Ask user for confirmation using inquirer
50
+ const answer = yield (0, prompts_1.select)({
51
+ message: chalk_1.default.yellow(`This operation will prepare your project for internationalization.
52
+ Make sure you have committed or stashed any changes.
53
+ Do you want to continue?`),
54
+ choices: [
55
+ { value: true, name: 'Yes' },
56
+ { value: false, name: 'No' },
57
+ ],
58
+ default: true,
59
+ });
60
+ if (!answer) {
61
+ console.log(chalk_1.default.gray('\nOperation cancelled.'));
62
+ process.exit(0);
63
+ }
64
+ const routerType = yield (0, prompts_1.select)({
65
+ message: 'Are you using the Next.js App router or the Pages router?',
66
+ choices: [
67
+ { value: 'app', name: 'App Router' },
68
+ { value: 'pages', name: 'Pages Router' },
69
+ ],
70
+ default: 'app',
71
+ });
72
+ if (routerType === 'pages') {
73
+ console.log(chalk_1.default.red('\nPlease use gt-react and gt-react-cli instead. gt-next is currently not supported for the Pages router.'));
74
+ process.exit(0);
75
+ }
76
+ const addGTProvider = yield (0, prompts_1.select)({
77
+ message: 'Do you want the setup tool to automatically add the GTProvider component?',
78
+ choices: [
79
+ { value: true, name: 'Yes' },
80
+ { value: false, name: 'No' },
81
+ ],
82
+ default: true,
83
+ });
84
+ // Check if they have a next.config.js file
85
+ const nextConfigPath = (0, findFilepath_1.default)([
86
+ './next.config.js',
87
+ './next.config.ts',
88
+ './next.config.mjs',
89
+ './next.config.mts',
90
+ ]);
91
+ if (!nextConfigPath) {
92
+ console.log(chalk_1.default.red('No next.config.js file found.'));
93
+ process.exit(0);
94
+ }
95
+ const addWithGTConfig = yield (0, prompts_1.select)({
96
+ message: `Do you want to automatically add withGTConfig() to your ${nextConfigPath}?`,
97
+ choices: [
98
+ { value: true, name: 'Yes' },
99
+ { value: false, name: 'No' },
100
+ ],
101
+ default: true,
102
+ });
103
+ const includeTId = yield (0, prompts_1.select)({
104
+ message: 'Do you want to include an unique id for each <T> tag?',
105
+ choices: [
106
+ { value: true, name: 'Yes' },
107
+ { value: false, name: 'No' },
108
+ ],
109
+ default: true,
110
+ });
111
+ // ----- Create a starter gt.config.json file -----
112
+ if (!options.config)
113
+ (0, setupConfig_1.default)('gt.config.json', process.env.GT_PROJECT_ID, '');
114
+ // ----- //
115
+ const mergeOptions = Object.assign(Object.assign({}, options), { disableIds: !includeTId, disableFormatting: true, addGTProvider });
116
+ // Wrap all JSX elements in the src directory with a <T> tag, with unique ids
117
+ const { errors, filesUpdated, warnings } = yield this.scanForContent(mergeOptions, 'next-app');
118
+ if (addWithGTConfig) {
119
+ // Add the withGTConfig() function to the next.config.js file
120
+ const { errors: initGTErrors, filesUpdated: initGTFilesUpdated } = yield (0, handleInitGT_1.default)(nextConfigPath);
121
+ // merge errors and files
122
+ errors.push(...initGTErrors);
123
+ filesUpdated.push(...initGTFilesUpdated);
124
+ }
125
+ if (errors.length > 0) {
126
+ console.log(chalk_1.default.red('\n✗ Failed to write files:\n'));
127
+ console.log(errors.join('\n'));
128
+ }
129
+ console.log(chalk_1.default.green(`\nSuccess! Added <T> tags and updated ${chalk_1.default.bold(filesUpdated.length)} files:\n`));
130
+ if (filesUpdated.length > 0) {
131
+ console.log(filesUpdated.map((file) => `${chalk_1.default.green('-')} ${file}`).join('\n'));
132
+ console.log();
133
+ console.log(chalk_1.default.green('Please verify the changes before committing.'));
134
+ }
135
+ if (warnings.length > 0) {
136
+ console.log(chalk_1.default.yellow('\nWarnings encountered:'));
137
+ console.log(warnings.map((warning) => `${chalk_1.default.yellow('-')} ${warning}`).join('\n'));
138
+ }
139
+ // Stage only the modified files
140
+ // const { execSync } = require('child_process');
141
+ // for (const file of filesUpdated) {
142
+ // await execSync(`git add "${file}"`);
143
+ // }
144
+ const formatter = yield (0, postProcess_1.detectFormatter)();
145
+ if (!formatter || filesUpdated.length === 0) {
146
+ return;
147
+ }
148
+ const applyFormatting = yield (0, prompts_1.select)({
149
+ message: `Would you like to auto-format the modified files? ${chalk_1.default.gray(`(${formatter})`)}`,
150
+ choices: [
151
+ { value: true, name: 'Yes' },
152
+ { value: false, name: 'No' },
153
+ ],
154
+ default: true,
155
+ });
156
+ // Format updated files if formatters are available
157
+ if (applyFormatting)
158
+ yield (0, postProcess_1.formatFiles)(filesUpdated, formatter);
159
+ });
160
+ }
161
+ }
162
+ exports.NextCLI = NextCLI;
@@ -0,0 +1,29 @@
1
+ import { Options, SetupOptions, SupportedFrameworks, Updates, WrapOptions, GenerateSourceOptions } from '../types';
2
+ import { BaseCLI } from './base';
3
+ export declare class ReactCLI extends BaseCLI {
4
+ constructor();
5
+ protected scanForContent(options: WrapOptions, framework: SupportedFrameworks): Promise<{
6
+ errors: string[];
7
+ filesUpdated: string[];
8
+ warnings: string[];
9
+ }>;
10
+ protected createDictionaryUpdates(options: Options & {
11
+ dictionary: string;
12
+ }, esbuildConfig: any): Promise<Updates>;
13
+ protected createInlineUpdates(options: Options): Promise<{
14
+ updates: Updates;
15
+ errors: string[];
16
+ }>;
17
+ protected setupTranslateCommand(): void;
18
+ protected setupGenerateSourceCommand(): void;
19
+ protected setupSetupCommand(): void;
20
+ protected setupScanCommand(): void;
21
+ protected handleGenerateSourceCommand(options: GenerateSourceOptions): Promise<void>;
22
+ protected handleScanCommand(options: WrapOptions): Promise<void>;
23
+ protected handleSetupCommand(options: SetupOptions): Promise<void>;
24
+ protected handleTranslateCommand(initOptions: Options): Promise<void>;
25
+ protected createUpdates(options: Options | GenerateSourceOptions): Promise<{
26
+ updates: Updates;
27
+ errors: string[];
28
+ }>;
29
+ }