gtx-cli 2.0.17 → 2.0.18

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,13 @@
1
1
  # gtx-cli
2
2
 
3
+ ## 2.0.18
4
+
5
+ ### Patch Changes
6
+
7
+ - [#507](https://github.com/generaltranslation/gt/pull/507) [`8f80795`](https://github.com/generaltranslation/gt/commit/8f80795daf862f769be728c044d48e5e28d7b126) Thanks [@SamEggert](https://github.com/SamEggert)! - Setup wizard detects and matches your module system when modifying the next.config
8
+
9
+ - [#517](https://github.com/generaltranslation/gt/pull/517) [`452da1e`](https://github.com/generaltranslation/gt/commit/452da1e1f0f6d7825b82bc66fb5d3dd6e7a6ad92) Thanks [@ErnestM1234](https://github.com/ErnestM1234)! - feat: add support for yaml
10
+
3
11
  ## 2.0.17
4
12
 
5
13
  ### Patch Changes
@@ -5,6 +5,8 @@ import { gt } from '../utils/gt.js';
5
5
  import { validateJsonSchema } from '../formats/json/utils.js';
6
6
  import { mergeJson } from '../formats/json/mergeJson.js';
7
7
  import { TextDecoder } from 'node:util';
8
+ import mergeYaml from '../formats/yaml/mergeYaml.js';
9
+ import { validateYamlSchema } from '../formats/yaml/utils.js';
8
10
  /**
9
11
  * Downloads a file from the API and saves it to a local directory
10
12
  * @param translationId - The ID of the translation to download
@@ -38,6 +40,20 @@ export async function downloadFile(translationId, outputPath, inputPath, locale,
38
40
  }
39
41
  }
40
42
  }
43
+ if (options.options?.yamlSchema && locale) {
44
+ const yamlSchema = validateYamlSchema(options.options, outputPath);
45
+ if (yamlSchema) {
46
+ const originalContent = fs.readFileSync(outputPath, 'utf8');
47
+ if (originalContent) {
48
+ data = mergeYaml(originalContent, outputPath, options.options, [
49
+ {
50
+ translatedContent: data,
51
+ targetLocale: locale,
52
+ },
53
+ ])[0];
54
+ }
55
+ }
56
+ }
41
57
  // Write the file to disk
42
58
  await fs.promises.writeFile(outputPath, data);
43
59
  return true;
@@ -3,7 +3,9 @@ import * as path from 'path';
3
3
  import { logError, logWarning } from '../console/logging.js';
4
4
  import { gt } from '../utils/gt.js';
5
5
  import { validateJsonSchema } from '../formats/json/utils.js';
6
+ import { validateYamlSchema } from '../formats/yaml/utils.js';
6
7
  import { mergeJson } from '../formats/json/mergeJson.js';
8
+ import mergeYaml from '../formats/yaml/mergeYaml.js';
7
9
  /**
8
10
  * Downloads multiple translation files in a single batch request
9
11
  * @param files - Array of files to download with their output paths
@@ -56,6 +58,20 @@ export async function downloadFileBatch(files, options, maxRetries = 3, retryDel
56
58
  }
57
59
  }
58
60
  }
61
+ if (options.options?.yamlSchema && locale) {
62
+ const yamlSchema = validateYamlSchema(options.options, inputPath);
63
+ if (yamlSchema) {
64
+ const originalContent = fs.readFileSync(inputPath, 'utf8');
65
+ if (originalContent) {
66
+ data = mergeYaml(originalContent, inputPath, options.options, [
67
+ {
68
+ translatedContent: file.data,
69
+ targetLocale: locale,
70
+ },
71
+ ])[0];
72
+ }
73
+ }
74
+ }
59
75
  // Write the file to disk
60
76
  await fs.promises.writeFile(outputPath, data);
61
77
  result.successful.push(translationId);
@@ -108,14 +108,27 @@ export async function generateSettings(options, cwd = process.cwd()) {
108
108
  ? resolveFiles(mergedOptions.files, mergedOptions.defaultLocale, cwd)
109
109
  : undefined;
110
110
  // Add additional options if provided
111
- if (mergedOptions.options && mergedOptions.options.jsonSchema) {
112
- for (const fileGlob of Object.keys(mergedOptions.options.jsonSchema)) {
113
- const jsonSchema = mergedOptions.options.jsonSchema[fileGlob];
114
- if (jsonSchema.preset) {
115
- mergedOptions.options.jsonSchema[fileGlob] = {
116
- ...generatePreset(jsonSchema.preset),
117
- ...jsonSchema,
118
- };
111
+ if (mergedOptions.options) {
112
+ if (mergedOptions.options.jsonSchema) {
113
+ for (const fileGlob of Object.keys(mergedOptions.options.jsonSchema)) {
114
+ const jsonSchema = mergedOptions.options.jsonSchema[fileGlob];
115
+ if (jsonSchema.preset) {
116
+ mergedOptions.options.jsonSchema[fileGlob] = {
117
+ ...generatePreset(jsonSchema.preset, 'json'),
118
+ ...jsonSchema,
119
+ };
120
+ }
121
+ }
122
+ }
123
+ if (mergedOptions.options.yamlSchema) {
124
+ for (const fileGlob of Object.keys(mergedOptions.options.yamlSchema)) {
125
+ const yamlSchema = mergedOptions.options.yamlSchema[fileGlob];
126
+ if (yamlSchema.preset) {
127
+ mergedOptions.options.yamlSchema[fileGlob] = {
128
+ ...generatePreset(yamlSchema.preset, 'yaml'),
129
+ ...yamlSchema,
130
+ };
131
+ }
119
132
  }
120
133
  }
121
134
  }
@@ -1,2 +1,2 @@
1
- import { JsonSchema } from '../types/index.js';
2
- export declare function generatePreset(preset: string): JsonSchema;
1
+ import { JsonSchema, YamlSchema } from '../types/index.js';
2
+ export declare function generatePreset(preset: string, type: 'json' | 'yaml'): JsonSchema | YamlSchema;
@@ -1,44 +1,56 @@
1
- export function generatePreset(preset) {
2
- switch (preset) {
3
- case 'mintlify':
4
- // https://mintlify.com/docs/navigation
5
- return {
6
- composite: {
7
- '$.navigation.languages': {
8
- type: 'array',
9
- key: '$.language',
10
- include: [
11
- '$..group',
12
- '$..tab',
13
- '$..item',
14
- '$..anchor',
15
- '$..dropdown',
16
- ],
17
- transform: {
18
- '$..pages[*]': {
19
- match: '^{locale}/(.*)$',
20
- replace: '{locale}/$1',
1
+ export function generatePreset(preset, type) {
2
+ if (type === 'json') {
3
+ switch (preset) {
4
+ case 'mintlify':
5
+ // https://mintlify.com/docs/navigation
6
+ return {
7
+ composite: {
8
+ '$.navigation.languages': {
9
+ type: 'array',
10
+ key: '$.language',
11
+ include: [
12
+ '$..group',
13
+ '$..tab',
14
+ '$..item',
15
+ '$..anchor',
16
+ '$..dropdown',
17
+ ],
18
+ transform: {
19
+ '$..pages[*]': {
20
+ match: '^{locale}/(.*)$',
21
+ replace: '{locale}/$1',
22
+ },
21
23
  },
22
24
  },
23
- },
24
- '$.redirects': {
25
- type: 'array',
26
- key: '$.language',
27
- include: [],
28
- transform: {
29
- '$.source': {
30
- match: '^/{locale}/(.*)$',
31
- replace: '/{locale}/$1',
32
- },
33
- '$.destination': {
34
- match: '^/{locale}/(.*)$',
35
- replace: '/{locale}/$1',
25
+ '$.redirects': {
26
+ type: 'array',
27
+ key: '$.language',
28
+ include: [],
29
+ transform: {
30
+ '$.source': {
31
+ match: '^/{locale}/(.*)$',
32
+ replace: '/{locale}/$1',
33
+ },
34
+ '$.destination': {
35
+ match: '^/{locale}/(.*)$',
36
+ replace: '/{locale}/$1',
37
+ },
36
38
  },
37
39
  },
38
40
  },
39
- },
40
- };
41
- default:
42
- return {};
41
+ };
42
+ default:
43
+ return {};
44
+ }
45
+ }
46
+ else {
47
+ switch (preset) {
48
+ case 'mintlify':
49
+ return {
50
+ include: ['$..summary', '$..description'],
51
+ };
52
+ default:
53
+ return {};
54
+ }
43
55
  }
44
56
  }
@@ -1,8 +1,9 @@
1
- export declare const SUPPORTED_FILE_EXTENSIONS: readonly ["json", "mdx", "md", "ts", "js"];
1
+ export declare const SUPPORTED_FILE_EXTENSIONS: readonly ["json", "mdx", "md", "ts", "js", "yaml"];
2
2
  export declare const FILE_EXT_TO_EXT_LABEL: {
3
3
  json: string;
4
4
  mdx: string;
5
5
  md: string;
6
6
  ts: string;
7
7
  js: string;
8
+ yaml: string;
8
9
  };
@@ -4,6 +4,7 @@ export const SUPPORTED_FILE_EXTENSIONS = [
4
4
  'md',
5
5
  'ts',
6
6
  'js',
7
+ 'yaml',
7
8
  ];
8
9
  export const FILE_EXT_TO_EXT_LABEL = {
9
10
  json: 'JSON',
@@ -11,4 +12,5 @@ export const FILE_EXT_TO_EXT_LABEL = {
11
12
  md: 'Markdown',
12
13
  ts: 'TypeScript',
13
14
  js: 'JavaScript',
15
+ yaml: 'YAML',
14
16
  };
@@ -10,6 +10,7 @@ import { SUPPORTED_FILE_EXTENSIONS } from './supportedFiles.js';
10
10
  import sanitizeFileContent from '../../utils/sanitizeFileContent.js';
11
11
  import { parseJson } from '../json/parseJson.js';
12
12
  import { createFileMapping } from './fileMapping.js';
13
+ import parseYaml from '../yaml/parseYaml.js';
13
14
  const SUPPORTED_DATA_FORMATS = ['JSX', 'ICU', 'I18NEXT'];
14
15
  /**
15
16
  * Sends multiple files to the API for translation
@@ -42,8 +43,26 @@ export async function translateFiles(filePaths, placeholderPaths, transformPaths
42
43
  });
43
44
  allFiles.push(...jsonFiles);
44
45
  }
46
+ // Process YAML files
47
+ if (filePaths.yaml) {
48
+ if (!SUPPORTED_DATA_FORMATS.includes(dataFormat)) {
49
+ logErrorAndExit(noSupportedFormatError);
50
+ }
51
+ const yamlFiles = filePaths.yaml.map((filePath) => {
52
+ const content = readFile(filePath);
53
+ const parsedYaml = parseYaml(content, filePath, additionalOptions);
54
+ const relativePath = getRelative(filePath);
55
+ return {
56
+ content: parsedYaml,
57
+ fileName: relativePath,
58
+ fileFormat: 'JSON', // Translate as a JSON file
59
+ dataFormat,
60
+ };
61
+ });
62
+ allFiles.push(...yamlFiles);
63
+ }
45
64
  for (const fileType of SUPPORTED_FILE_EXTENSIONS) {
46
- if (fileType === 'json')
65
+ if (fileType === 'json' || fileType === 'yaml')
47
66
  continue;
48
67
  if (filePaths[fileType]) {
49
68
  const files = filePaths[fileType].map((filePath) => {
@@ -10,6 +10,7 @@ import { parseJson } from '../json/parseJson.js';
10
10
  import { uploadFiles } from '../../api/uploadFiles.js';
11
11
  import { existsSync, readFileSync } from 'node:fs';
12
12
  import { createFileMapping } from './fileMapping.js';
13
+ import parseYaml from '../yaml/parseYaml.js';
13
14
  const SUPPORTED_DATA_FORMATS = ['JSX', 'ICU', 'I18NEXT'];
14
15
  /**
15
16
  * Sends multiple files to the API for translation
@@ -43,8 +44,27 @@ export async function upload(filePaths, placeholderPaths, transformPaths, dataFo
43
44
  });
44
45
  allFiles.push(...jsonFiles);
45
46
  }
47
+ // Process YAML files
48
+ if (filePaths.yaml) {
49
+ if (!SUPPORTED_DATA_FORMATS.includes(dataFormat)) {
50
+ logErrorAndExit(noSupportedFormatError);
51
+ }
52
+ const yamlFiles = filePaths.yaml.map((filePath) => {
53
+ const content = readFile(filePath);
54
+ const parsedYaml = parseYaml(content, filePath, additionalOptions);
55
+ const relativePath = getRelative(filePath);
56
+ return {
57
+ content: parsedYaml,
58
+ fileName: relativePath,
59
+ fileFormat: 'JSON', // Translate as a JSON file
60
+ dataFormat,
61
+ locale: options.defaultLocale,
62
+ };
63
+ });
64
+ allFiles.push(...yamlFiles);
65
+ }
46
66
  for (const fileType of SUPPORTED_FILE_EXTENSIONS) {
47
- if (fileType === 'json')
67
+ if (fileType === 'json' || fileType === 'yaml')
48
68
  continue;
49
69
  if (filePaths[fileType]) {
50
70
  const files = filePaths[fileType].map((filePath) => {
@@ -0,0 +1,5 @@
1
+ import { AdditionalOptions } from '../../types/index.js';
2
+ export default function mergeYaml(originalContent: string, inputPath: string, options: AdditionalOptions, targets: {
3
+ translatedContent: string;
4
+ targetLocale: string;
5
+ }[]): string[];
@@ -0,0 +1,55 @@
1
+ import JSONPointer from 'jsonpointer';
2
+ import { exit, logError } from '../../console/logging.js';
3
+ import { validateYamlSchema } from './utils.js';
4
+ import YAML from 'yaml';
5
+ export default function mergeYaml(originalContent, inputPath, options, targets) {
6
+ const yamlSchema = validateYamlSchema(options, inputPath);
7
+ if (!yamlSchema) {
8
+ return targets.map((target) => target.translatedContent);
9
+ }
10
+ let originalYaml;
11
+ try {
12
+ originalYaml = YAML.parse(originalContent);
13
+ }
14
+ catch {
15
+ logError(`Invalid YAML file: ${inputPath}`);
16
+ exit(1);
17
+ }
18
+ // Unreachable (validated in validateYamlSchema, included for type check)
19
+ if (!yamlSchema.include) {
20
+ logError('No include property found in YAML schema');
21
+ exit(1);
22
+ }
23
+ // Handle include
24
+ const output = [];
25
+ for (const target of targets) {
26
+ // Must clone the original YAML to avoid mutations
27
+ const mergedYaml = JSON.parse(JSON.stringify(originalYaml));
28
+ let translatedJson;
29
+ try {
30
+ translatedJson = JSON.parse(target.translatedContent);
31
+ }
32
+ catch {
33
+ // If parsing fails, treat as empty object to avoid crashes
34
+ translatedJson = {};
35
+ }
36
+ for (const [jsonPointer, translatedValue] of Object.entries(translatedJson)) {
37
+ try {
38
+ // Try to get the value - if this succeeds, the pointer exists
39
+ if (JSONPointer.get(mergedYaml, jsonPointer) == null) {
40
+ continue;
41
+ }
42
+ // Set the new value regardless of what the current value is (including null/falsy)
43
+ JSONPointer.set(mergedYaml, jsonPointer, translatedValue);
44
+ }
45
+ catch {
46
+ // Silently ignore invalid or non-existent JSON pointers
47
+ }
48
+ }
49
+ output.push(YAML.stringify(mergedYaml));
50
+ }
51
+ if (!output.length) {
52
+ return [originalContent];
53
+ }
54
+ return output;
55
+ }
@@ -0,0 +1,2 @@
1
+ import { AdditionalOptions } from '../../types/index.js';
2
+ export default function parseYaml(content: string, filePath: string, options: AdditionalOptions): string;
@@ -0,0 +1,23 @@
1
+ import { exit, logError } from '../../console/logging.js';
2
+ import YAML from 'yaml';
3
+ import { validateYamlSchema } from './utils.js';
4
+ import { flattenJsonWithStringFilter } from '../json/flattenJson.js';
5
+ export default function parseYaml(content, filePath, options) {
6
+ const yamlSchema = validateYamlSchema(options, filePath);
7
+ if (!yamlSchema) {
8
+ return content;
9
+ }
10
+ let yaml;
11
+ try {
12
+ yaml = YAML.parse(content);
13
+ }
14
+ catch {
15
+ logError(`Invalid YAML file: ${filePath}`);
16
+ exit(1);
17
+ }
18
+ if (yamlSchema.include) {
19
+ const flattenedYaml = flattenJsonWithStringFilter(yaml, yamlSchema.include);
20
+ return JSON.stringify(flattenedYaml);
21
+ }
22
+ return content;
23
+ }
@@ -0,0 +1,2 @@
1
+ import { AdditionalOptions, YamlSchema } from '../../types/index.js';
2
+ export declare function validateYamlSchema(options: AdditionalOptions, filePath: string): YamlSchema | null;
@@ -0,0 +1,22 @@
1
+ import { logError, exit } from '../../console/logging.js';
2
+ import micromatch from 'micromatch';
3
+ const { isMatch } = micromatch;
4
+ import path from 'path';
5
+ export function validateYamlSchema(options, filePath) {
6
+ if (!options.yamlSchema) {
7
+ return null;
8
+ }
9
+ // Check if the file matches any of the yaml schema globs
10
+ const fileGlobs = Object.keys(options.yamlSchema);
11
+ const matchingGlob = fileGlobs.find((fileGlob) => isMatch(path.relative(process.cwd(), filePath), fileGlob));
12
+ if (!matchingGlob || !options.yamlSchema[matchingGlob]) {
13
+ return null;
14
+ }
15
+ // Validate includes
16
+ const yamlSchema = options.yamlSchema[matchingGlob];
17
+ if (!yamlSchema.include) {
18
+ logError('No include property found in YAML schema');
19
+ exit(1);
20
+ }
21
+ return yamlSchema;
22
+ }
@@ -1 +1,7 @@
1
- export declare function handleInitGT(filepath: string, errors: string[], warnings: string[], filesUpdated: string[]): Promise<void>;
1
+ export declare function handleInitGT(filepath: string, errors: string[], warnings: string[], filesUpdated: string[], packageJson?: {
2
+ type?: string;
3
+ }, tsconfigJson?: {
4
+ compilerOptions?: {
5
+ module?: string;
6
+ };
7
+ }): Promise<void>;
@@ -7,7 +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
- export async function handleInitGT(filepath, errors, warnings, filesUpdated) {
10
+ export async function handleInitGT(filepath, errors, warnings, filesUpdated, packageJson, tsconfigJson) {
11
11
  const code = await fs.promises.readFile(filepath, 'utf8');
12
12
  let ast;
13
13
  try {
@@ -17,7 +17,66 @@ export async function handleInitGT(filepath, errors, warnings, filesUpdated) {
17
17
  tokens: true,
18
18
  createParenthesizedExpressions: true,
19
19
  });
20
- const needsCJS = filepath.endsWith('.js');
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
+ },
32
+ });
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
+ }
21
80
  // Check if withGTConfig or initGT is already imported/required
22
81
  let hasGTConfig = false;
23
82
  let hasInitGT = false;
@@ -36,16 +95,48 @@ export async function handleInitGT(filepath, errors, warnings, filesUpdated) {
36
95
  },
37
96
  VariableDeclaration(path) {
38
97
  path.node.declarations.forEach((dec) => {
39
- if (t.isVariableDeclarator(dec) &&
40
- t.isCallExpression(dec.init) &&
41
- t.isIdentifier(dec.init.callee, { name: 'require' }) &&
42
- t.isStringLiteral(dec.init.arguments[0], {
43
- value: 'gt-next/config',
44
- })) {
45
- if (t.isIdentifier(dec.id, { name: 'withGTConfig' }))
46
- hasGTConfig = true;
47
- if (t.isIdentifier(dec.id, { name: 'initGT' }))
48
- hasInitGT = true;
98
+ if (t.isVariableDeclarator(dec)) {
99
+ // Handle destructuring: const { withGTConfig } = require('gt-next/config')
100
+ if (t.isCallExpression(dec.init) &&
101
+ t.isIdentifier(dec.init.callee, { name: 'require' }) &&
102
+ t.isStringLiteral(dec.init.arguments[0], {
103
+ value: 'gt-next/config',
104
+ })) {
105
+ // Handle simple assignment: const withGTConfig = require(...)
106
+ if (t.isIdentifier(dec.id, { name: 'withGTConfig' }))
107
+ hasGTConfig = true;
108
+ if (t.isIdentifier(dec.id, { name: 'initGT' }))
109
+ hasInitGT = true;
110
+ // Handle destructuring: const { withGTConfig } = require(...)
111
+ if (t.isObjectPattern(dec.id)) {
112
+ dec.id.properties.forEach((prop) => {
113
+ if (t.isObjectProperty(prop) &&
114
+ t.isIdentifier(prop.key) &&
115
+ t.isIdentifier(prop.value)) {
116
+ if (prop.key.name === 'withGTConfig')
117
+ hasGTConfig = true;
118
+ if (prop.key.name === 'initGT')
119
+ hasInitGT = true;
120
+ }
121
+ });
122
+ }
123
+ }
124
+ // Handle member access: const withGTConfig = require('gt-next/config').withGTConfig
125
+ else if (t.isMemberExpression(dec.init) &&
126
+ t.isCallExpression(dec.init.object) &&
127
+ t.isIdentifier(dec.init.object.callee, { name: 'require' }) &&
128
+ t.isStringLiteral(dec.init.object.arguments[0], {
129
+ value: 'gt-next/config',
130
+ })) {
131
+ if (t.isIdentifier(dec.id, { name: 'withGTConfig' }) &&
132
+ t.isIdentifier(dec.init.property, { name: 'withGTConfig' })) {
133
+ hasGTConfig = true;
134
+ }
135
+ if (t.isIdentifier(dec.id, { name: 'initGT' }) &&
136
+ t.isIdentifier(dec.init.property, { name: 'initGT' })) {
137
+ hasInitGT = true;
138
+ }
139
+ }
49
140
  }
50
141
  });
51
142
  },
@@ -12,6 +12,7 @@ import { wrapContentNext } from '../next/parse/wrapContent.js';
12
12
  import { getPackageManager } from '../utils/packageManager.js';
13
13
  import { installPackage } from '../utils/installPackage.js';
14
14
  import { createOrUpdateConfig } from '../fs/config/setupConfig.js';
15
+ import { loadConfig } from '../fs/config/loadConfig.js';
15
16
  export async function handleSetupReactCommand(options) {
16
17
  // Ask user for confirmation using inquirer
17
18
  const answer = await promptConfirm({
@@ -111,8 +112,11 @@ Please let us know what you would like to see supported at https://github.com/ge
111
112
  filesUpdated = [...filesUpdated, ...filesUpdatedNext];
112
113
  spinner.stop(chalk.green(`Success! Added <T> tags and updated ${chalk.bold.cyan(filesUpdated.length)} files:\n`) + filesUpdated.map((file) => `${chalk.green('-')} ${file}`).join('\n'));
113
114
  if (addWithGTConfig) {
115
+ // Read tsconfig.json if it exists
116
+ const tsconfigPath = findFilepath(['tsconfig.json']);
117
+ const tsconfigJson = tsconfigPath ? loadConfig(tsconfigPath) : undefined;
114
118
  // Add the withGTConfig() function to the next.config.js file
115
- await handleInitGT(nextConfigPath, errors, warnings, filesUpdated);
119
+ await handleInitGT(nextConfigPath, errors, warnings, filesUpdated, packageJson, tsconfigJson);
116
120
  logStep(chalk.green(`Added withGTConfig() to your ${nextConfigPath} file.`));
117
121
  }
118
122
  if (errors.length > 0) {
@@ -103,6 +103,9 @@ export type AdditionalOptions = {
103
103
  jsonSchema?: {
104
104
  [fileGlob: string]: JsonSchema;
105
105
  };
106
+ yamlSchema?: {
107
+ [fileGlob: string]: YamlSchema;
108
+ };
106
109
  docsUrlPattern?: string;
107
110
  docsImportPattern?: string;
108
111
  docsHideDefaultLocaleImport?: boolean;
@@ -115,6 +118,10 @@ export type JsonSchema = {
115
118
  [sourceObjectPath: string]: SourceObjectOptions;
116
119
  };
117
120
  };
121
+ export type YamlSchema = {
122
+ preset?: 'mintlify';
123
+ include?: string[];
124
+ };
118
125
  export type SourceObjectOptions = {
119
126
  type: 'array' | 'object';
120
127
  include: string[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gtx-cli",
3
- "version": "2.0.17",
3
+ "version": "2.0.18",
4
4
  "main": "dist/index.js",
5
5
  "bin": "dist/main.js",
6
6
  "files": [
@@ -88,13 +88,15 @@
88
88
  "fast-glob": "^3.3.3",
89
89
  "form-data": "^4.0.2",
90
90
  "generaltranslation": "^7.1.4",
91
+ "json-pointer": "^0.6.2",
91
92
  "jsonpath-plus": "^10.3.0",
92
93
  "jsonpointer": "^5.0.1",
93
94
  "micromatch": "^4.0.8",
94
95
  "open": "^10.1.1",
95
96
  "ora": "^8.2.0",
96
97
  "resolve": "^1.22.10",
97
- "tsconfig-paths": "^4.2.0"
98
+ "tsconfig-paths": "^4.2.0",
99
+ "yaml": "^2.8.0"
98
100
  },
99
101
  "devDependencies": {
100
102
  "@biomejs/biome": "^1.9.4",