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 +6 -0
- package/dist/next/parse/handleInitGT.js +9 -60
- package/dist/react/parse/addVitePlugin/index.d.ts +22 -0
- package/dist/react/parse/addVitePlugin/index.js +40 -0
- package/dist/react/parse/addVitePlugin/installCompiler.d.ts +8 -0
- package/dist/react/parse/addVitePlugin/installCompiler.js +22 -0
- package/dist/react/parse/addVitePlugin/updateViteConfig.d.ts +19 -0
- package/dist/react/parse/addVitePlugin/updateViteConfig.js +123 -0
- package/dist/react/parse/addVitePlugin/utils/addCompilerImport.d.ts +9 -0
- package/dist/react/parse/addVitePlugin/utils/addCompilerImport.js +34 -0
- package/dist/react/parse/addVitePlugin/utils/addPluginInvocation.d.ts +11 -0
- package/dist/react/parse/addVitePlugin/utils/addPluginInvocation.js +48 -0
- package/dist/react/parse/addVitePlugin/utils/checkCompilerImport.d.ts +15 -0
- package/dist/react/parse/addVitePlugin/utils/checkCompilerImport.js +113 -0
- package/dist/react/parse/addVitePlugin/utils/checkPluginInvocation.d.ts +12 -0
- package/dist/react/parse/addVitePlugin/utils/checkPluginInvocation.js +32 -0
- package/dist/setup/wizard.js +14 -3
- package/dist/utils/parse/needsCJS.d.ts +20 -0
- package/dist/utils/parse/needsCJS.js +72 -0
- package/package.json +1 -1
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
|
-
//
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
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(
|
|
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,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
|
+
}
|
package/dist/setup/wizard.js
CHANGED
|
@@ -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
|
+
}
|