gtx-cli 2.3.11 → 2.3.12

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
+ ## 2.3.12
4
+
5
+ ### Patch Changes
6
+
7
+ - [#735](https://github.com/generaltranslation/gt/pull/735) [`8e4612e`](https://github.com/generaltranslation/gt/commit/8e4612e0b2c426d64153b6ca460e619fa29cb8e8) Thanks [@ErnestM1234](https://github.com/ErnestM1234)! - fix: auto enable gt compiler in default config
8
+
3
9
  ## 2.3.11
4
10
 
5
11
  ### Patch Changes
@@ -7,6 +7,7 @@ const traverse = traverseModule.default || traverseModule;
7
7
  const generate = generateModule.default || generateModule;
8
8
  import * as t from '@babel/types';
9
9
  import { logError } from '../../console/logging.js';
10
+ import { needsCJS } from '../../utils/parse/needsCJS.js';
10
11
  export async function handleInitGT(filepath, errors, warnings, filesUpdated, packageJson, tsconfigJson) {
11
12
  const code = await fs.promises.readFile(filepath, 'utf8');
12
13
  let ast;
@@ -17,66 +18,14 @@ export async function handleInitGT(filepath, errors, warnings, filesUpdated, pac
17
18
  tokens: true,
18
19
  createParenthesizedExpressions: true,
19
20
  });
20
- // Analyze the actual file content to determine module system
21
- let hasES6Imports = false;
22
- let hasCommonJSRequire = false;
23
- traverse(ast, {
24
- ImportDeclaration() {
25
- hasES6Imports = true;
26
- },
27
- CallExpression(path) {
28
- if (t.isIdentifier(path.node.callee, { name: 'require' })) {
29
- hasCommonJSRequire = true;
30
- }
31
- },
21
+ // Get cjs or esm
22
+ const cjsEnabled = needsCJS({
23
+ ast,
24
+ warnings,
25
+ filepath,
26
+ packageJson,
27
+ tsconfigJson,
32
28
  });
33
- // Determine if we need CommonJS based on actual file content and fallback to config-based logic
34
- let needsCJS = false;
35
- if (hasES6Imports && !hasCommonJSRequire) {
36
- // File uses ES6 imports, so we should use ES6 imports
37
- needsCJS = false;
38
- }
39
- else if (hasCommonJSRequire && !hasES6Imports) {
40
- // File uses CommonJS require, so we should use CommonJS require
41
- needsCJS = true;
42
- }
43
- else if (hasES6Imports && hasCommonJSRequire) {
44
- // Mixed usage - this is unusual but we'll default to ES6 imports
45
- warnings.push(`Mixed ES6 imports and CommonJS require detected in ${filepath}. Defaulting to ES6 imports.`);
46
- needsCJS = false;
47
- }
48
- else {
49
- // No imports/requires found, fall back to configuration-based logic
50
- if (filepath.endsWith('.ts') || filepath.endsWith('.tsx')) {
51
- // For TypeScript files, check tsconfig.json compilerOptions.module
52
- const moduleSetting = tsconfigJson?.compilerOptions?.module;
53
- if (moduleSetting === 'commonjs' || moduleSetting === 'node') {
54
- needsCJS = true;
55
- }
56
- else if (moduleSetting === 'esnext' ||
57
- moduleSetting === 'es2022' ||
58
- moduleSetting === 'es2020' ||
59
- moduleSetting === 'es2015' ||
60
- moduleSetting === 'es6' ||
61
- moduleSetting === 'node16' ||
62
- moduleSetting === 'nodenext') {
63
- needsCJS = false;
64
- }
65
- else {
66
- // Default to ESM for TypeScript files if no module setting is specified
67
- needsCJS = false;
68
- }
69
- }
70
- else if (filepath.endsWith('.js')) {
71
- // For JavaScript files, check package.json type
72
- // If package.json has "type": "module", .js files are treated as ES modules
73
- needsCJS = packageJson?.type !== 'module';
74
- }
75
- else {
76
- // For other file extensions, default to ESM
77
- needsCJS = false;
78
- }
79
- }
80
29
  // Check if withGTConfig or initGT is already imported/required
81
30
  let hasGTConfig = false;
82
31
  let hasInitGT = false;
@@ -145,7 +94,7 @@ export async function handleInitGT(filepath, errors, warnings, filesUpdated, pac
145
94
  if (hasGTConfig || hasInitGT) {
146
95
  return;
147
96
  }
148
- ast.program.body.unshift(needsCJS
97
+ ast.program.body.unshift(cjsEnabled
149
98
  ? t.variableDeclaration('const', [
150
99
  t.variableDeclarator(t.identifier('withGTConfig'), t.memberExpression(t.callExpression(t.identifier('require'), [
151
100
  t.stringLiteral('gt-next/config'),
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Adds the gt compiler plugin to the vite config file
3
+ */
4
+ export declare function addVitePlugin({ errors, warnings, filesUpdated, packageJson, tsconfigJson, }: {
5
+ errors: string[];
6
+ warnings: string[];
7
+ filesUpdated: string[];
8
+ packageJson?: {
9
+ type?: string;
10
+ dependencies?: Record<string, string>;
11
+ devDependencies?: Record<string, string>;
12
+ };
13
+ tsconfigJson?: {
14
+ compilerOptions?: {
15
+ module?: string;
16
+ };
17
+ };
18
+ }): Promise<{
19
+ errors: string[];
20
+ warnings: string[];
21
+ filesUpdated: string[];
22
+ }>;
@@ -0,0 +1,40 @@
1
+ import findFilepath from '../../../fs/findFilepath.js';
2
+ import { logError } from '../../../console/logging.js';
3
+ import { installCompiler } from './installCompiler.js';
4
+ import { updateViteConfig } from './updateViteConfig.js';
5
+ const VITE_CONFIG_PATH_BASE = './vite.config.';
6
+ /**
7
+ * Adds the gt compiler plugin to the vite config file
8
+ */
9
+ export async function addVitePlugin({ errors, warnings, filesUpdated, packageJson, tsconfigJson, }) {
10
+ // Resolve file path
11
+ const viteConfigPath = findFilepath([
12
+ VITE_CONFIG_PATH_BASE + 'js',
13
+ VITE_CONFIG_PATH_BASE + 'ts',
14
+ VITE_CONFIG_PATH_BASE + 'mjs',
15
+ VITE_CONFIG_PATH_BASE + 'mts',
16
+ VITE_CONFIG_PATH_BASE + 'cjs',
17
+ VITE_CONFIG_PATH_BASE + 'cts',
18
+ ]);
19
+ if (!viteConfigPath) {
20
+ logError(`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
+ import { vite as gtCompiler } from '@generaltranslation/compiler';
22
+ export default defineConfig({
23
+ plugins: [gtCompiler()],
24
+ });
25
+ `);
26
+ process.exit(1);
27
+ }
28
+ // Install @generaltranslation/compiler if not installed
29
+ await installCompiler({ packageJson });
30
+ // Update the config file
31
+ await updateViteConfig({
32
+ errors,
33
+ warnings,
34
+ filesUpdated,
35
+ viteConfigPath,
36
+ packageJson,
37
+ tsconfigJson,
38
+ });
39
+ return { errors, warnings, filesUpdated };
40
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Installs @generaltranslation/compiler if not installed
3
+ */
4
+ export declare function installCompiler({ packageJson, }: {
5
+ packageJson?: {
6
+ type?: string;
7
+ };
8
+ }): Promise<void>;
@@ -0,0 +1,22 @@
1
+ import { createSpinner } from '../../../console/logging.js';
2
+ import { installPackage } from '../../../utils/installPackage.js';
3
+ import { isPackageInstalled } from '../../../utils/packageJson.js';
4
+ import { getPackageManager } from '../../../utils/packageManager.js';
5
+ import chalk from 'chalk';
6
+ /**
7
+ * Installs @generaltranslation/compiler if not installed
8
+ */
9
+ export async function installCompiler({ packageJson, }) {
10
+ // Check if installed
11
+ if (isPackageInstalled('@generaltranslation/compiler', packageJson || {})) {
12
+ return;
13
+ }
14
+ // Animation
15
+ const spinner = createSpinner();
16
+ spinner.start(`Installing @generaltranslation/compiler...`);
17
+ // Install
18
+ const packageManager = await getPackageManager();
19
+ await installPackage('@generaltranslation/compiler', packageManager, true);
20
+ // Animation
21
+ spinner.stop(chalk.green('Installed @generaltranslation/compiler.'));
22
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * - Reads the vite config file
3
+ * - Updates the ast to add the gt compiler plugin
4
+ * - Writes the file back to the filesystem
5
+ */
6
+ export declare function updateViteConfig({ errors, warnings, filesUpdated, viteConfigPath, packageJson, tsconfigJson, }: {
7
+ errors: string[];
8
+ warnings: string[];
9
+ filesUpdated: string[];
10
+ viteConfigPath: string;
11
+ packageJson?: {
12
+ type?: string;
13
+ };
14
+ tsconfigJson?: {
15
+ compilerOptions?: {
16
+ module?: string;
17
+ };
18
+ };
19
+ }): Promise<void>;
@@ -0,0 +1,123 @@
1
+ import { createSpinner } from '../../../console/logging.js';
2
+ import { logError } from '../../../console/logging.js';
3
+ import fs from 'node:fs';
4
+ import chalk from 'chalk';
5
+ import generateModule from '@babel/generator';
6
+ import { parse } from '@babel/parser';
7
+ import { needsCJS } from '../../../utils/parse/needsCJS.js';
8
+ import { addCompilerImport } from './utils/addCompilerImport.js';
9
+ import { checkCompilerImport } from './utils/checkCompilerImport.js';
10
+ import { checkPluginInvocation } from './utils/checkPluginInvocation.js';
11
+ import { addPluginInvocation } from './utils/addPluginInvocation.js';
12
+ // Handle CommonJS/ESM interop
13
+ const generate = generateModule.default || generateModule;
14
+ /**
15
+ * - Reads the vite config file
16
+ * - Updates the ast to add the gt compiler plugin
17
+ * - Writes the file back to the filesystem
18
+ */
19
+ export async function updateViteConfig({ errors, warnings, filesUpdated, viteConfigPath, packageJson, tsconfigJson, }) {
20
+ // Animation
21
+ const spinner = createSpinner();
22
+ spinner.start(`Adding gt compiler plugin to ${viteConfigPath}...`);
23
+ // Read the file
24
+ let code;
25
+ try {
26
+ code = await fs.promises.readFile(viteConfigPath, 'utf8');
27
+ }
28
+ catch (error) {
29
+ logError(`Error: Failed to read ${viteConfigPath}: ${error}`);
30
+ process.exit(1);
31
+ return;
32
+ }
33
+ // Update the ast
34
+ let updatedCode, success;
35
+ try {
36
+ ({ updatedCode, success } = await updateViteConfigAst({
37
+ code,
38
+ errors,
39
+ warnings,
40
+ viteConfigPath,
41
+ packageJson,
42
+ tsconfigJson,
43
+ }));
44
+ }
45
+ catch (error) {
46
+ logError(`Error: Failed to update ${viteConfigPath}: ${error}`);
47
+ process.exit(1);
48
+ return;
49
+ }
50
+ // Write the file
51
+ try {
52
+ await fs.promises.writeFile(viteConfigPath, updatedCode);
53
+ filesUpdated.push(viteConfigPath);
54
+ }
55
+ catch (error) {
56
+ logError(`Error: Failed to write ${viteConfigPath}: ${error}`);
57
+ process.exit(1);
58
+ return;
59
+ }
60
+ // Animation
61
+ spinner.stop(success
62
+ ? chalk.green(`Success! Added gt compiler plugin to ${viteConfigPath}`)
63
+ : chalk.red(`Failed to add gt compiler plugin to ${viteConfigPath}. Continuing setup...`));
64
+ }
65
+ /**
66
+ * Orchestrates AST manipulation
67
+ * @param code - The code to update
68
+ * @param errors - The errors to update
69
+ * @param warnings - The warnings to update
70
+ * @param viteConfigPath - The path to the vite config file
71
+ * @param packageJson - The package.json file
72
+ * @param tsconfigJson - The tsconfig.json file
73
+ * @returns
74
+ */
75
+ async function updateViteConfigAst({ code, warnings, viteConfigPath, packageJson, tsconfigJson, }) {
76
+ // Parse the code
77
+ const ast = parse(code, {
78
+ sourceType: 'module',
79
+ plugins: ['jsx', 'typescript'],
80
+ });
81
+ // Get cjs or esm
82
+ const cjsEnabled = needsCJS({
83
+ ast,
84
+ warnings,
85
+ filepath: viteConfigPath,
86
+ packageJson,
87
+ tsconfigJson,
88
+ });
89
+ // Check if the compiler import is already present
90
+ let { hasCompilerImport, alias, namespaces } = checkCompilerImport(ast);
91
+ // Add the import declaration
92
+ if (!hasCompilerImport) {
93
+ addCompilerImport({ ast, cjsEnabled });
94
+ hasCompilerImport = true;
95
+ alias = 'gtCompiler';
96
+ namespaces = [];
97
+ }
98
+ // Check if plugin is already present
99
+ let pluginAlreadyPresent = false;
100
+ if (hasCompilerImport) {
101
+ pluginAlreadyPresent = checkPluginInvocation({ ast, alias, namespaces });
102
+ }
103
+ // Insert plugin invocation
104
+ let success = false;
105
+ if (!pluginAlreadyPresent) {
106
+ success = addPluginInvocation({ ast, alias, namespaces });
107
+ if (!success) {
108
+ warnings.push(`Failed to add gt compiler plugin to ${viteConfigPath}. Please add the plugin manually:
109
+ import { vite as gtCompiler } from '@generaltranslation/compiler';
110
+ export default defineConfig({
111
+ plugins: [gtCompiler()],
112
+ });`);
113
+ }
114
+ }
115
+ // Generate the modified code
116
+ const output = generate(ast, {
117
+ retainLines: true,
118
+ retainFunctionParens: true,
119
+ comments: true,
120
+ compact: 'auto',
121
+ }, code);
122
+ return { updatedCode: output.code, success };
123
+ }
@@ -0,0 +1,9 @@
1
+ import { ParseResult } from '@babel/parser';
2
+ import * as t from '@babel/types';
3
+ /**
4
+ * Given the vite config file ast, inserts the import declaration for the @generaltranslation/compiler package
5
+ */
6
+ export declare function addCompilerImport({ ast, cjsEnabled, }: {
7
+ ast: ParseResult<t.File>;
8
+ cjsEnabled: boolean;
9
+ }): void;
@@ -0,0 +1,34 @@
1
+ import * as t from '@babel/types';
2
+ /**
3
+ * Given the vite config file ast, inserts the import declaration for the @generaltranslation/compiler package
4
+ */
5
+ export function addCompilerImport({ ast, cjsEnabled, }) {
6
+ if (cjsEnabled) {
7
+ handleCjsImport(ast);
8
+ }
9
+ else {
10
+ handleEsmImport(ast);
11
+ }
12
+ }
13
+ /**
14
+ * Adds a CJS import declaration for the @generaltranslation/compiler package
15
+ * @param ast - The ast of the file
16
+ * const gtCompiler = require('@generaltranslation/compiler').vite;
17
+ */
18
+ function handleCjsImport(ast) {
19
+ const variableDeclaration = t.variableDeclaration('const', [
20
+ t.variableDeclarator(t.identifier('gtCompiler'), t.memberExpression(t.callExpression(t.identifier('require'), [
21
+ t.stringLiteral('@generaltranslation/compiler'),
22
+ ]), t.identifier('vite'))),
23
+ ]);
24
+ ast.program.body.unshift(variableDeclaration);
25
+ }
26
+ /**
27
+ * Adds an ESM import declaration for the @generaltranslation/compiler package
28
+ * @param ast - The ast of the file
29
+ * import { vite as gtCompiler } from '@generaltranslation/compiler';
30
+ */
31
+ function handleEsmImport(ast) {
32
+ const importDeclaration = t.importDeclaration([t.importSpecifier(t.identifier('gtCompiler'), t.identifier('vite'))], t.stringLiteral('@generaltranslation/compiler'));
33
+ ast.program.body.unshift(importDeclaration);
34
+ }
@@ -0,0 +1,11 @@
1
+ import * as t from '@babel/types';
2
+ import { ParseResult } from '@babel/parser';
3
+ /**
4
+ * Adds the plugin invocation to the vite config file
5
+ * Naive solution: look for an object with a plugins property only inside of a defineConfig call
6
+ */
7
+ export declare function addPluginInvocation({ ast, alias, namespaces, }: {
8
+ ast: ParseResult<t.File>;
9
+ alias: string | null;
10
+ namespaces: string[];
11
+ }): boolean;
@@ -0,0 +1,48 @@
1
+ import * as t from '@babel/types';
2
+ import traverseModule from '@babel/traverse';
3
+ // Handle CommonJS/ESM interop
4
+ const traverse = traverseModule.default || traverseModule;
5
+ /**
6
+ * Adds the plugin invocation to the vite config file
7
+ * Naive solution: look for an object with a plugins property only inside of a defineConfig call
8
+ */
9
+ export function addPluginInvocation({ ast, alias, namespaces, }) {
10
+ let addedPlugin = false;
11
+ if (namespaces.length === 0 && !alias) {
12
+ return false;
13
+ }
14
+ const pluginInvocation = alias
15
+ ? t.callExpression(t.identifier(alias), [])
16
+ : t.callExpression(t.memberExpression(t.identifier(namespaces[0]), t.identifier('vite')), []);
17
+ traverse(ast, {
18
+ CallExpression(path) {
19
+ if (!t.isIdentifier(path.node.callee, { name: 'defineConfig' }) ||
20
+ !path.node.arguments.length ||
21
+ !t.isObjectExpression(path.node.arguments[0])) {
22
+ return;
23
+ }
24
+ for (const property of path.node.arguments[0].properties) {
25
+ if (!t.isObjectProperty(property) || !isPluginsProperty(property))
26
+ continue;
27
+ if (t.isArrayExpression(property.value)) {
28
+ // Add to array: [react()] -> [react(), gtCompiler()]
29
+ property.value.elements.push(pluginInvocation);
30
+ addedPlugin = true;
31
+ }
32
+ else {
33
+ // Spread the array: someList -> [...someList, gtCompiler()]
34
+ property.value = t.arrayExpression([
35
+ t.spreadElement(property.value),
36
+ pluginInvocation,
37
+ ]);
38
+ addedPlugin = true;
39
+ }
40
+ }
41
+ },
42
+ });
43
+ return addedPlugin;
44
+ }
45
+ function isPluginsProperty(node) {
46
+ return (t.isIdentifier(node.key, { name: 'plugins' }) ||
47
+ t.isStringLiteral(node.key, { value: 'plugins' }));
48
+ }
@@ -0,0 +1,15 @@
1
+ import { ParseResult } from '@babel/parser';
2
+ import * as t from '@babel/types';
3
+ export interface CheckCompilerImportResult {
4
+ hasCompilerImport: boolean;
5
+ alias: string | null;
6
+ namespaces: string[];
7
+ }
8
+ /**
9
+ * Given the vite config file ast, checks if the @generaltranslation/compiler package is imported.
10
+ * If it is imported, capture any aliases or namespace.
11
+ *
12
+ * Does not handle:
13
+ * - Nested expressions
14
+ */
15
+ export declare function checkCompilerImport(ast: ParseResult<t.File>): CheckCompilerImportResult;
@@ -0,0 +1,113 @@
1
+ import * as t from '@babel/types';
2
+ import traverseModule from '@babel/traverse';
3
+ // Handle CommonJS/ESM interop
4
+ const traverse = traverseModule.default || traverseModule;
5
+ /**
6
+ * Given the vite config file ast, checks if the @generaltranslation/compiler package is imported.
7
+ * If it is imported, capture any aliases or namespace.
8
+ *
9
+ * Does not handle:
10
+ * - Nested expressions
11
+ */
12
+ export function checkCompilerImport(ast) {
13
+ const result = {
14
+ hasCompilerImport: false,
15
+ alias: null,
16
+ namespaces: [],
17
+ };
18
+ traverse(ast, {
19
+ ImportDeclaration(path) {
20
+ handleImportDeclaration(path, result);
21
+ },
22
+ VariableDeclaration(path) {
23
+ handleVariableDeclaration(path, result);
24
+ },
25
+ });
26
+ return result;
27
+ }
28
+ /* =============================== */
29
+ /* Parsing Functions */
30
+ /* =============================== */
31
+ /**
32
+ * Checks an import declaration for a compiler import
33
+ * @param path - The import declaration path
34
+ * @param result - The result object
35
+ */
36
+ function handleImportDeclaration(path, result) {
37
+ if (path.node.source.value !== '@generaltranslation/compiler')
38
+ return;
39
+ for (const spec of path.node.specifiers) {
40
+ if (t.isImportSpecifier(spec)) {
41
+ // Handle named import: import { vite as gtCompiler } from '@generaltranslation/compiler'
42
+ if (t.isIdentifier(spec.imported) && spec.imported.name === 'vite') {
43
+ result.hasCompilerImport = true;
44
+ result.alias = spec.local.name;
45
+ }
46
+ }
47
+ else {
48
+ // Handle default import: import gtCompiler from '@generaltranslation/compiler'
49
+ // Handle namespace import: import * as gtCompiler from '@generaltranslation/compiler'
50
+ result.hasCompilerImport = true;
51
+ result.namespaces.push(spec.local.name);
52
+ }
53
+ }
54
+ }
55
+ /**
56
+ * Handles a variable declaration for a compiler import
57
+ * @param path - The variable declaration path
58
+ * @param result - The result object
59
+ */
60
+ function handleVariableDeclaration(path, result) {
61
+ path.node.declarations.forEach((dec) => {
62
+ // Handle destructuring: const { withGTConfig } = require('@generaltranslation/compiler')
63
+ if (t.isCallExpression(dec.init) &&
64
+ t.isIdentifier(dec.init.callee, { name: 'require' }) &&
65
+ t.isStringLiteral(dec.init.arguments[0], {
66
+ value: '@generaltranslation/compiler',
67
+ })) {
68
+ if (t.isIdentifier(dec.id)) {
69
+ // Handle namespace assignment: const gtCompiler = require('@generaltranslation/compiler')
70
+ result.hasCompilerImport = true;
71
+ result.namespaces.push(dec.id.name);
72
+ }
73
+ else if (t.isObjectPattern(dec.id)) {
74
+ // Handle destructuring: const { vite: gtCompiler } = require('@generaltranslation/compiler')
75
+ let foundVite = false;
76
+ const restElements = [];
77
+ for (const prop of dec.id.properties) {
78
+ if (t.isObjectProperty(prop) &&
79
+ t.isIdentifier(prop.key) &&
80
+ t.isIdentifier(prop.value) &&
81
+ prop.key.name === 'vite') {
82
+ // Handle destructing alias assignment: const { vite: gtCompiler } = require('@generaltranslation/compiler')
83
+ result.hasCompilerImport = true;
84
+ result.alias = prop.value.name;
85
+ foundVite = true;
86
+ break;
87
+ }
88
+ else if (t.isRestElement(prop) && t.isIdentifier(prop.argument)) {
89
+ // Track list of rest elements
90
+ restElements.push(prop.argument.name);
91
+ }
92
+ }
93
+ // Handle destructuring rest elements: const { ...some, b, ...others, d } = require('@generaltranslation/compiler')
94
+ if (!foundVite && restElements.length > 0) {
95
+ result.hasCompilerImport = true;
96
+ result.namespaces.push(...restElements);
97
+ }
98
+ }
99
+ }
100
+ else if (t.isMemberExpression(dec.init) &&
101
+ t.isCallExpression(dec.init.object) &&
102
+ t.isIdentifier(dec.init.object.callee, { name: 'require' }) &&
103
+ t.isStringLiteral(dec.init.object.arguments[0], {
104
+ value: '@generaltranslation/compiler',
105
+ }) &&
106
+ t.isIdentifier(dec.init.property, { name: 'vite' }) &&
107
+ t.isIdentifier(dec.id)) {
108
+ // Handle member access: const gtCompiler = require('@generaltranslation/compiler').vite
109
+ result.hasCompilerImport = true;
110
+ result.alias = dec.id.name;
111
+ }
112
+ });
113
+ }
@@ -0,0 +1,12 @@
1
+ import { ParseResult } from '@babel/parser';
2
+ import * as t from '@babel/types';
3
+ /**
4
+ * Checks if the given AST is exporting the gtCompiler plugin
5
+ *
6
+ * Naive check: see if the plugin has been invoked anywhere in the file
7
+ */
8
+ export declare function checkPluginInvocation({ ast, alias, namespaces, }: {
9
+ ast: ParseResult<t.File>;
10
+ alias: string | null;
11
+ namespaces: string[];
12
+ }): boolean;
@@ -0,0 +1,32 @@
1
+ import * as t from '@babel/types';
2
+ import traverseModule from '@babel/traverse';
3
+ // Handle CommonJS/ESM interop
4
+ const traverse = traverseModule.default || traverseModule;
5
+ /**
6
+ * Checks if the given AST is exporting the gtCompiler plugin
7
+ *
8
+ * Naive check: see if the plugin has been invoked anywhere in the file
9
+ */
10
+ export function checkPluginInvocation({ ast, alias, namespaces, }) {
11
+ let result = false;
12
+ traverse(ast, {
13
+ CallExpression(path) {
14
+ // Handle: gtCompiler()
15
+ if (!alias)
16
+ return;
17
+ if (t.isIdentifier(path.node.callee, { name: alias })) {
18
+ result = true;
19
+ }
20
+ },
21
+ MemberExpression(path) {
22
+ // Handle: gtCompiler.vite()
23
+ if (t.isIdentifier(path.node.object) &&
24
+ namespaces.includes(path.node.object.name) &&
25
+ t.isCallExpression(path.parent) &&
26
+ t.isIdentifier(path.node.property, { name: 'vite' })) {
27
+ result = true;
28
+ }
29
+ },
30
+ });
31
+ return result;
32
+ }
@@ -12,6 +12,7 @@ import { getPackageManager } from '../utils/packageManager.js';
12
12
  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
+ import { addVitePlugin } from '../react/parse/addVitePlugin/index.js';
15
16
  export async function handleSetupReactCommand(options) {
16
17
  // Ask user for confirmation using inquirer
17
18
  const answer = await promptConfirm({
@@ -73,6 +74,9 @@ Please let us know what you would like to see supported at https://github.com/ge
73
74
  const errors = [];
74
75
  const warnings = [];
75
76
  let filesUpdated = [];
77
+ // Read tsconfig.json if it exists
78
+ const tsconfigPath = findFilepath(['tsconfig.json']);
79
+ const tsconfigJson = tsconfigPath ? loadConfig(tsconfigPath) : undefined;
76
80
  if (frameworkType === 'next-app') {
77
81
  // Check if they have a next.config.js file
78
82
  const nextConfigPath = findFilepath([
@@ -98,13 +102,20 @@ Please let us know what you would like to see supported at https://github.com/ge
98
102
  const { filesUpdated: filesUpdatedNext } = await wrapContentNext(mergeOptions, 'gt-next', errors, warnings);
99
103
  filesUpdated = [...filesUpdated, ...filesUpdatedNext];
100
104
  spinner.stop(chalk.green(`Success! Updated ${chalk.bold.cyan(filesUpdated.length)} files:\n`) + filesUpdated.map((file) => `${chalk.green('-')} ${file}`).join('\n'));
101
- // Read tsconfig.json if it exists
102
- const tsconfigPath = findFilepath(['tsconfig.json']);
103
- const tsconfigJson = tsconfigPath ? loadConfig(tsconfigPath) : undefined;
104
105
  // Add the withGTConfig() function to the next.config.js file
105
106
  await handleInitGT(nextConfigPath, errors, warnings, filesUpdated, packageJson, tsconfigJson);
106
107
  logStep(chalk.green(`Added withGTConfig() to your ${nextConfigPath} file.`));
107
108
  }
109
+ // Add gt compiler plugin
110
+ if (frameworkType === 'vite') {
111
+ await addVitePlugin({
112
+ errors,
113
+ warnings,
114
+ filesUpdated,
115
+ packageJson,
116
+ tsconfigJson,
117
+ });
118
+ }
108
119
  if (errors.length > 0) {
109
120
  logError(chalk.red('Failed to write files:\n') + errors.join('\n'));
110
121
  }
@@ -0,0 +1,20 @@
1
+ import { ParseResult } from '@babel/parser';
2
+ import * as t from '@babel/types';
3
+ /**
4
+ * Given an AST determines if the file needs to be compiled as CommonJS or ESM.
5
+ * @param ast - The AST to analyze
6
+ * @returns True if the file needs to be compiled as CommonJS, false if it needs to be compiled as ESM
7
+ */
8
+ export declare function needsCJS({ ast, warnings, filepath, packageJson, tsconfigJson, }: {
9
+ ast: ParseResult<t.File>;
10
+ warnings: string[];
11
+ filepath: string;
12
+ packageJson?: {
13
+ type?: string;
14
+ };
15
+ tsconfigJson?: {
16
+ compilerOptions?: {
17
+ module?: string;
18
+ };
19
+ };
20
+ }): boolean;
@@ -0,0 +1,72 @@
1
+ import traverseModule from '@babel/traverse';
2
+ import * as t from '@babel/types';
3
+ // Handle CommonJS/ESM interop
4
+ const traverse = traverseModule.default || traverseModule;
5
+ /**
6
+ * Given an AST determines if the file needs to be compiled as CommonJS or ESM.
7
+ * @param ast - The AST to analyze
8
+ * @returns True if the file needs to be compiled as CommonJS, false if it needs to be compiled as ESM
9
+ */
10
+ export function needsCJS({ ast, warnings, filepath, packageJson, tsconfigJson, }) {
11
+ // Analyze the actual file content to determine module system
12
+ let hasES6Imports = false;
13
+ let hasCommonJSRequire = false;
14
+ traverse(ast, {
15
+ ImportDeclaration() {
16
+ hasES6Imports = true;
17
+ },
18
+ CallExpression(path) {
19
+ if (t.isIdentifier(path.node.callee, { name: 'require' })) {
20
+ hasCommonJSRequire = true;
21
+ }
22
+ },
23
+ });
24
+ // Determine if we need CommonJS based on actual file content and fallback to config-based logic
25
+ let needsCJS = false;
26
+ if (hasES6Imports && !hasCommonJSRequire) {
27
+ // File uses ES6 imports, so we should use ES6 imports
28
+ needsCJS = false;
29
+ }
30
+ else if (hasCommonJSRequire && !hasES6Imports) {
31
+ // File uses CommonJS require, so we should use CommonJS require
32
+ needsCJS = true;
33
+ }
34
+ else if (hasES6Imports && hasCommonJSRequire) {
35
+ // Mixed usage - this is unusual but we'll default to ES6 imports
36
+ warnings.push(`Mixed ES6 imports and CommonJS require detected in ${filepath}. Defaulting to ES6 imports.`);
37
+ needsCJS = false;
38
+ }
39
+ else {
40
+ // No imports/requires found, fall back to configuration-based logic
41
+ if (filepath.endsWith('.ts') || filepath.endsWith('.tsx')) {
42
+ // For TypeScript files, check tsconfig.json compilerOptions.module
43
+ const moduleSetting = tsconfigJson?.compilerOptions?.module;
44
+ if (moduleSetting === 'commonjs' || moduleSetting === 'node') {
45
+ needsCJS = true;
46
+ }
47
+ else if (moduleSetting === 'esnext' ||
48
+ moduleSetting === 'es2022' ||
49
+ moduleSetting === 'es2020' ||
50
+ moduleSetting === 'es2015' ||
51
+ moduleSetting === 'es6' ||
52
+ moduleSetting === 'node16' ||
53
+ moduleSetting === 'nodenext') {
54
+ needsCJS = false;
55
+ }
56
+ else {
57
+ // Default to ESM for TypeScript files if no module setting is specified
58
+ needsCJS = false;
59
+ }
60
+ }
61
+ else if (filepath.endsWith('.js')) {
62
+ // For JavaScript files, check package.json type
63
+ // If package.json has "type": "module", .js files are treated as ES modules
64
+ needsCJS = packageJson?.type !== 'module';
65
+ }
66
+ else {
67
+ // For other file extensions, default to ESM
68
+ needsCJS = false;
69
+ }
70
+ }
71
+ return needsCJS;
72
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gtx-cli",
3
- "version": "2.3.11",
3
+ "version": "2.3.12",
4
4
  "main": "dist/index.js",
5
5
  "bin": "dist/main.js",
6
6
  "files": [