gtx-cli 1.2.20 → 1.2.21

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 CHANGED
@@ -1,5 +1,11 @@
1
1
  # gtx-cli
2
2
 
3
+ ## 1.2.21
4
+
5
+ ### Patch Changes
6
+
7
+ - [#324](https://github.com/generaltranslation/gt/pull/324) [`34a8c97`](https://github.com/generaltranslation/gt/commit/34a8c97a9d4c9efb3b441eecf0f7ea77ccc1ad7a) Thanks [@brian-lou](https://github.com/brian-lou)! - Add support for passing useGT and getGT function callback into other functions
8
+
3
9
  ## 1.2.20
4
10
 
5
11
  ### Patch Changes
@@ -32,6 +32,7 @@ exports.warnTemplateLiteral = warnTemplateLiteral;
32
32
  exports.warnTernary = warnTernary;
33
33
  const prompts_1 = require("@clack/prompts");
34
34
  const chalk_1 = __importDefault(require("chalk"));
35
+ const packageJson_1 = require("../utils/packageJson");
35
36
  // Basic logging functions
36
37
  function logInfo(message) {
37
38
  prompts_1.log.info(message);
@@ -81,7 +82,10 @@ Y8, 88 88
81
82
  \`"Y88888P" 88 `));
82
83
  }
83
84
  function displayInitializingText() {
84
- console.log(`\n${chalk_1.default.bold.blue('General Translation, Inc.')}\n${chalk_1.default.gray('https://generaltranslation.com/docs')}\n`);
85
+ const version = (0, packageJson_1.getCLIVersion)();
86
+ console.log(`\n${chalk_1.default.bold.blue('General Translation, Inc.')}
87
+ ${chalk_1.default.gray('https://generaltranslation.com/docs')}
88
+ ${chalk_1.default.gray(`CLI Version: ${version}\n`)}`);
85
89
  }
86
90
  function displayProjectId(projectId) {
87
91
  logMessage(chalk_1.default.gray(`Project ID: ${chalk_1.default.bold(projectId)}`));
@@ -0,0 +1 @@
1
+ export declare function fromPackageRoot(relative: string): string;
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.fromPackageRoot = fromPackageRoot;
7
+ const node_path_1 = __importDefault(require("node:path"));
8
+ function fromPackageRoot(relative) {
9
+ return node_path_1.default.resolve(__dirname, `../../`, relative);
10
+ }
@@ -40,7 +40,7 @@ function addGTIdentifierToSyntaxTree(tree, startingIndex = 0) {
40
40
  key: (0, getVariableName_1.getVariableName)({ ...props, 'data-_gt': generaltranslation }, 'datetime'),
41
41
  };
42
42
  }
43
- else if (type === "" || type === "React.Fragment") {
43
+ else if (type === '' || type === 'React.Fragment') {
44
44
  generaltranslation.transformation = 'fragment';
45
45
  }
46
46
  if (type === 'Plural') {
@@ -128,7 +128,9 @@ function buildJSXTree(importAliases, node, unwrappedExpressions, updates, errors
128
128
  if (elementIsVariable) {
129
129
  parseJSXElement(importAliases, element, updates, errors, file);
130
130
  return {
131
- type: componentType,
131
+ // if componentType is undefined, use typeName
132
+ // Basically, if componentType is not a GT component, use typeName such as <div>
133
+ type: componentType ?? typeName,
132
134
  props,
133
135
  };
134
136
  }
@@ -142,7 +144,9 @@ function buildJSXTree(importAliases, node, unwrappedExpressions, updates, errors
142
144
  props.children = children;
143
145
  }
144
146
  return {
145
- type: componentType,
147
+ // if componentType is undefined, use typeName
148
+ // Basically, if componentType is not a GT component, use typeName such as <div>
149
+ type: componentType ?? typeName,
146
150
  props,
147
151
  };
148
152
  }
@@ -2,11 +2,16 @@ import { NodePath } from '@babel/traverse';
2
2
  import { Updates } from '../../../types';
3
3
  export declare const attributes: string[];
4
4
  /**
5
- * For the following example code:
6
- * const t = useGT();
7
- * t('string to translate', { id: 'exampleId', context: 'exampleContext' });
5
+ * Main entry point for parsing translation strings from useGT() and getGT() calls.
8
6
  *
9
- * This function will find all call expressions of useGT(), then find all call expressions
10
- * of the subsequent tx() calls, and append the content and metadata to the updates array.
7
+ * Supports complex patterns including:
8
+ * 1. Direct calls: const t = useGT(); t('hello');
9
+ * 2. Function parameters: const t = useGT(); getInfo(t); where getInfo uses t() internally
10
+ * 3. Cross-file function calls: imported functions that receive t as a parameter
11
+ *
12
+ * Example flow:
13
+ * - const t = useGT();
14
+ * - const { home } = getInfo(t); // getInfo is imported from './constants'
15
+ * - This will parse constants.ts to find t() calls within getInfo function
11
16
  */
12
17
  export declare function parseStrings(importName: string, path: NodePath, updates: Updates, errors: string[], file: string): void;
@@ -43,17 +43,227 @@ const t = __importStar(require("@babel/types"));
43
43
  const evaluateJsx_1 = require("../evaluateJsx");
44
44
  const console_1 = require("../../../console");
45
45
  const generator_1 = __importDefault(require("@babel/generator"));
46
+ const node_fs_1 = __importDefault(require("node:fs"));
47
+ const node_path_1 = __importDefault(require("node:path"));
48
+ const parser_1 = require("@babel/parser");
49
+ const traverse_1 = __importDefault(require("@babel/traverse"));
50
+ const tsconfig_paths_1 = require("tsconfig-paths");
51
+ const resolve = __importStar(require("resolve"));
46
52
  exports.attributes = ['id', 'context'];
47
53
  /**
48
- * For the following example code:
49
- * const t = useGT();
50
- * t('string to translate', { id: 'exampleId', context: 'exampleContext' });
54
+ * Processes a single translation function call (e.g., t('hello world', { id: 'greeting' })).
55
+ * Extracts the translatable string content and metadata, then adds it to the updates array.
51
56
  *
52
- * This function will find all call expressions of useGT(), then find all call expressions
53
- * of the subsequent tx() calls, and append the content and metadata to the updates array.
57
+ * Handles:
58
+ * - String literals: t('hello')
59
+ * - Template literals without expressions: t(`hello`)
60
+ * - Metadata extraction from options object
61
+ * - Error reporting for non-static expressions and template literals with expressions
62
+ */
63
+ function processTranslationCall(tPath, updates, errors, file) {
64
+ if (tPath.parent.type === 'CallExpression' &&
65
+ tPath.parent.arguments.length > 0) {
66
+ const arg = tPath.parent.arguments[0];
67
+ if (arg.type === 'StringLiteral' ||
68
+ (t.isTemplateLiteral(arg) && arg.expressions.length === 0)) {
69
+ const source = arg.type === 'StringLiteral' ? arg.value : arg.quasis[0].value.raw;
70
+ // split the string into content (same as runtime behavior)
71
+ const content = (0, generaltranslation_1.splitStringToContent)(source);
72
+ // get metadata and id from options
73
+ const options = tPath.parent.arguments[1];
74
+ const metadata = {};
75
+ if (options && options.type === 'ObjectExpression') {
76
+ options.properties.forEach((prop) => {
77
+ if (prop.type === 'ObjectProperty' &&
78
+ prop.key.type === 'Identifier') {
79
+ const attribute = prop.key.name;
80
+ if (exports.attributes.includes(attribute) && t.isExpression(prop.value)) {
81
+ const result = (0, evaluateJsx_1.isStaticExpression)(prop.value);
82
+ if (!result.isStatic) {
83
+ errors.push((0, console_1.warnNonStaticExpressionSync)(file, attribute, (0, generator_1.default)(prop.value).code, `${prop.loc?.start?.line}:${prop.loc?.start?.column}`));
84
+ }
85
+ if (result.isStatic && result.value) {
86
+ metadata[attribute] = result.value;
87
+ }
88
+ }
89
+ }
90
+ });
91
+ }
92
+ updates.push({
93
+ dataFormat: 'JSX',
94
+ source: content,
95
+ metadata,
96
+ });
97
+ }
98
+ else if (t.isTemplateLiteral(arg)) {
99
+ // warn if template literal
100
+ errors.push((0, console_1.warnTemplateLiteralSync)(file, (0, generator_1.default)(arg).code, `${arg.loc?.start?.line}:${arg.loc?.start?.column}`));
101
+ }
102
+ else {
103
+ errors.push((0, console_1.warnNonStringSync)(file, (0, generator_1.default)(arg).code, `${arg.loc?.start?.line}:${arg.loc?.start?.column}`));
104
+ }
105
+ }
106
+ }
107
+ /**
108
+ * Finds all usages of a function parameter within a function's scope and processes
109
+ * any translation calls made with that parameter.
110
+ *
111
+ * Example: In function getInfo(t) { return t('hello'); }, this finds the t('hello') call.
112
+ */
113
+ function findFunctionParameterUsage(functionPath, parameterName, updates, errors, file) {
114
+ // Look for the function body and find all usages of the parameter
115
+ if (functionPath.isFunction()) {
116
+ const functionScope = functionPath.scope;
117
+ const binding = functionScope.bindings[parameterName];
118
+ if (binding) {
119
+ binding.referencePaths.forEach((refPath) => {
120
+ processTranslationCall(refPath, updates, errors, file);
121
+ });
122
+ }
123
+ }
124
+ }
125
+ /**
126
+ * Resolves import paths to absolute file paths using battle-tested libraries.
127
+ * Handles relative paths, TypeScript paths, and node module resolution.
128
+ *
129
+ * Examples:
130
+ * - './constants' -> '/full/path/to/constants.ts'
131
+ * - '@/components/ui/button' -> '/full/path/to/src/components/ui/button.tsx'
132
+ * - '@shared/utils' -> '/full/path/to/packages/utils/index.ts'
133
+ */
134
+ function resolveImportPath(currentFile, importPath) {
135
+ const basedir = node_path_1.default.dirname(currentFile);
136
+ const extensions = ['.tsx', '.ts', '.jsx', '.js'];
137
+ // 1. Try tsconfig-paths resolution first (handles TypeScript path mapping)
138
+ const tsConfigResult = (0, tsconfig_paths_1.loadConfig)(basedir);
139
+ if (tsConfigResult.resultType === 'success') {
140
+ const matchPath = (0, tsconfig_paths_1.createMatchPath)(tsConfigResult.absoluteBaseUrl, tsConfigResult.paths, ['main', 'module', 'browser']);
141
+ // First try without any extension
142
+ let tsResolved = matchPath(importPath);
143
+ if (tsResolved && node_fs_1.default.existsSync(tsResolved)) {
144
+ return tsResolved;
145
+ }
146
+ // Then try with each extension
147
+ for (const ext of extensions) {
148
+ tsResolved = matchPath(importPath + ext);
149
+ if (tsResolved && node_fs_1.default.existsSync(tsResolved)) {
150
+ return tsResolved;
151
+ }
152
+ // Also try the resolved path with extension
153
+ tsResolved = matchPath(importPath);
154
+ if (tsResolved) {
155
+ const resolvedWithExt = tsResolved + ext;
156
+ if (node_fs_1.default.existsSync(resolvedWithExt)) {
157
+ return resolvedWithExt;
158
+ }
159
+ }
160
+ }
161
+ }
162
+ // 2. Fallback to Node.js resolution (handles relative paths and node_modules)
163
+ try {
164
+ return resolve.sync(importPath, { basedir, extensions });
165
+ }
166
+ catch {
167
+ return null;
168
+ }
169
+ }
170
+ /**
171
+ * Searches for a specific function in a file and analyzes how a particular parameter
172
+ * (at argIndex position) is used within that function for translation calls.
173
+ *
174
+ * Handles multiple function declaration patterns:
175
+ * - function getInfo(t) { ... }
176
+ * - export function getInfo(t) { ... }
177
+ * - const getInfo = (t) => { ... }
178
+ */
179
+ function findFunctionInFile(filePath, functionName, argIndex, updates, errors) {
180
+ try {
181
+ const code = node_fs_1.default.readFileSync(filePath, 'utf8');
182
+ const ast = (0, parser_1.parse)(code, {
183
+ sourceType: 'module',
184
+ plugins: ['jsx', 'typescript'],
185
+ });
186
+ (0, traverse_1.default)(ast, {
187
+ // Handle function declarations: function getInfo(t) { ... }
188
+ FunctionDeclaration(path) {
189
+ if (path.node.id?.name === functionName &&
190
+ path.node.params.length > argIndex) {
191
+ const param = path.node.params[argIndex];
192
+ if (t.isIdentifier(param)) {
193
+ findFunctionParameterUsage(path, param.name, updates, errors, filePath);
194
+ }
195
+ }
196
+ },
197
+ // Handle exported function declarations: export function getInfo(t) { ... }
198
+ ExportNamedDeclaration(path) {
199
+ if (path.node.declaration &&
200
+ t.isFunctionDeclaration(path.node.declaration)) {
201
+ const func = path.node.declaration;
202
+ if (func.id?.name === functionName && func.params.length > argIndex) {
203
+ const param = func.params[argIndex];
204
+ if (t.isIdentifier(param)) {
205
+ findFunctionParameterUsage(path.get('declaration'), param.name, updates, errors, filePath);
206
+ }
207
+ }
208
+ }
209
+ },
210
+ // Handle variable declarations: const getInfo = (t) => { ... }
211
+ VariableDeclarator(path) {
212
+ if (t.isIdentifier(path.node.id) &&
213
+ path.node.id.name === functionName &&
214
+ path.node.init &&
215
+ (t.isArrowFunctionExpression(path.node.init) ||
216
+ t.isFunctionExpression(path.node.init)) &&
217
+ path.node.init.params.length > argIndex) {
218
+ const param = path.node.init.params[argIndex];
219
+ if (t.isIdentifier(param)) {
220
+ const initPath = path.get('init');
221
+ findFunctionParameterUsage(initPath, param.name, updates, errors, filePath);
222
+ }
223
+ }
224
+ },
225
+ });
226
+ }
227
+ catch {
228
+ // Silently skip files that can't be parsed or accessed
229
+ }
230
+ }
231
+ /**
232
+ * Main entry point for parsing translation strings from useGT() and getGT() calls.
233
+ *
234
+ * Supports complex patterns including:
235
+ * 1. Direct calls: const t = useGT(); t('hello');
236
+ * 2. Function parameters: const t = useGT(); getInfo(t); where getInfo uses t() internally
237
+ * 3. Cross-file function calls: imported functions that receive t as a parameter
238
+ *
239
+ * Example flow:
240
+ * - const t = useGT();
241
+ * - const { home } = getInfo(t); // getInfo is imported from './constants'
242
+ * - This will parse constants.ts to find t() calls within getInfo function
54
243
  */
55
244
  function parseStrings(importName, path, updates, errors, file) {
56
- path.scope.bindings[importName]?.referencePaths.forEach((refPath) => {
245
+ // First, collect all imports in this file to track cross-file function calls
246
+ const importMap = new Map(); // functionName -> importPath
247
+ path.scope.getProgramParent().path.traverse({
248
+ ImportDeclaration(importPath) {
249
+ if (t.isStringLiteral(importPath.node.source)) {
250
+ const importSource = importPath.node.source.value;
251
+ importPath.node.specifiers.forEach((spec) => {
252
+ if (t.isImportSpecifier(spec) &&
253
+ t.isIdentifier(spec.imported) &&
254
+ t.isIdentifier(spec.local)) {
255
+ importMap.set(spec.local.name, importSource);
256
+ }
257
+ else if (t.isImportDefaultSpecifier(spec) &&
258
+ t.isIdentifier(spec.local)) {
259
+ importMap.set(spec.local.name, importSource);
260
+ }
261
+ });
262
+ }
263
+ },
264
+ });
265
+ const referencePaths = path.scope.bindings[importName]?.referencePaths || [];
266
+ for (const refPath of referencePaths) {
57
267
  // Find call expressions of useGT() / await getGT()
58
268
  const callExpr = refPath.findParent((p) => p.isCallExpression());
59
269
  if (callExpr) {
@@ -68,54 +278,44 @@ function parseStrings(importName, path, updates, errors, file) {
68
278
  const tFuncName = effectiveParent.node.id.name;
69
279
  // Get the scope from the variable declaration
70
280
  const variableScope = effectiveParent.scope;
71
- variableScope.bindings[tFuncName]?.referencePaths.forEach((tPath) => {
281
+ const tReferencePaths = variableScope.bindings[tFuncName]?.referencePaths || [];
282
+ for (const tPath of tReferencePaths) {
283
+ // Check if this is a direct call to the translation function
72
284
  if (tPath.parent.type === 'CallExpression' &&
73
- tPath.parent.arguments.length > 0) {
74
- const arg = tPath.parent.arguments[0];
75
- if (arg.type === 'StringLiteral' ||
76
- (t.isTemplateLiteral(arg) && arg.expressions.length === 0)) {
77
- const source = arg.type === 'StringLiteral'
78
- ? arg.value
79
- : arg.quasis[0].value.raw;
80
- // split the string into content (same as runtime behavior)
81
- const content = (0, generaltranslation_1.splitStringToContent)(source);
82
- // get metadata and id from options
83
- const options = tPath.parent.arguments[1];
84
- const metadata = {};
85
- if (options && options.type === 'ObjectExpression') {
86
- options.properties.forEach((prop) => {
87
- if (prop.type === 'ObjectProperty' &&
88
- prop.key.type === 'Identifier') {
89
- const attribute = prop.key.name;
90
- if (exports.attributes.includes(attribute) &&
91
- t.isExpression(prop.value)) {
92
- const result = (0, evaluateJsx_1.isStaticExpression)(prop.value);
93
- if (!result.isStatic) {
94
- errors.push((0, console_1.warnNonStaticExpressionSync)(file, attribute, (0, generator_1.default)(prop.value).code, `${prop.loc?.start?.line}:${prop.loc?.start?.column}`));
95
- }
96
- if (result.isStatic && result.value) {
97
- metadata[attribute] = result.value;
98
- }
99
- }
100
- }
101
- });
285
+ tPath.parent.callee === tPath.node) {
286
+ processTranslationCall(tPath, updates, errors, file);
287
+ }
288
+ // Check if this is being passed as an argument to another function
289
+ else if (tPath.parent.type === 'CallExpression' &&
290
+ t.isExpression(tPath.node) &&
291
+ tPath.parent.arguments.includes(tPath.node)) {
292
+ // Find which parameter position this is
293
+ const argIndex = tPath.parent.arguments.indexOf(tPath.node);
294
+ // Try to find the function definition being called
295
+ const callee = tPath.parent.callee;
296
+ if (t.isIdentifier(callee)) {
297
+ // Look for function declarations or function expressions with this name
298
+ const calleeBinding = tPath.scope.getBinding(callee.name);
299
+ if (calleeBinding && calleeBinding.path.isFunction()) {
300
+ const functionPath = calleeBinding.path;
301
+ const params = functionPath.node.params;
302
+ if (params[argIndex] && t.isIdentifier(params[argIndex])) {
303
+ const paramName = params[argIndex].name;
304
+ findFunctionParameterUsage(functionPath, paramName, updates, errors, file);
305
+ }
306
+ }
307
+ // If not found locally, check if it's an imported function
308
+ else if (importMap.has(callee.name)) {
309
+ const importPath = importMap.get(callee.name);
310
+ const resolvedPath = resolveImportPath(file, importPath);
311
+ if (resolvedPath) {
312
+ findFunctionInFile(resolvedPath, callee.name, argIndex, updates, errors);
313
+ }
102
314
  }
103
- updates.push({
104
- dataFormat: 'JSX',
105
- source: content,
106
- metadata,
107
- });
108
- }
109
- else if (t.isTemplateLiteral(arg)) {
110
- // warn if template literal
111
- errors.push((0, console_1.warnTemplateLiteralSync)(file, (0, generator_1.default)(arg).code, `${arg.loc?.start?.line}:${arg.loc?.start?.column}`));
112
- }
113
- else {
114
- errors.push((0, console_1.warnNonStringSync)(file, (0, generator_1.default)(arg).code, `${arg.loc?.start?.line}:${arg.loc?.start?.column}`));
115
315
  }
116
316
  }
117
- });
317
+ }
118
318
  }
119
319
  }
120
- });
320
+ }
121
321
  }
@@ -72,14 +72,15 @@ async function createInlineUpdates(options, pkg) {
72
72
  'Plural',
73
73
  ];
74
74
  const importAliases = {};
75
- // handle imports & alias & handle string functions
75
+ // First pass: collect imports and process translation functions
76
+ const translationPaths = [];
76
77
  (0, traverse_1.default)(ast, {
77
78
  ImportDeclaration(path) {
78
79
  if (path.node.source.value.startsWith(pkg)) {
79
80
  const importName = (0, parseAst_1.extractImportName)(path.node, pkg, translationFuncs);
80
81
  for (const name of importName) {
81
82
  if (name.original === 'useGT' || name.original === 'getGT') {
82
- (0, parseStringFunction_1.parseStrings)(name.local, path, updates, errors, file);
83
+ translationPaths.push({ name: name.local, path });
83
84
  }
84
85
  else {
85
86
  importAliases[name.local] = name.original;
@@ -102,7 +103,7 @@ async function createInlineUpdates(options, pkg) {
102
103
  const importName = (0, parseAst_1.extractImportName)(parentPath.node, pkg, translationFuncs);
103
104
  for (const name of importName) {
104
105
  if (name.original === 'useGT' || name.original === 'getGT') {
105
- (0, parseStringFunction_1.parseStrings)(name.local, parentPath, updates, errors, file);
106
+ translationPaths.push({ name: name.local, path: parentPath });
106
107
  }
107
108
  else {
108
109
  importAliases[name.local] = name.original;
@@ -113,6 +114,10 @@ async function createInlineUpdates(options, pkg) {
113
114
  }
114
115
  },
115
116
  });
117
+ // Process translation functions asynchronously
118
+ for (const { name, path } of translationPaths) {
119
+ (0, parseStringFunction_1.parseStrings)(name, path, updates, errors, file);
120
+ }
116
121
  // Parse <T> components
117
122
  (0, traverse_1.default)(ast, {
118
123
  JSXElement(path) {
@@ -1,5 +1,6 @@
1
1
  export declare function searchForPackageJson(): Promise<Record<string, any> | null>;
2
2
  export declare function getPackageJson(): Promise<Record<string, any>>;
3
+ export declare function getCLIVersion(): string;
3
4
  export declare function updatePackageJson(packageJson: Record<string, any>): Promise<void>;
4
5
  export declare function isPackageInstalled(packageName: string, packageJson: Record<string, any>, asDevDependency?: boolean, checkBoth?: boolean): boolean;
5
6
  export declare function getPackageVersion(packageName: string, packageJson: Record<string, any>): string | undefined;
@@ -5,6 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.searchForPackageJson = searchForPackageJson;
7
7
  exports.getPackageJson = getPackageJson;
8
+ exports.getCLIVersion = getCLIVersion;
8
9
  exports.updatePackageJson = updatePackageJson;
9
10
  exports.isPackageInstalled = isPackageInstalled;
10
11
  exports.getPackageVersion = getPackageVersion;
@@ -13,6 +14,7 @@ const chalk_1 = __importDefault(require("chalk"));
13
14
  const node_path_1 = __importDefault(require("node:path"));
14
15
  const node_fs_1 = __importDefault(require("node:fs"));
15
16
  const console_2 = require("../console");
17
+ const getPackageResource_1 = require("../fs/getPackageResource");
16
18
  // search for package.json such that we can run init in non-js projects
17
19
  async function searchForPackageJson() {
18
20
  // Get the current working directory (where the CLI is being run)
@@ -45,6 +47,18 @@ async function getPackageJson() {
45
47
  process.exit(1);
46
48
  }
47
49
  }
50
+ function getCLIVersion() {
51
+ const packageJsonPath = (0, getPackageResource_1.fromPackageRoot)('package.json');
52
+ if (!node_fs_1.default.existsSync(packageJsonPath)) {
53
+ return 'unknown';
54
+ }
55
+ try {
56
+ return JSON.parse(node_fs_1.default.readFileSync(packageJsonPath, 'utf8')).version;
57
+ }
58
+ catch (error) {
59
+ return 'unknown';
60
+ }
61
+ }
48
62
  async function updatePackageJson(packageJson) {
49
63
  try {
50
64
  await node_fs_1.default.promises.writeFile(node_path_1.default.join(process.cwd(), 'package.json'), JSON.stringify(packageJson, null, 2));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gtx-cli",
3
- "version": "1.2.20",
3
+ "version": "1.2.21",
4
4
  "main": "dist/index.js",
5
5
  "bin": "dist/main.js",
6
6
  "files": [
@@ -81,7 +81,9 @@
81
81
  "form-data": "^4.0.2",
82
82
  "generaltranslation": "^6.2.9",
83
83
  "open": "^10.1.1",
84
- "ora": "^8.2.0"
84
+ "ora": "^8.2.0",
85
+ "resolve": "^1.22.10",
86
+ "tsconfig-paths": "^4.2.0"
85
87
  },
86
88
  "devDependencies": {
87
89
  "@biomejs/biome": "1.9.4",
@@ -91,6 +93,7 @@
91
93
  "@types/mock-require": "^2.0.3",
92
94
  "@types/node": "^22.5.1",
93
95
  "@types/react": "^18.3.4",
96
+ "@types/resolve": "^1.20.2",
94
97
  "eslint": "^9.20.0",
95
98
  "esm": "^3.2.25",
96
99
  "prettier": "^3.4.2",