gt 2.22.4 → 2.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (127) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/dist/auth/errors.d.ts +1 -0
  3. package/dist/auth/errors.js +12 -2
  4. package/dist/auth/errors.js.map +1 -1
  5. package/dist/auth/interactiveLogin.d.ts +2 -0
  6. package/dist/auth/interactiveLogin.js +22 -0
  7. package/dist/auth/interactiveLogin.js.map +1 -0
  8. package/dist/auth/oauth.js +2 -2
  9. package/dist/auth/oauth.js.map +1 -1
  10. package/dist/cli/base.d.ts +22 -4
  11. package/dist/cli/base.js +328 -223
  12. package/dist/cli/base.js.map +1 -1
  13. package/dist/cli/commands/api.js +15 -16
  14. package/dist/cli/commands/api.js.map +1 -1
  15. package/dist/cli/node.js +1 -1
  16. package/dist/cli/node.js.map +1 -1
  17. package/dist/cli/react.js +1 -1
  18. package/dist/cli/react.js.map +1 -1
  19. package/dist/cli/vue.js +2 -2
  20. package/dist/cli/vue.js.map +1 -1
  21. package/dist/config/generateSettings.d.ts +2 -0
  22. package/dist/config/generateSettings.js +13 -6
  23. package/dist/config/generateSettings.js.map +1 -1
  24. package/dist/config/resolveConfig.js +0 -4
  25. package/dist/config/resolveConfig.js.map +1 -1
  26. package/dist/config/validateSettings.js +5 -4
  27. package/dist/config/validateSettings.js.map +1 -1
  28. package/dist/console/{inkLocaleData.d.ts → localeOptions.d.ts} +7 -2
  29. package/dist/console/{inkLocaleData.js → localeOptions.js} +3 -8
  30. package/dist/console/localeOptions.js.map +1 -0
  31. package/dist/console/logger.d.ts +7 -0
  32. package/dist/console/logger.js +48 -85
  33. package/dist/console/logger.js.map +1 -1
  34. package/dist/console/logging.d.ts +11 -1
  35. package/dist/console/logging.js +88 -100
  36. package/dist/console/logging.js.map +1 -1
  37. package/dist/formats/files/aggregateFiles.js +1 -1
  38. package/dist/formats/files/supportedFiles.d.ts +3 -0
  39. package/dist/formats/files/supportedFiles.js +10 -1
  40. package/dist/formats/files/supportedFiles.js.map +1 -1
  41. package/dist/formats/yaml/mergeYaml.js +1 -1
  42. package/dist/fs/config/loadConfig.d.ts +2 -0
  43. package/dist/fs/config/loadConfig.js +5 -1
  44. package/dist/fs/config/loadConfig.js.map +1 -1
  45. package/dist/fs/config/setupConfig.d.ts +18 -9
  46. package/dist/fs/config/setupConfig.js +51 -31
  47. package/dist/fs/config/setupConfig.js.map +1 -1
  48. package/dist/fs/createLoadTranslationsFile.d.ts +22 -1
  49. package/dist/fs/createLoadTranslationsFile.js +43 -20
  50. package/dist/fs/createLoadTranslationsFile.js.map +1 -1
  51. package/dist/generated/version.d.ts +1 -1
  52. package/dist/generated/version.js +1 -1
  53. package/dist/generated/version.js.map +1 -1
  54. package/dist/hooks/postProcess.d.ts +1 -2
  55. package/dist/hooks/postProcess.js +1 -1
  56. package/dist/hooks/postProcess.js.map +1 -1
  57. package/dist/locadex/setupFlow.d.ts +4 -1
  58. package/dist/locadex/setupFlow.js +5 -3
  59. package/dist/locadex/setupFlow.js.map +1 -1
  60. package/dist/react/jsx/utils/jsxParsing/addGTIdentifierToSyntaxTree.js +1 -1
  61. package/dist/react/jsx/utils/jsxParsing/parseJsx.js +1 -1
  62. package/dist/react/jsx/utils/parseString.js +1 -1
  63. package/dist/react/jsx/utils/stringParsing/derivation/index.js +1 -1
  64. package/dist/setup/buildTools/index.d.ts +44 -0
  65. package/dist/setup/buildTools/index.js +10 -0
  66. package/dist/setup/buildTools/index.js.map +1 -0
  67. package/dist/setup/buildTools/vite.d.ts +2 -0
  68. package/dist/setup/buildTools/vite.js +61 -0
  69. package/dist/setup/buildTools/vite.js.map +1 -0
  70. package/dist/setup/developmentCredentials.d.ts +40 -5
  71. package/dist/setup/developmentCredentials.js +119 -37
  72. package/dist/setup/developmentCredentials.js.map +1 -1
  73. package/dist/setup/instructions/base.md +1 -1
  74. package/dist/setup/onboarding.d.ts +131 -0
  75. package/dist/setup/onboarding.js +289 -0
  76. package/dist/setup/onboarding.js.map +1 -0
  77. package/dist/setup/setupTarget.d.ts +1 -0
  78. package/dist/setup/setupTarget.js +52 -0
  79. package/dist/setup/setupTarget.js.map +1 -0
  80. package/dist/setup/setupViteSPA.d.ts +32 -1
  81. package/dist/setup/setupViteSPA.js +110 -20
  82. package/dist/setup/setupViteSPA.js.map +1 -1
  83. package/dist/setup/userInput.d.ts +12 -3
  84. package/dist/setup/userInput.js +27 -11
  85. package/dist/setup/userInput.js.map +1 -1
  86. package/dist/setup/wizard.d.ts +19 -3
  87. package/dist/setup/wizard.js +119 -105
  88. package/dist/setup/wizard.js.map +1 -1
  89. package/dist/types/index.d.ts +2 -1
  90. package/dist/types/index.js +13 -1
  91. package/dist/types/index.js.map +1 -0
  92. package/dist/utils/credentials.d.ts +9 -6
  93. package/dist/utils/credentials.js +36 -22
  94. package/dist/utils/credentials.js.map +1 -1
  95. package/dist/utils/monorepoVersionCheck.d.ts +1 -1
  96. package/dist/utils/monorepoVersionCheck.js +5 -5
  97. package/dist/utils/monorepoVersionCheck.js.map +1 -1
  98. package/dist/utils/packageManager.js +13 -14
  99. package/dist/utils/packageManager.js.map +1 -1
  100. package/package.json +5 -9
  101. package/dist/console/inkFields.d.ts +0 -23
  102. package/dist/console/inkFields.js +0 -88
  103. package/dist/console/inkFields.js.map +0 -1
  104. package/dist/console/inkLayout.d.ts +0 -7
  105. package/dist/console/inkLayout.js +0 -140
  106. package/dist/console/inkLayout.js.map +0 -1
  107. package/dist/console/inkLocaleData.js.map +0 -1
  108. package/dist/console/inkPrompts.d.ts +0 -8
  109. package/dist/console/inkPrompts.js +0 -499
  110. package/dist/console/inkPrompts.js.map +0 -1
  111. package/dist/console/inkSession.d.ts +0 -3
  112. package/dist/console/inkSession.js +0 -42
  113. package/dist/console/inkSession.js.map +0 -1
  114. package/dist/console/inkTerminal.d.ts +0 -4
  115. package/dist/console/inkTerminal.js +0 -15
  116. package/dist/console/inkTerminal.js.map +0 -1
  117. package/dist/console/inkTheme.d.ts +0 -1
  118. package/dist/console/inkTheme.js +0 -6
  119. package/dist/console/inkTheme.js.map +0 -1
  120. package/dist/console/inkTypes.d.ts +0 -69
  121. package/dist/console/inkTypes.js +0 -1
  122. package/dist/console/inkUtils.d.ts +0 -24
  123. package/dist/console/inkUtils.js +0 -87
  124. package/dist/console/inkUtils.js.map +0 -1
  125. package/dist/console/terminalSession.d.ts +0 -5
  126. package/dist/console/terminalSession.js +0 -38
  127. package/dist/console/terminalSession.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"base.js","names":[],"sources":["../../src/cli/base.ts"],"sourcesContent":["import { Command, InvalidArgumentError, Option } from 'commander';\nimport { ProjectApiKeyPermission } from 'generaltranslation/api';\nimport {\n DEFAULT_TRANSLATIONS_DIR,\n DEFAULT_VITE_TRANSLATIONS_DIR,\n} from '../utils/constants.js';\nimport { createOrUpdateConfig } from '../fs/config/setupConfig.js';\nimport findFilepath from '../fs/findFilepath.js';\nimport {\n displayHeader,\n promptText,\n logErrorAndExit,\n exitSync,\n promptConfirm,\n promptMultiSelect,\n promptSelect,\n promptGlobPatterns,\n} from '../console/logging.js';\nimport { logger } from '../console/logger.js';\nimport { lottieTranslateError } from '../console/index.js';\nimport { parseGlobPatterns } from '../console/promptParsing.js';\nimport path from 'node:path';\nimport fs from 'node:fs';\nimport {\n FilesOptions,\n Settings,\n SupportedFrameworks,\n SupportedLibraries,\n SetupOptions,\n TranslateFlags,\n SharedFlags,\n} from '../types/index.js';\nimport { generateSettings } from '../config/generateSettings.js';\nimport chalk from 'chalk';\nimport { FILE_EXT_TO_EXT_LABEL } from '../formats/files/supportedFiles.js';\nimport { handleSetupReactCommand } from '../setup/wizard.js';\nimport {\n isPackageInstalled,\n searchForPackageJson,\n} from '../utils/packageJson.js';\nimport { getDesiredLocales } from '../setup/userInput.js';\nimport { installPackage } from '../utils/installPackage.js';\nimport { getPackageManager } from '../utils/packageManager.js';\nimport { areCredentialsSet } from '../utils/credentials.js';\nimport { provisionDevelopmentCredentials } from '../setup/developmentCredentials.js';\nimport { upload } from './commands/upload.js';\nimport { attachSharedFlags, attachTranslateFlags } from './flags.js';\nimport { handleStage } from './commands/stage.js';\nimport { handleSetupProject } from './commands/setupProject.js';\nimport { handleDownload } from './commands/download.js';\nimport {\n handleTranslate,\n postProcessTranslations,\n} from './commands/translate.js';\nimport {\n getNeedsPostprocessing,\n clearDownloaded,\n} from '../state/recentDownloads.js';\nimport { clearWarnings } from '../state/translateWarnings.js';\nimport { displayTranslateSummary } from '../console/displayTranslateSummary.js';\nimport updateConfig from '../fs/config/updateConfig.js';\nimport { loadConfig } from '../fs/config/loadConfig.js';\nimport { createLoadTranslationsFile } from '../fs/createLoadTranslationsFile.js';\nimport { saveLocalEdits } from '../api/saveLocalEdits.js';\nimport {\n hasValidCredentials,\n hasValidServiceLocales,\n} from './commands/utils/validation.js';\nimport processSharedStaticAssets, {\n mirrorAssetsToLocales,\n} from '../utils/sharedStaticAssets.js';\nimport { setupLocadex } from '../locadex/setupFlow.js';\nimport { detectFramework } from '../setup/detectFramework.js';\nimport {\n getFrameworkDisplayName,\n getReactFrameworkLibrary,\n} from '../setup/frameworkUtils.js';\nimport { INLINE_LIBRARIES, Libraries } from '../types/libraries.js';\nimport { handleEnqueue } from './commands/enqueue.js';\nimport { splitMintlifyLanguageRefs } from '../utils/splitMintlifyLanguageRefs.js';\nimport { runMergeDriver } from '../git/mergeDrivers.js';\nimport { setupGitMergeDrivers } from '../git/setupMergeDrivers.js';\nimport { warnReactPackageCompatibility } from '../utils/reactPackageCompatibility.js';\nimport {\n createDiagnosticMessage,\n formatDiagnosticErrorDetails,\n} from 'generaltranslation/diagnostics';\nimport { hasLogin, login, logout, whoAmI } from '../auth/oauth.js';\nimport { UserAuthError } from '../auth/errors.js';\nimport { resolveConfig } from '../config/resolveConfig.js';\nimport { setupViteSPA } from '../setup/setupViteSPA.js';\nimport { manifestDirectlyDeclaresGTVue } from '@generaltranslation/vue-extractor/integration';\nimport { api } from '../utils/api.js';\nimport { handleApiCommand, type ApiCommandOptions } from './commands/api.js';\n\nconst ID_COMPATIBILITY_WARNING_COMMANDS = new Set([\n 'download',\n 'enqueue',\n 'generate',\n 'setup',\n 'stage',\n 'translate',\n 'validate',\n]);\nconst workspaceRootSetupError = createDiagnosticMessage({\n source: 'gt',\n severity: 'Error',\n whatHappened: 'The setup wizard cannot run from a monorepo workspace root',\n why: 'GT must be configured in the specific app you want to localize',\n fix: \"Change to that app's directory and rerun `npx gt@latest`\",\n});\nfunction createProjectCommandError(\n whatHappened: string,\n error: unknown\n): string {\n return createDiagnosticMessage({\n source: 'gt',\n severity: 'Error',\n whatHappened,\n details: formatDiagnosticErrorDetails(error),\n });\n}\n\nconst emptyApiKeyNameError = createDiagnosticMessage({\n whatHappened: 'The key name cannot be empty',\n fix: 'Pass a non-empty value with --name',\n});\n\nfunction parseApiKeyName(value: string): string {\n const name = value.trim();\n if (!name) throw new InvalidArgumentError(emptyApiKeyNameError);\n return name;\n}\n\nconst electronSetupError = createDiagnosticMessage({\n source: 'gt',\n severity: 'Error',\n whatHappened:\n 'The automatic setup wizard is not ready for Electron applications',\n docsUrl: 'https://generaltranslation.com/docs/react',\n});\n\n/** .env.local never reaches production; the runtime key there is set on the host. */\nfunction productionRuntimeKeyGuidance(dashboardUrl: string): string {\n return `${chalk.dim('For runtime translation in production, create an API key in the dashboard')} ${chalk.cyan(dashboardUrl)} ${chalk.dim('and set GT_API_KEY and GT_PROJECT_ID in your hosting environment.')}`;\n}\n\nasync function loginInteractively(\n baseUrl: string | undefined,\n useBrowser = true\n): Promise<void> {\n await login({\n baseUrl,\n noBrowser: !useBrowser,\n onDeviceCode: ({ userCode, verificationUri, verificationUriComplete }) => {\n logger.message(\n `Visit:\\n\\n${chalk.cyan(verificationUriComplete ?? verificationUri)}\\n\\nThen ${verificationUriComplete ? 'confirm' : 'enter'} the code ${chalk.bold(userCode)}.\\nWaiting for authentication...`\n );\n },\n onAuthorizationUrl: (url) => {\n logger.message(\n `Opening your browser to sign in. If it does not open, visit:\\n${chalk.cyan(url)}`\n );\n },\n });\n}\n\nfunction createUserAuthError(whatHappened: string, error: unknown): string {\n if (error instanceof UserAuthError) return error.message;\n return createDiagnosticMessage({\n source: 'gt',\n severity: 'Error',\n whatHappened,\n details: formatDiagnosticErrorDetails(error),\n fix: 'Run `gt login` and try again',\n });\n}\n\nasync function exitIfUnsupportedSetupTarget(): Promise<void> {\n const packageJson = await searchForPackageJson();\n if (packageJson && isPackageInstalled('electron', packageJson, false, true)) {\n logErrorAndExit(electronSetupError);\n }\n if (\n fs.existsSync(path.join(process.cwd(), 'pnpm-workspace.yaml')) ||\n packageJson?.workspaces\n ) {\n logErrorAndExit(workspaceRootSetupError);\n }\n}\n\nexport type UploadOptions = {\n config?: string;\n apiKey?: string;\n projectId?: string;\n defaultLocale?: string;\n};\n\nexport type GitSetupOptions = {\n config?: string;\n dryRun?: boolean;\n omitConfigIds?: boolean;\n driverCommand?: string;\n};\n\ntype LocalTranslationGuidanceOptions = {\n generatedLoader: boolean;\n runtimeSetup: InlineRuntimeSetup;\n translationsDir: string;\n};\n\ntype InlineRuntimeSetup = {\n hasOtherInlineRuntime: boolean;\n hasVueRuntime: boolean;\n ranReactSetup: boolean;\n};\n\nexport class BaseCLI {\n protected library: SupportedLibraries;\n protected additionalModules: SupportedLibraries[];\n protected program: Command;\n // Constructor is shared amongst all CLI class types\n public constructor(\n program: Command,\n library: SupportedLibraries,\n additionalModules?: SupportedLibraries[]\n ) {\n this.program = program;\n this.library = library;\n this.additionalModules = additionalModules || [];\n\n this.program.option(\n '--skip-version-check',\n 'Skip the monorepo GT package version consistency check'\n );\n this.program.option(\n '--suppress-id-compatibility-warning',\n 'Suppress the React package ID compatibility warning'\n );\n this.program.option(\n '-q, --quiet',\n 'Suppress informational output; only warnings and errors are shown'\n );\n // Select console routing for this command before anything else logs:\n // root hooks run before subclass hooks (version checks) and the action's\n // settings resolution. `gt api-key create` prints the new secret on\n // stdout, so its diagnostics go to stderr; every other command gets the\n // historical default back (main() routes startup output to stderr).\n this.program.hook('preAction', (_thisCommand, actionCommand) => {\n logger.setConsoleOutput(\n actionCommand.parent?.name() === 'api-key' ? 'stderr' : 'stdout'\n );\n });\n // Apply --quiet before any other hook or command action runs so the\n // singleton logger is muted for the rest of the invocation. The flag is a\n // global root option, so commander resolves it in any position and for\n // nested commands (e.g. `gt git setup --quiet`).\n this.program.hook('preAction', () => {\n logger.setQuiet(Boolean(this.program.opts().quiet));\n });\n this.program.hook('preAction', async (thisCommand, actionCommand) => {\n // Nested commands (e.g. `gt git setup`) can share leaf names with\n // translation commands; only direct children of the root qualify\n if (actionCommand.parent !== thisCommand) return;\n if (!ID_COMPATIBILITY_WARNING_COMMANDS.has(actionCommand.name())) return;\n await warnReactPackageCompatibility(\n Boolean(this.program.opts().suppressIdCompatibilityWarning)\n );\n });\n\n this.setupInitCommand();\n this.setupConfigureCommand();\n this.setupUploadCommand();\n this.setupUserAuthCommands();\n this.setupSendDiffsCommand();\n this.setupApiCommand();\n this.setupProjectCommands();\n this.setupApiKeyCommands();\n this.setupGitCommand();\n }\n // Init is never called in a child class\n public init() {\n this.setupSetupProjectCommand();\n this.setupStageCommand();\n this.setupTranslateCommand();\n this.setupDownloadCommand();\n this.setupEnqueueCommand();\n }\n // Execute is called by the main program\n public execute() {\n // If no command is specified, run 'init'\n if (process.argv.length <= 2) {\n process.argv.push('init');\n }\n }\n\n protected setupSetupProjectCommand(): void {\n attachTranslateFlags(\n this.program\n .command('setup')\n .description(\n 'Upload source files and setup the project for translation'\n )\n ).action(async (initOptions: TranslateFlags) => {\n displayHeader('Uploading source files and setting up project...');\n await this.handleSetupProject(initOptions);\n logger.endCommand('Done!');\n });\n }\n\n protected setupStageCommand(): void {\n attachTranslateFlags(\n this.program\n .command('stage')\n .description(\n 'Submits the project to the General Translation API for translation. Translations created using this command will require human approval.'\n )\n ).action(async (initOptions: TranslateFlags) => {\n displayHeader(\n 'Staging project for translation with approval required...'\n );\n await this.handleStage(initOptions);\n logger.endCommand('Done!');\n });\n }\n\n /**\n * Enqueues translations for a given set of files\n * @param initOptions - The options for the command\n * @returns The results of the command\n */\n protected setupEnqueueCommand(): void {\n attachTranslateFlags(\n this.program\n .command('enqueue')\n .description('Enqueues translations for a given set of files')\n ).action(async (initOptions: TranslateFlags) => {\n displayHeader('Enqueuing translations...');\n await this.handleEnqueue(initOptions);\n logger.endCommand('Done!');\n });\n }\n\n /**\n * Downloads translations that were originally staged\n * @param initOptions - The options for the command\n * @returns The results of the command\n */\n protected setupDownloadCommand(): void {\n attachTranslateFlags(\n this.program\n .command('download')\n .description('Download translations that were originally staged')\n ).action(async (initOptions: TranslateFlags) => {\n displayHeader('Downloading translations...');\n await this.handleDownload(initOptions);\n logger.endCommand('Done!');\n });\n }\n\n protected setupTranslateCommand(): void {\n attachTranslateFlags(\n this.program\n .command('translate')\n .description('Translate your project using General Translation')\n ).action(async (initOptions: TranslateFlags) => {\n displayHeader('Starting translation...');\n await this.handleTranslate(initOptions);\n logger.endCommand('Done!');\n });\n }\n\n protected setupSendDiffsCommand(): void {\n attachSharedFlags(\n this.program\n .command('save-local')\n .description(\n 'Save local edits for all configured files by sending diffs (no translation enqueued)'\n )\n )\n .option('--publish', 'Publish translations to the CDN', false)\n .action(async (initOptions: SharedFlags) => {\n displayHeader('Saving local edits...');\n const settings = await generateSettings(initOptions, undefined, {\n requireConfig: true,\n });\n if (!hasValidCredentials(settings) || !hasValidServiceLocales(settings))\n return exitSync(1);\n await saveLocalEdits(settings);\n logger.endCommand('Saved local edits');\n });\n }\n\n protected setupApiCommand(): void {\n attachSharedFlags(\n this.program\n .command('api [endpoint]')\n .description('Make an authenticated request to the GT API')\n .option('-X, --method <method>', 'HTTP method', 'GET')\n .option('--input <file>', 'Request body file, or - for standard input')\n .option(\n '-H, --header <header>',\n 'Request header in \"Key: Value\" format',\n (header, headers: string[] | undefined) => [\n ...(headers ?? []),\n header,\n ]\n )\n .option('-i, --include', 'Include response status and headers')\n .option('--spec', 'Print the bundled OpenAPI specification')\n ).action((endpoint, options: ApiCommandOptions) =>\n handleApiCommand(endpoint, options)\n );\n }\n\n protected setupProjectCommands(): void {\n const projectCommand = this.program\n .command('project')\n .description('Manage General Translation projects');\n\n attachSharedFlags(\n projectCommand\n .command('create')\n .description(\n 'Create a General Translation project using an organization API key'\n )\n .requiredOption('--org-id <orgId>', 'Organization ID')\n .requiredOption('--name <name>', 'Project name')\n .requiredOption('--default-locale <locale>', 'Project default locale')\n .option('--cdn-enabled', 'Enable CDN delivery', false)\n ).action(async (options) => {\n try {\n const settings = await generateSettings(options);\n // Project creation happens before a project ID exists.\n if (!hasValidServiceLocales(settings)) return exitSync(1);\n const { project } = await api.createProject(options.orgId, {\n name: options.name,\n defaultLocale: options.defaultLocale,\n cdnEnabled: options.cdnEnabled,\n });\n logger.info(`Created ${project.name} (${project.id})`);\n } catch (error) {\n return logErrorAndExit(\n createProjectCommandError('Failed to create the project', error)\n );\n }\n });\n\n attachSharedFlags(\n projectCommand\n .command('status')\n .description('Check the status of a project setup job')\n .argument('<job-id>', 'Setup job ID')\n ).action(async (jobId, options) => {\n try {\n const settings = await generateSettings(options);\n if (!hasValidCredentials(settings)) return exitSync(1);\n const [status] = await api.checkJobStatus([jobId]);\n logger.info(status?.status ?? 'unknown');\n } catch (error) {\n return logErrorAndExit(\n createProjectCommandError(\n 'Failed to check the project setup status',\n error\n )\n );\n }\n });\n }\n\n protected setupApiKeyCommands(): void {\n const apiKeyCommand = this.program\n .command('api-key')\n .description('Manage API keys for the configured project');\n\n attachSharedFlags(\n apiKeyCommand\n .command('create')\n .description(\n 'Create a project API key with the requested permissions and print it once'\n )\n .requiredOption('--name <name>', 'Key name', parseApiKeyName)\n // Validated before any request; the server grants the requested set\n // all-or-nothing, so omitting permissions would delegate everything.\n .addOption(\n new Option('--permission <permissions...>', 'Permissions to grant')\n .choices(Object.values(ProjectApiKeyPermission))\n .makeOptionMandatory()\n )\n ).action(\n async (\n options: SharedFlags & {\n name: string;\n permission: ProjectApiKeyPermission[];\n }\n ) => {\n try {\n const settings = await generateSettings(options);\n if (!hasValidCredentials(settings)) return exitSync(1);\n const { apiKey } = await api.createProjectApiKey(settings.projectId, {\n name: options.name,\n permissions: options.permission,\n });\n // Raw stdout: the secret is shown once and never reaches the log file.\n process.stdout.write(`${apiKey.key}\\n`);\n } catch (error) {\n return logErrorAndExit(\n error instanceof UserAuthError\n ? error.message\n : createProjectCommandError('Failed to create the API key', error)\n );\n }\n }\n );\n }\n\n protected setupGitCommand(): void {\n const gitCommand = this.program\n .command('git')\n .description('Configure Git integrations for General Translation');\n\n gitCommand\n .command('setup')\n .description('Set up GT merge drivers for generated translation files')\n .option(\n '-c, --config <path>',\n 'Filepath to config file, by default gt.config.json',\n findFilepath(['gt.config.json'])\n )\n .option('--dry-run', 'Print changes without writing files', false)\n .option(\n '--omit-config-ids',\n 'Persist omitConfigIds and remove generated config IDs'\n )\n .option(\n '--driver-command <command>',\n 'Command Git should use to invoke gt, e.g. \"pnpm exec gt\"'\n )\n .action(async (options: GitSetupOptions) => {\n displayHeader('Setting up GT Git merge drivers...');\n const settings = await generateSettings(options, undefined, {\n requireConfig: true,\n });\n const omitConfigIds = await this.resolveGitSetupOmitConfigIds(\n options,\n settings\n );\n const result = await setupGitMergeDrivers(settings, {\n dryRun: options.dryRun,\n omitConfigIds,\n driverCommand: options.driverCommand,\n });\n\n for (const line of result.addedAttributes) {\n logger.step(\n `${options.dryRun ? 'Would add' : 'Added'} ${chalk.cyan(\n line\n )} to ${chalk.cyan(result.gitattributesPath)}`\n );\n }\n if (result.addedAttributes.length === 0) {\n logger.info(`${chalk.cyan('.gitattributes')} is already configured.`);\n }\n\n for (const args of result.gitConfigCommands) {\n logger.step(\n `${options.dryRun ? 'Would run' : 'Configured'} ${chalk.cyan(\n `git config --local ${args.join(' ')}`\n )}`\n );\n }\n\n if (result.updatedConfig) {\n logger.step(\n `${options.dryRun ? 'Would persist' : 'Persisted'} ${chalk.cyan(\n 'omitConfigIds: true'\n )} in ${chalk.cyan(settings.config)}`\n );\n } else if (options.dryRun && !settings.omitConfigIds) {\n logger.info(\n `Run without ${chalk.cyan('--dry-run')} to be prompted to persist ${chalk.cyan(\n 'omitConfigIds: true'\n )}, or pass ${chalk.cyan('--omit-config-ids')}.`\n );\n }\n\n for (const warning of result.warnings) {\n logger.warn(chalk.yellow(warning));\n }\n\n logger.endCommand(\n options.dryRun\n ? 'Dry run complete.'\n : 'GT Git merge drivers configured.'\n );\n });\n\n gitCommand\n .command('merge-driver', { hidden: true })\n .argument('<driver>', 'Merge driver name')\n .argument('<base>', 'Common ancestor file')\n .argument('<ours>', 'Current branch file')\n .argument('<theirs>', 'Incoming branch file')\n .argument('[path]', 'Merged path')\n .action((driver: string, base: string, ours: string, theirs: string) => {\n if (driver !== 'gt-lock' && driver !== 'gtjson') {\n logger.error(`Unknown GT merge driver: ${driver}`);\n exitSync(1);\n }\n const result = runMergeDriver(driver, base, ours, theirs);\n if (!result.ok) {\n logger.error(result.reason);\n exitSync(1);\n }\n });\n }\n\n protected async resolveGitSetupOmitConfigIds(\n options: GitSetupOptions,\n settings: Settings\n ): Promise<boolean> {\n if (options.omitConfigIds) return true;\n // Already opted in: persist again so stale config IDs still get removed\n if (settings.omitConfigIds) return true;\n if (options.dryRun || !process.stdin.isTTY || !process.stdout.isTTY) {\n return false;\n }\n return promptConfirm({\n message:\n 'Also set omitConfigIds: true to reduce gt.config.json merge conflicts?',\n defaultValue: true,\n });\n }\n\n protected async handleSetupProject(\n initOptions: TranslateFlags\n ): Promise<void> {\n const settings = await generateSettings(initOptions, undefined, {\n requireConfig: true,\n });\n\n // Preprocess shared static assets if configured (move + rewrite sources)\n await processSharedStaticAssets(settings);\n\n await handleSetupProject(initOptions, settings, this.library);\n }\n\n protected async handleStage(initOptions: TranslateFlags): Promise<void> {\n const settings = await generateSettings(initOptions, undefined, {\n requireConfig: true,\n });\n\n // Preprocess shared static assets if configured (move + rewrite sources)\n await processSharedStaticAssets(settings);\n\n if (!settings.stageTranslations) {\n // Update settings.stageTranslations to true\n settings.stageTranslations = true;\n await updateConfig(settings.config, {\n stageTranslations: true,\n });\n }\n await handleStage(initOptions, settings, this.library, true);\n }\n\n /**\n * Enqueues translations for a given set of files\n * @param initOptions - The options for the command\n * @returns The results of the command\n */\n protected async handleEnqueue(initOptions: TranslateFlags): Promise<void> {\n const settings = await generateSettings(initOptions, undefined, {\n requireConfig: true,\n });\n await handleEnqueue(initOptions, settings, this.library);\n }\n\n /**\n * Downloads translations that were originally staged\n * @param initOptions - The options for the command\n * @returns The results of the command\n */\n protected async handleDownload(initOptions: TranslateFlags): Promise<void> {\n const settings = await generateSettings(initOptions, undefined, {\n requireConfig: true,\n });\n await handleDownload(initOptions, settings, this.library);\n }\n\n protected async handleTranslate(initOptions: TranslateFlags): Promise<void> {\n const settings = await generateSettings(initOptions, undefined, {\n requireConfig: true,\n });\n\n // Preprocess shared static assets if configured (move + rewrite sources)\n await processSharedStaticAssets(settings);\n\n if (!settings.stageTranslations) {\n // Lottie translations finish asynchronously server-side (layout\n // refinement runs after the translation job completes), so the immediate\n // translate flow would try to download them before they're ready. Only\n // the stage + download flow supports them.\n if (settings.files?.resolvedPaths.lottie?.length) {\n return logErrorAndExit(lottieTranslateError);\n }\n const results = await handleStage(\n initOptions,\n settings,\n this.library,\n false\n );\n if (results) {\n await handleTranslate(\n initOptions,\n settings,\n results.fileVersionData,\n results.jobData,\n results.branchData,\n results.publishMap,\n results.inlineLibrary\n );\n }\n } else {\n await handleDownload(initOptions, settings, this.library);\n }\n // Only postprocess files downloaded in this run\n const include = getNeedsPostprocessing();\n if (include.size > 0) {\n await postProcessTranslations(settings, include);\n }\n // Split Mintlify language entries into $ref files to keep docs.json small\n await splitMintlifyLanguageRefs(settings);\n // Mirror assets after translations are downloaded and locale dirs are populated\n await mirrorAssetsToLocales(settings);\n clearDownloaded();\n displayTranslateSummary();\n clearWarnings();\n }\n\n protected setupUploadCommand(): void {\n attachTranslateFlags(\n this.program\n .command('upload')\n .description(\n 'Upload source files and translations to the General Translation platform'\n )\n ).action(async (initOptions: UploadOptions) => {\n displayHeader('Starting upload...');\n const settings = await generateSettings(initOptions, undefined, {\n requireConfig: true,\n });\n\n const options = { ...initOptions, ...settings };\n\n await this.handleUploadCommand(options);\n logger.endCommand('Done!');\n });\n }\n\n protected setupUserAuthCommands(): void {\n this.program\n .command('login')\n .description('Sign in to your General Translation account')\n .option(\n '--no-browser',\n 'Do not open a browser; show a sign-in URL to use on any device instead'\n )\n .action(async (options: { browser: boolean }) => {\n displayHeader('Signing in to General Translation...');\n try {\n // Tokens are bound to one API resource, so log in to the configured one.\n const baseUrl = resolveConfig(process.cwd())?.config.baseUrl;\n await loginInteractively(\n typeof baseUrl === 'string' ? baseUrl : undefined,\n options.browser\n );\n logger.endCommand('You are now signed in.');\n } catch (error) {\n logErrorAndExit(createUserAuthError('Sign in failed', error));\n }\n });\n\n this.program\n .command('logout')\n .description('Sign out of your General Translation account')\n .action(async () => {\n try {\n await logout();\n logger.endCommand('Signed out successfully.');\n } catch (error) {\n logErrorAndExit(createUserAuthError('Sign out failed', error));\n }\n });\n\n this.program\n .command('whoami')\n .description('Show the signed-in General Translation account')\n .action(async () => {\n try {\n const user = await whoAmI();\n logger.message(user.email ?? user.name ?? user.sub);\n } catch (error) {\n logErrorAndExit(\n createUserAuthError('Could not load your account', error)\n );\n }\n });\n }\n\n protected setupInitCommand(): void {\n this.program\n .command('init')\n .description(\n 'Run the setup wizard to configure your project for General Translation'\n )\n .option(\n '--src <paths...>',\n \"Space-separated list of glob patterns containing the app's source code, by default 'src/**/*.{js,jsx,ts,tsx}' 'app/**/*.{js,jsx,ts,tsx}' 'pages/**/*.{js,jsx,ts,tsx}' 'components/**/*.{js,jsx,ts,tsx}'\"\n )\n .option(\n '-c, --config <path>',\n 'Filepath to config file, by default gt.config.json',\n findFilepath(['gt.config.json'])\n )\n .action(async (options: SetupOptions) => {\n await exitIfUnsupportedSetupTarget();\n const settings = await generateSettings(options);\n displayHeader('Running setup wizard...');\n\n const framework = await detectFramework();\n\n const useAgent = await (async () => {\n let useAgentMessage;\n if (framework.name === 'mintlify') {\n useAgentMessage = `Mintlify project detected. Would you like to connect to GitHub so that the Locadex AI Agent can translate your project automatically?`;\n }\n if (framework.name === 'next-app') {\n useAgentMessage = `Next.js App Router detected. Would you like to connect to GitHub so that the Locadex AI Agent can set up your project automatically?`;\n }\n if (useAgentMessage) {\n return await promptConfirm({\n message: useAgentMessage,\n defaultValue: false,\n });\n }\n return false;\n })();\n\n if (useAgent) {\n await setupLocadex(settings);\n logger.endCommand(\n 'Once installed, Locadex will open a PR to your repository. See the docs for more information: https://generaltranslation.com/docs/locadex'\n );\n } else {\n // Get framework display info for the defaults message\n const frameworkDisplayName =\n framework.type === 'react'\n ? getFrameworkDisplayName(framework)\n : null;\n const library =\n framework.type === 'react'\n ? getReactFrameworkLibrary(framework)\n : null;\n\n // Build defaults description based on detected framework\n const defaultTranslationsDir =\n framework.name === 'vite'\n ? DEFAULT_VITE_TRANSLATIONS_DIR\n : DEFAULT_TRANSLATIONS_DIR;\n\n const defaultsDescription =\n framework.name === 'vite'\n ? `${library} & initializeGTSPA, ${frameworkDisplayName}, Files saved locally in ${defaultTranslationsDir}`\n : framework.type === 'react'\n ? `${library} & GTProvider, ${frameworkDisplayName}, Files saved locally in ${defaultTranslationsDir}`\n : `Files saved locally in ${defaultTranslationsDir}`;\n\n // Ask if user wants to use defaults\n const useDefaults = await promptConfirm({\n message: `Would you like to use the recommended General Translation defaults? ${chalk.dim(`(${defaultsDescription})`)}`,\n defaultValue: true,\n });\n\n let ranReactSetup = false;\n\n // so that people can run init in non-js projects\n if (framework.type === 'react') {\n const wrap = useDefaults\n ? true\n : await promptConfirm({\n message:\n framework.name === 'vite'\n ? `Would you like to install ${library} and configure initializeGTSPA? See the docs for more information: https://generaltranslation.com/docs/react/tutorials/quickstart`\n : `Would you like to install ${library} and add the GTProvider? See the docs for more information: https://generaltranslation.com/docs/react/tutorials/quickstart`,\n defaultValue: true,\n });\n\n if (wrap) {\n logger.info(\n `${chalk.yellow('[EXPERIMENTAL]')} Configuring project...`\n );\n await handleSetupReactCommand(options, framework, useDefaults);\n logger.endCommand(\n `Done! Since this wizard is experimental, please review the changes and make modifications as needed.\n\\nNext step: start internationalizing! See the docs for more information: https://generaltranslation.com/docs/react/tutorials/quickstart`\n );\n ranReactSetup = true;\n }\n }\n\n if (ranReactSetup) {\n logger.startCommand('Setting up project config...');\n }\n // Configure gt.config.json\n await this.handleInitCommand(\n ranReactSetup,\n useDefaults,\n framework.name === 'vite',\n options,\n framework.name\n );\n\n logger.endCommand(\n 'Done! Check out our docs for more information on how to use General Translation: https://generaltranslation.com/docs'\n );\n }\n });\n }\n\n protected setupConfigureCommand(): void {\n this.program\n .command('configure')\n .description(\n 'Configure your project for General Translation. This will create a gt.config.json file in your codebase.'\n )\n .action(() => this.handleConfigureCommand());\n }\n\n protected async handleConfigureCommand(\n options?: SetupOptions\n ): Promise<void> {\n await exitIfUnsupportedSetupTarget();\n displayHeader('Configuring project...');\n\n logger.info(\n 'Welcome! This tool will help you configure your gt.config.json file. See the docs: https://generaltranslation.com/docs/cli/reference/config for more information.'\n );\n\n // Configure gt.config.json\n const framework = await detectFramework();\n await this.handleInitCommand(\n false,\n false,\n framework.name === 'vite',\n options\n );\n\n logger.endCommand(\n 'Done! Make sure you have an API key and project ID to use General Translation. Get them on the dashboard: https://generaltranslation.com/dashboard'\n );\n }\n\n protected async handleUploadCommand(\n settings: Settings & UploadOptions\n ): Promise<void> {\n if (!settings.files) {\n return;\n }\n\n // Process all file types at once with a single call\n await upload(settings);\n }\n\n /** Describes installed runtimes without changing historical package lookup. */\n protected getInlineRuntimeSetup(\n packageJson: Record<string, unknown>,\n ranReactSetup: boolean = false\n ): InlineRuntimeSetup {\n return {\n hasOtherInlineRuntime: INLINE_LIBRARIES.some(\n (lib) =>\n lib !== Libraries.GT_VUE && isPackageInstalled(lib, packageJson)\n ),\n hasVueRuntime: manifestDirectlyDeclaresGTVue(packageJson),\n ranReactSetup,\n };\n }\n\n /** Returns whether any inline runtime is installed for setup. */\n protected isInlineRuntimeInstalled(\n packageJson: Record<string, unknown>\n ): boolean {\n const { hasOtherInlineRuntime, hasVueRuntime } =\n this.getInlineRuntimeSetup(packageJson);\n return hasOtherInlineRuntime || hasVueRuntime;\n }\n\n /** Returns whether every installed runtime can consume CDN translations. */\n protected supportsCDNStorage(runtimeSetup: InlineRuntimeSetup): boolean {\n return !runtimeSetup.hasVueRuntime;\n }\n\n /** Returns whether setup should generate a local runtime loader. */\n protected shouldGenerateLocalTranslationLoader(\n isVite: boolean,\n runtimeSetup: InlineRuntimeSetup\n ): boolean {\n if (isVite) return false;\n if (!runtimeSetup.hasVueRuntime) return true;\n return runtimeSetup.hasOtherInlineRuntime || runtimeSetup.ranReactSetup;\n }\n\n /** Returns framework guidance after selecting local translation storage. */\n protected getLocalTranslationGuidance({\n generatedLoader,\n runtimeSetup,\n translationsDir,\n }: LocalTranslationGuidanceOptions): string | undefined {\n const guidance: string[] = [];\n if (generatedLoader) {\n guidance.push(`Created ${chalk.cyan('loadTranslations.js')} file for local translations.\nMake sure to add this function to your app configuration.\nSee https://generaltranslation.com/en/docs/next/guides/local-tx`);\n }\n if (runtimeSetup.hasVueRuntime) {\n guidance.push(`GT will write local translation files to ${translationsDir}.\nConfigure createGT({ loadTranslations }) to load files from that directory.\nSee https://www.npmjs.com/package/gt-vue`);\n }\n return guidance.length > 0 ? guidance.join('\\n') : undefined;\n }\n\n // Wizard for configuring gt.config.json\n protected async handleInitCommand(\n ranReactSetup: boolean,\n useDefaults: boolean = false,\n isVite: boolean = false,\n options?: SetupOptions,\n framework?: SupportedFrameworks\n ): Promise<void> {\n const configFilepath =\n options?.config ||\n (!isVite && fs.existsSync('src/gt.config.json')\n ? 'src/gt.config.json'\n : 'gt.config.json');\n const existingConfig = loadConfig(configFilepath);\n const { defaultLocale, locales } = await getDesiredLocales(existingConfig);\n\n const packageJson = await searchForPackageJson();\n\n // Ask if using another i18n library\n const runtimeSetup: InlineRuntimeSetup = packageJson\n ? this.getInlineRuntimeSetup(packageJson, ranReactSetup)\n : {\n hasOtherInlineRuntime: false,\n hasVueRuntime: false,\n ranReactSetup,\n };\n const isUsingGT =\n runtimeSetup.ranReactSetup ||\n runtimeSetup.hasOtherInlineRuntime ||\n runtimeSetup.hasVueRuntime;\n\n // Ask where the translations are stored\n const usingCDN = await (async () => {\n if (!isUsingGT) return false;\n if (useDefaults) return false; // Default to local\n if (!this.supportsCDNStorage(runtimeSetup)) return false;\n const selectedValue = await promptSelect({\n message: `Would you like to save translation files locally or use the General Translation CDN to store them?`,\n options: [\n { value: 'local', label: 'Save locally' },\n { value: 'cdn', label: 'Use CDN' },\n ],\n defaultValue: 'local',\n });\n return selectedValue === 'cdn';\n })();\n\n const defaultTranslationsDir = isVite\n ? DEFAULT_VITE_TRANSLATIONS_DIR\n : DEFAULT_TRANSLATIONS_DIR;\n\n // Ask where the translations are stored\n const translationsDir =\n isUsingGT && !usingCDN\n ? useDefaults\n ? defaultTranslationsDir\n : await promptText({\n message:\n 'What is the path to the directory where you would like to store your translation files?',\n defaultValue: defaultTranslationsDir,\n })\n : null;\n\n // Determine final translations directory with fallback\n const finalTranslationsDir =\n translationsDir?.trim() || defaultTranslationsDir;\n\n if (isUsingGT && !usingCDN) {\n const generatedLoader = this.shouldGenerateLocalTranslationLoader(\n isVite,\n runtimeSetup\n );\n if (generatedLoader) {\n await createLoadTranslationsFile(\n process.cwd(),\n finalTranslationsDir,\n locales\n );\n }\n const guidance = this.getLocalTranslationGuidance({\n generatedLoader,\n runtimeSetup,\n translationsDir: finalTranslationsDir,\n });\n if (guidance) logger.message(guidance);\n }\n\n const message = !isUsingGT\n ? 'What is the format of your language resource files? Select as many as applicable.\\nAdditionally, you can translate any other files you have in your project.'\n : `Do you have any additional files in this project to translate? For example, Markdown files for docs. ${chalk.dim(\n '(To continue without selecting press Enter)'\n )}`;\n const fileExtensions =\n useDefaults && isUsingGT\n ? [] // Skip for GT projects when using defaults\n : await promptMultiSelect({\n message,\n options: [\n { value: 'json', label: FILE_EXT_TO_EXT_LABEL.json },\n { value: 'md', label: FILE_EXT_TO_EXT_LABEL.md },\n { value: 'mdx', label: FILE_EXT_TO_EXT_LABEL.mdx },\n { value: 'ts', label: FILE_EXT_TO_EXT_LABEL.ts },\n { value: 'js', label: FILE_EXT_TO_EXT_LABEL.js },\n { value: 'yaml', label: FILE_EXT_TO_EXT_LABEL.yaml },\n // TWILIO_CONTENT_JSON not supported in CLI init as its too niche\n ],\n required: !isUsingGT,\n });\n\n const files: FilesOptions = {};\n for (const fileExtension of fileExtensions) {\n const label = FILE_EXT_TO_EXT_LABEL[fileExtension];\n const paths = await promptGlobPatterns({\n label,\n message: `${chalk.cyan(FILE_EXT_TO_EXT_LABEL[fileExtension])}: Enter a space-separated list of glob patterns matching the location of the ${FILE_EXT_TO_EXT_LABEL[fileExtension]} files you would like to translate.\\nMake sure to include [locale] in the patterns.\\nSee https://generaltranslation.com/docs/cli/reference/config#include for more information.`,\n defaultValue: `./**/[locale]/*.${fileExtension}`,\n });\n\n files[fileExtension] = {\n include: parseGlobPatterns(paths),\n };\n }\n\n // Add GT translations if using GT and storing locally\n if (isUsingGT && !usingCDN) {\n files.gt = {\n output: path.join(finalTranslationsDir, `[locale].json`),\n };\n }\n\n // Create gt.config.json\n await createOrUpdateConfig(configFilepath, {\n defaultLocale,\n locales,\n src: options?.src,\n files: Object.keys(files).length > 0 ? files : undefined,\n framework: isVite ? 'vite' : undefined,\n publish: isUsingGT && usingCDN,\n clearPublish: runtimeSetup.hasVueRuntime && !usingCDN,\n });\n\n logger.success(\n `Edit ${chalk.cyan(\n configFilepath\n )} to customize your translation setup. Docs: https://generaltranslation.com/docs/cli/reference/config`\n );\n\n if (ranReactSetup && isVite) {\n await setupViteSPA({\n appDirectory: process.cwd(),\n configFilepath,\n defaultLocale,\n locales,\n translationsDir: usingCDN ? undefined : finalTranslationsDir,\n });\n }\n\n // Install gt if not installed\n const isCLIInstalled = packageJson\n ? isPackageInstalled('gt', packageJson, true, true)\n : true; // if no package.json, we can't install it\n\n if (!isCLIInstalled && !(isUsingGT && isVite)) {\n const packageManager = await getPackageManager();\n const spinner = logger.createSpinner();\n spinner.start(\n `Installing gt as a dev dependency with ${packageManager.name}...`\n );\n await installPackage('gt', packageManager, true);\n spinner.stop(chalk.green('Installed gt.'));\n }\n\n const localVite = isVite && isUsingGT && !usingCDN;\n const enableLiveTranslations =\n localVite &&\n (await promptConfirm({\n message:\n 'Would you like to set up live development translations? This requires signing in or an API key.',\n defaultValue: false,\n }));\n if (!localVite || enableLiveTranslations) {\n const settings = await generateSettings({ config: configFilepath });\n const envFramework = framework ?? (isVite ? 'vite' : settings.framework);\n // The CLI translates as the signed-in user; an API key in the\n // environment takes precedence and needs no login. A development key in\n // .env.local is runtime-only and never stands in for either.\n if (\n !settings.apiKey &&\n !(await hasLogin({ baseUrl: settings.baseUrl }))\n ) {\n try {\n await loginInteractively(settings.baseUrl);\n logger.message('You are now signed in.');\n } catch (error) {\n logErrorAndExit(createUserAuthError('Sign in failed', error));\n }\n }\n if (!areCredentialsSet(settings, envFramework)) {\n const provision =\n useDefaults || enableLiveTranslations\n ? true\n : await promptConfirm({\n message:\n 'Would you like to set up a project ID and hot-reload key in .env.local?',\n defaultValue: true,\n });\n if (provision) {\n try {\n await provisionDevelopmentCredentials(settings, envFramework);\n } catch (error) {\n logErrorAndExit(\n error instanceof UserAuthError\n ? error.message\n : createProjectCommandError(\n 'Failed to set up the development credentials',\n error\n )\n );\n }\n logger.message(productionRuntimeKeyGuidance(settings.dashboardUrl));\n }\n }\n }\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"base.js","names":[],"sources":["../../src/cli/base.ts"],"sourcesContent":["import { Command, InvalidArgumentError, Option } from 'commander';\nimport { ProjectApiKeyPermission } from 'generaltranslation/api';\nimport { DEFAULT_TRANSLATIONS_DIR } from '../utils/constants.js';\nimport {\n createOrUpdateConfig,\n mergeSetupConfig,\n type SetupConfigUpdate,\n} from '../fs/config/setupConfig.js';\nimport findFilepath from '../fs/findFilepath.js';\nimport {\n displayHeader,\n promptText,\n logErrorAndExit,\n exitSync,\n promptConfirm,\n promptMultiSelect,\n promptSelect,\n promptGlobPatterns,\n} from '../console/logging.js';\nimport { logger } from '../console/logger.js';\nimport { lottieTranslateError } from '../console/index.js';\nimport { parseGlobPatterns } from '../console/promptParsing.js';\nimport path from 'node:path';\nimport {\n FilesOptions,\n Settings,\n SupportedFrameworks,\n SupportedLibraries,\n TranslateFlags,\n SharedFlags,\n} from '../types/index.js';\nimport { generateSettings } from '../config/generateSettings.js';\nimport chalk from 'chalk';\nimport {\n FILE_EXT_TO_EXT_LABEL,\n SETUP_FILE_FORMATS,\n SUPPORTED_FILE_EXTENSIONS,\n type SetupFileFormat,\n} from '../formats/files/supportedFiles.js';\nimport {\n executeReactSetup,\n resolveReactSetup,\n type ReactSetupPlan,\n} from '../setup/wizard.js';\nimport {\n isPackageInstalled,\n searchForPackageJson,\n} from '../utils/packageJson.js';\nimport { getDesiredLocales } from '../setup/userInput.js';\nimport {\n areCredentialsSet,\n getDevelopmentEnvNames,\n inspectCredentialsEnvFile,\n} from '../utils/credentials.js';\nimport {\n checkDevelopmentProjectInputs,\n productionRuntimeKeyGuidance,\n provisionDevelopmentCredentials,\n resolveDevelopmentProject,\n signInForSetup,\n} from '../setup/developmentCredentials.js';\nimport { exitIfUnsupportedSetupTarget } from '../setup/setupTarget.js';\nimport {\n asRecord,\n attachConfigureFlags,\n attachInitFlags,\n describeDefaults,\n displaySetupHeader,\n getConfiguredFramework,\n INIT_SOURCE_HELP,\n installWithProgress,\n OnboardingError,\n parseFilePatterns,\n readSetupConfig,\n reportJsonExitsBeforeOnboarding,\n resolvePackageManager,\n runOnboarding,\n setupConfigPath,\n validateSetupPattern,\n type ConfigureOptions,\n type InitOptions,\n type OnboardingSession,\n} from '../setup/onboarding.js';\nimport { upload } from './commands/upload.js';\nimport { attachSharedFlags, attachTranslateFlags } from './flags.js';\nimport { handleStage } from './commands/stage.js';\nimport { handleSetupProject } from './commands/setupProject.js';\nimport { handleDownload } from './commands/download.js';\nimport {\n handleTranslate,\n postProcessTranslations,\n} from './commands/translate.js';\nimport {\n getNeedsPostprocessing,\n clearDownloaded,\n} from '../state/recentDownloads.js';\nimport { clearWarnings } from '../state/translateWarnings.js';\nimport { displayTranslateSummary } from '../console/displayTranslateSummary.js';\nimport updateConfig from '../fs/config/updateConfig.js';\nimport {\n createLoadTranslationsFile,\n findLoadTranslationsFiles,\n} from '../fs/createLoadTranslationsFile.js';\nimport { saveLocalEdits } from '../api/saveLocalEdits.js';\nimport { resolveProjectId } from '../fs/utils.js';\nimport {\n hasValidCredentials,\n hasValidServiceLocales,\n} from './commands/utils/validation.js';\nimport processSharedStaticAssets, {\n mirrorAssetsToLocales,\n} from '../utils/sharedStaticAssets.js';\nimport { setupLocadex } from '../locadex/setupFlow.js';\nimport { detectFramework } from '../setup/detectFramework.js';\nimport { INLINE_LIBRARIES, Libraries } from '../types/libraries.js';\nimport { handleEnqueue } from './commands/enqueue.js';\nimport { splitMintlifyLanguageRefs } from '../utils/splitMintlifyLanguageRefs.js';\nimport { runMergeDriver } from '../git/mergeDrivers.js';\nimport { setupGitMergeDrivers } from '../git/setupMergeDrivers.js';\nimport { warnReactPackageCompatibility } from '../utils/reactPackageCompatibility.js';\nimport {\n createDiagnosticMessage,\n formatDiagnosticErrorDetails,\n} from 'generaltranslation/diagnostics';\nimport { hasLogin, logout, whoAmI } from '../auth/oauth.js';\nimport { createUserAuthError, UserAuthError } from '../auth/errors.js';\nimport { loginInteractively } from '../auth/interactiveLogin.js';\nimport { resolveConfig } from '../config/resolveConfig.js';\nimport { loadConfig, withJsonExtension } from '../fs/config/loadConfig.js';\nimport {\n getBuildToolSetup,\n type ManualAction,\n type SetupResult,\n} from '../setup/buildTools/index.js';\nimport { manifestDirectlyDeclaresGTVue } from '@generaltranslation/vue-extractor/integration';\nimport { api } from '../utils/api.js';\nimport { handleApiCommand, type ApiCommandOptions } from './commands/api.js';\n\nconst ID_COMPATIBILITY_WARNING_COMMANDS = new Set([\n 'download',\n 'enqueue',\n 'generate',\n 'setup',\n 'stage',\n 'translate',\n 'validate',\n]);\nfunction createProjectCommandError(\n whatHappened: string,\n error: unknown\n): string {\n return createDiagnosticMessage({\n source: 'gt',\n severity: 'Error',\n whatHappened,\n details: formatDiagnosticErrorDetails(error),\n });\n}\n\nconst emptyApiKeyNameError = createDiagnosticMessage({\n whatHappened: 'The key name cannot be empty',\n fix: 'Pass a non-empty value with --name',\n});\n\nfunction parseApiKeyName(value: string): string {\n const name = value.trim();\n if (!name) throw new InvalidArgumentError(emptyApiKeyNameError);\n return name;\n}\n\n/** Credential failures keep their own diagnostic or get the setup context. */\nasync function withCredentialsError<T>(run: () => Promise<T>): Promise<T> {\n try {\n return await run();\n } catch (error) {\n if (error instanceof OnboardingError) throw error;\n throw new Error(\n error instanceof UserAuthError\n ? error.message\n : createProjectCommandError(\n 'Failed to set up the development credentials',\n error\n )\n );\n }\n}\n\nexport type UploadOptions = {\n config?: string;\n apiKey?: string;\n projectId?: string;\n defaultLocale?: string;\n};\n\nexport type GitSetupOptions = {\n config?: string;\n dryRun?: boolean;\n omitConfigIds?: boolean;\n driverCommand?: string;\n};\n\ntype LocalTranslationGuidanceOptions = {\n generatedLoader: boolean;\n runtimeSetup: InlineRuntimeSetup;\n translationsDir: string;\n};\n\ntype InlineRuntimeSetup = {\n hasOtherInlineRuntime: boolean;\n hasVueRuntime: boolean;\n ranReactSetup: boolean;\n};\n\nexport class BaseCLI {\n protected library: SupportedLibraries;\n protected additionalModules: SupportedLibraries[];\n protected program: Command;\n // Constructor is shared amongst all CLI class types\n public constructor(\n program: Command,\n library: SupportedLibraries,\n additionalModules?: SupportedLibraries[]\n ) {\n this.program = program;\n this.library = library;\n this.additionalModules = additionalModules || [];\n\n this.program.option(\n '--skip-version-check',\n 'Skip the monorepo GT package version consistency check'\n );\n this.program.option(\n '--suppress-id-compatibility-warning',\n 'Suppress the React package ID compatibility warning'\n );\n this.program.option(\n '-q, --quiet',\n 'Suppress informational output; only warnings and errors are shown'\n );\n // Select console routing for this command before anything else logs:\n // root hooks run before subclass hooks (version checks) and the action's\n // settings resolution. `gt api-key create` prints the new secret on\n // stdout, so its diagnostics go to stderr, as do setup commands writing\n // JSON events; every other command gets the historical default back\n // (main() routes startup output to stderr).\n this.program.hook('preAction', (thisCommand, actionCommand) => {\n logger.setConsoleOutput(\n actionCommand.parent?.name() === 'api-key' || actionCommand.opts().json\n ? 'stderr'\n : 'stdout'\n );\n if (\n actionCommand.opts().json &&\n actionCommand.parent === thisCommand &&\n ['init', 'configure'].includes(actionCommand.name())\n ) {\n reportJsonExitsBeforeOnboarding(actionCommand.name());\n }\n });\n // Apply --quiet before any other hook or command action runs so the\n // singleton logger is muted for the rest of the invocation. The flag is a\n // global root option, so commander resolves it in any position and for\n // nested commands (e.g. `gt git setup --quiet`).\n this.program.hook('preAction', () => {\n logger.setQuiet(Boolean(this.program.opts().quiet));\n });\n this.program.hook('preAction', async (thisCommand, actionCommand) => {\n // Nested commands (e.g. `gt git setup`) can share leaf names with\n // translation commands; only direct children of the root qualify\n if (actionCommand.parent !== thisCommand) return;\n if (!ID_COMPATIBILITY_WARNING_COMMANDS.has(actionCommand.name())) return;\n await warnReactPackageCompatibility(\n Boolean(this.program.opts().suppressIdCompatibilityWarning)\n );\n });\n\n this.setupInitCommand();\n this.setupConfigureCommand();\n this.setupUploadCommand();\n this.setupUserAuthCommands();\n this.setupSendDiffsCommand();\n this.setupApiCommand();\n this.setupProjectCommands();\n this.setupApiKeyCommands();\n this.setupGitCommand();\n }\n // Init is never called in a child class\n public init() {\n this.setupSetupProjectCommand();\n this.setupStageCommand();\n this.setupTranslateCommand();\n this.setupDownloadCommand();\n this.setupEnqueueCommand();\n }\n // Execute is called by the main program\n public execute() {\n // If no command is specified, run 'init'\n if (process.argv.length <= 2) {\n process.argv.push('init');\n }\n }\n\n protected setupSetupProjectCommand(): void {\n attachTranslateFlags(\n this.program\n .command('setup')\n .description(\n 'Upload source files and setup the project for translation'\n )\n ).action(async (initOptions: TranslateFlags) => {\n displayHeader('Uploading source files and setting up project...');\n await this.handleSetupProject(initOptions);\n logger.endCommand('Done!');\n });\n }\n\n protected setupStageCommand(): void {\n attachTranslateFlags(\n this.program\n .command('stage')\n .description(\n 'Submits the project to the General Translation API for translation. Translations created using this command will require human approval.'\n )\n ).action(async (initOptions: TranslateFlags) => {\n displayHeader(\n 'Staging project for translation with approval required...'\n );\n await this.handleStage(initOptions);\n logger.endCommand('Done!');\n });\n }\n\n /**\n * Enqueues translations for a given set of files\n * @param initOptions - The options for the command\n * @returns The results of the command\n */\n protected setupEnqueueCommand(): void {\n attachTranslateFlags(\n this.program\n .command('enqueue')\n .description('Enqueues translations for a given set of files')\n ).action(async (initOptions: TranslateFlags) => {\n displayHeader('Enqueuing translations...');\n await this.handleEnqueue(initOptions);\n logger.endCommand('Done!');\n });\n }\n\n /**\n * Downloads translations that were originally staged\n * @param initOptions - The options for the command\n * @returns The results of the command\n */\n protected setupDownloadCommand(): void {\n attachTranslateFlags(\n this.program\n .command('download')\n .description('Download translations that were originally staged')\n ).action(async (initOptions: TranslateFlags) => {\n displayHeader('Downloading translations...');\n await this.handleDownload(initOptions);\n logger.endCommand('Done!');\n });\n }\n\n protected setupTranslateCommand(): void {\n attachTranslateFlags(\n this.program\n .command('translate')\n .description('Translate your project using General Translation')\n ).action(async (initOptions: TranslateFlags) => {\n displayHeader('Starting translation...');\n await this.handleTranslate(initOptions);\n logger.endCommand('Done!');\n });\n }\n\n protected setupSendDiffsCommand(): void {\n attachSharedFlags(\n this.program\n .command('save-local')\n .description(\n 'Save local edits for all configured files by sending diffs (no translation enqueued)'\n )\n )\n .option('--publish', 'Publish translations to the CDN', false)\n .action(async (initOptions: SharedFlags) => {\n displayHeader('Saving local edits...');\n const settings = await generateSettings(initOptions, undefined, {\n requireConfig: true,\n });\n if (!hasValidCredentials(settings) || !hasValidServiceLocales(settings))\n return exitSync(1);\n await saveLocalEdits(settings);\n logger.endCommand('Saved local edits');\n });\n }\n\n protected setupApiCommand(): void {\n attachSharedFlags(\n this.program\n .command('api [endpoint]')\n .description('Make an authenticated request to the GT API')\n .option('-X, --method <method>', 'HTTP method', 'GET')\n .option('--input <file>', 'Request body file, or - for standard input')\n .option(\n '-H, --header <header>',\n 'Request header in \"Key: Value\" format',\n (header, headers: string[] | undefined) => [\n ...(headers ?? []),\n header,\n ]\n )\n .option('-i, --include', 'Include response status and headers')\n .option('--spec', 'Print the bundled OpenAPI specification')\n ).action((endpoint, options: ApiCommandOptions) =>\n handleApiCommand(endpoint, options)\n );\n }\n\n protected setupProjectCommands(): void {\n const projectCommand = this.program\n .command('project')\n .description('Manage General Translation projects');\n\n attachSharedFlags(\n projectCommand\n .command('create')\n .description(\n 'Create a General Translation project using an organization API key'\n )\n .requiredOption('--org-id <orgId>', 'Organization ID')\n .requiredOption('--name <name>', 'Project name')\n .requiredOption('--default-locale <locale>', 'Project default locale')\n .option('--cdn-enabled', 'Enable CDN delivery', false)\n ).action(async (options) => {\n try {\n const settings = await generateSettings(options);\n // Project creation happens before a project ID exists.\n if (!hasValidServiceLocales(settings)) return exitSync(1);\n const { project } = await api.createProject(options.orgId, {\n name: options.name,\n defaultLocale: options.defaultLocale,\n cdnEnabled: options.cdnEnabled,\n });\n logger.info(`Created ${project.name} (${project.id})`);\n } catch (error) {\n return logErrorAndExit(\n createProjectCommandError('Failed to create the project', error)\n );\n }\n });\n\n attachSharedFlags(\n projectCommand\n .command('status')\n .description('Check the status of a project setup job')\n .argument('<job-id>', 'Setup job ID')\n ).action(async (jobId, options) => {\n try {\n const settings = await generateSettings(options);\n if (!hasValidCredentials(settings)) return exitSync(1);\n const [status] = await api.checkJobStatus([jobId]);\n logger.info(status?.status ?? 'unknown');\n } catch (error) {\n return logErrorAndExit(\n createProjectCommandError(\n 'Failed to check the project setup status',\n error\n )\n );\n }\n });\n }\n\n protected setupApiKeyCommands(): void {\n const apiKeyCommand = this.program\n .command('api-key')\n .description('Manage API keys for the configured project');\n\n attachSharedFlags(\n apiKeyCommand\n .command('create')\n .description(\n 'Create a project API key with the requested permissions and print it once'\n )\n .requiredOption('--name <name>', 'Key name', parseApiKeyName)\n // Validated before any request; the server grants the requested set\n // all-or-nothing, so omitting permissions would delegate everything.\n .addOption(\n new Option('--permission <permissions...>', 'Permissions to grant')\n .choices(Object.values(ProjectApiKeyPermission))\n .makeOptionMandatory()\n )\n ).action(\n async (\n options: SharedFlags & {\n name: string;\n permission: ProjectApiKeyPermission[];\n }\n ) => {\n try {\n const settings = await generateSettings(options);\n if (!hasValidCredentials(settings)) return exitSync(1);\n const { apiKey } = await api.createProjectApiKey(settings.projectId, {\n name: options.name,\n permissions: options.permission,\n });\n // Raw stdout: the secret is shown once and never reaches the log file.\n process.stdout.write(`${apiKey.key}\\n`);\n } catch (error) {\n return logErrorAndExit(\n error instanceof UserAuthError\n ? error.message\n : createProjectCommandError('Failed to create the API key', error)\n );\n }\n }\n );\n }\n\n protected setupGitCommand(): void {\n const gitCommand = this.program\n .command('git')\n .description('Configure Git integrations for General Translation');\n\n gitCommand\n .command('setup')\n .description('Set up GT merge drivers for generated translation files')\n .option(\n '-c, --config <path>',\n 'Filepath to config file, by default gt.config.json',\n findFilepath(['gt.config.json'])\n )\n .option('--dry-run', 'Print changes without writing files', false)\n .option(\n '--omit-config-ids',\n 'Persist omitConfigIds and remove generated config IDs'\n )\n .option(\n '--driver-command <command>',\n 'Command Git should use to invoke gt, e.g. \"pnpm exec gt\"'\n )\n .action(async (options: GitSetupOptions) => {\n displayHeader('Setting up GT Git merge drivers...');\n const settings = await generateSettings(options, undefined, {\n requireConfig: true,\n });\n const omitConfigIds = await this.resolveGitSetupOmitConfigIds(\n options,\n settings\n );\n const result = await setupGitMergeDrivers(settings, {\n dryRun: options.dryRun,\n omitConfigIds,\n driverCommand: options.driverCommand,\n });\n\n for (const line of result.addedAttributes) {\n logger.step(\n `${options.dryRun ? 'Would add' : 'Added'} ${chalk.cyan(\n line\n )} to ${chalk.cyan(result.gitattributesPath)}`\n );\n }\n if (result.addedAttributes.length === 0) {\n logger.info(`${chalk.cyan('.gitattributes')} is already configured.`);\n }\n\n for (const args of result.gitConfigCommands) {\n logger.step(\n `${options.dryRun ? 'Would run' : 'Configured'} ${chalk.cyan(\n `git config --local ${args.join(' ')}`\n )}`\n );\n }\n\n if (result.updatedConfig) {\n logger.step(\n `${options.dryRun ? 'Would persist' : 'Persisted'} ${chalk.cyan(\n 'omitConfigIds: true'\n )} in ${chalk.cyan(settings.config)}`\n );\n } else if (options.dryRun && !settings.omitConfigIds) {\n logger.info(\n `Run without ${chalk.cyan('--dry-run')} to be prompted to persist ${chalk.cyan(\n 'omitConfigIds: true'\n )}, or pass ${chalk.cyan('--omit-config-ids')}.`\n );\n }\n\n for (const warning of result.warnings) {\n logger.warn(chalk.yellow(warning));\n }\n\n logger.endCommand(\n options.dryRun\n ? 'Dry run complete.'\n : 'GT Git merge drivers configured.'\n );\n });\n\n gitCommand\n .command('merge-driver', { hidden: true })\n .argument('<driver>', 'Merge driver name')\n .argument('<base>', 'Common ancestor file')\n .argument('<ours>', 'Current branch file')\n .argument('<theirs>', 'Incoming branch file')\n .argument('[path]', 'Merged path')\n .action((driver: string, base: string, ours: string, theirs: string) => {\n if (driver !== 'gt-lock' && driver !== 'gtjson') {\n logger.error(`Unknown GT merge driver: ${driver}`);\n exitSync(1);\n }\n const result = runMergeDriver(driver, base, ours, theirs);\n if (!result.ok) {\n logger.error(result.reason);\n exitSync(1);\n }\n });\n }\n\n protected async resolveGitSetupOmitConfigIds(\n options: GitSetupOptions,\n settings: Settings\n ): Promise<boolean> {\n if (options.omitConfigIds) return true;\n // Already opted in: persist again so stale config IDs still get removed\n if (settings.omitConfigIds) return true;\n if (options.dryRun || !process.stdin.isTTY || !process.stdout.isTTY) {\n return false;\n }\n return promptConfirm({\n message:\n 'Also set omitConfigIds: true to reduce gt.config.json merge conflicts?',\n defaultValue: true,\n });\n }\n\n protected async handleSetupProject(\n initOptions: TranslateFlags\n ): Promise<void> {\n const settings = await generateSettings(initOptions, undefined, {\n requireConfig: true,\n });\n\n // Preprocess shared static assets if configured (move + rewrite sources)\n await processSharedStaticAssets(settings);\n\n await handleSetupProject(initOptions, settings, this.library);\n }\n\n protected async handleStage(initOptions: TranslateFlags): Promise<void> {\n const settings = await generateSettings(initOptions, undefined, {\n requireConfig: true,\n });\n\n // Preprocess shared static assets if configured (move + rewrite sources)\n await processSharedStaticAssets(settings);\n\n if (!settings.stageTranslations) {\n // Update settings.stageTranslations to true\n settings.stageTranslations = true;\n await updateConfig(settings.config, {\n stageTranslations: true,\n });\n }\n await handleStage(initOptions, settings, this.library, true);\n }\n\n /**\n * Enqueues translations for a given set of files\n * @param initOptions - The options for the command\n * @returns The results of the command\n */\n protected async handleEnqueue(initOptions: TranslateFlags): Promise<void> {\n const settings = await generateSettings(initOptions, undefined, {\n requireConfig: true,\n });\n await handleEnqueue(initOptions, settings, this.library);\n }\n\n /**\n * Downloads translations that were originally staged\n * @param initOptions - The options for the command\n * @returns The results of the command\n */\n protected async handleDownload(initOptions: TranslateFlags): Promise<void> {\n const settings = await generateSettings(initOptions, undefined, {\n requireConfig: true,\n });\n await handleDownload(initOptions, settings, this.library);\n }\n\n protected async handleTranslate(initOptions: TranslateFlags): Promise<void> {\n const settings = await generateSettings(initOptions, undefined, {\n requireConfig: true,\n });\n\n // Preprocess shared static assets if configured (move + rewrite sources)\n await processSharedStaticAssets(settings);\n\n if (!settings.stageTranslations) {\n // Lottie translations finish asynchronously server-side (layout\n // refinement runs after the translation job completes), so the immediate\n // translate flow would try to download them before they're ready. Only\n // the stage + download flow supports them.\n if (settings.files?.resolvedPaths.lottie?.length) {\n return logErrorAndExit(lottieTranslateError);\n }\n const results = await handleStage(\n initOptions,\n settings,\n this.library,\n false\n );\n if (results) {\n await handleTranslate(\n initOptions,\n settings,\n results.fileVersionData,\n results.jobData,\n results.branchData,\n results.publishMap,\n results.inlineLibrary\n );\n }\n } else {\n await handleDownload(initOptions, settings, this.library);\n }\n // Only postprocess files downloaded in this run\n const include = getNeedsPostprocessing();\n if (include.size > 0) {\n await postProcessTranslations(settings, include);\n }\n // Split Mintlify language entries into $ref files to keep docs.json small\n await splitMintlifyLanguageRefs(settings);\n // Mirror assets after translations are downloaded and locale dirs are populated\n await mirrorAssetsToLocales(settings);\n clearDownloaded();\n displayTranslateSummary();\n clearWarnings();\n }\n\n protected setupUploadCommand(): void {\n attachTranslateFlags(\n this.program\n .command('upload')\n .description(\n 'Upload source files and translations to the General Translation platform'\n )\n ).action(async (initOptions: UploadOptions) => {\n displayHeader('Starting upload...');\n const settings = await generateSettings(initOptions, undefined, {\n requireConfig: true,\n });\n\n const options = { ...initOptions, ...settings };\n\n await this.handleUploadCommand(options);\n logger.endCommand('Done!');\n });\n }\n\n protected setupUserAuthCommands(): void {\n this.program\n .command('login')\n .description('Sign in to your General Translation account')\n .option(\n '--no-browser',\n 'Do not open a browser; show a sign-in URL to use on any device instead'\n )\n .option(\n '-c, --config <path>',\n 'Filepath to config file, by default gt.config.json'\n )\n .action(async (options: { browser: boolean; config?: string }) => {\n displayHeader('Signing in to General Translation...');\n try {\n // Tokens are bound to one API resource, so log in to the configured one.\n const baseUrl = (\n options.config\n ? loadConfig(withJsonExtension(options.config))\n : resolveConfig(process.cwd())?.config\n )?.baseUrl;\n await loginInteractively(\n typeof baseUrl === 'string' ? baseUrl : undefined,\n options.browser\n );\n logger.endCommand('You are now signed in.');\n } catch (error) {\n logErrorAndExit(createUserAuthError('Sign in failed', error));\n }\n });\n\n this.program\n .command('logout')\n .description('Sign out of your General Translation account')\n .action(async () => {\n try {\n await logout();\n logger.endCommand('Signed out successfully.');\n } catch (error) {\n logErrorAndExit(createUserAuthError('Sign out failed', error));\n }\n });\n\n this.program\n .command('whoami')\n .description('Show the signed-in General Translation account')\n .action(async () => {\n try {\n const user = await whoAmI();\n logger.message(user.email ?? user.name ?? user.sub);\n } catch (error) {\n logErrorAndExit(\n createUserAuthError('Could not load your account', error)\n );\n }\n });\n }\n\n protected setupInitCommand(): void {\n attachInitFlags(\n this.program\n .command('init')\n .description(\n 'Run the setup wizard to configure your project for General Translation. Flags answer its questions; unanswered ones are asked, or listed as missing with --no-interactive'\n ),\n INIT_SOURCE_HELP\n ).action((options: InitOptions) => this.handleInitWizard(options));\n }\n\n protected async handleInitWizard(options: InitOptions): Promise<void> {\n await runOnboarding('init', options, async (session) => {\n await exitIfUnsupportedSetupTarget();\n displaySetupHeader(session, 'Running setup wizard...');\n\n const detected = await detectFramework();\n const reactDetected = detected.type === 'react' ? detected : undefined;\n if (options.framework && !reactDetected) {\n session.reject(\n '--framework applies only to projects detected as React applications'\n );\n }\n const configFilepath = setupConfigPath(options);\n const configured = getConfiguredFramework(\n readSetupConfig(configFilepath)\n );\n const configuredReact =\n configured !== 'mintlify' ? configured : undefined;\n // Explicit --defaults / --no-defaults also answer the Locadex gate.\n if (options.defaults !== undefined) session.defaults = options.defaults;\n const gateFramework = options.framework ?? configured ?? detected.name;\n if (gateFramework === 'mintlify' || gateFramework === 'next-app') {\n const useLocadex = await session.answer('--locadex', {\n explicit: options.locadex,\n recommended: false,\n ask: () =>\n promptConfirm({\n message:\n gateFramework === 'mintlify'\n ? `Mintlify project detected. Would you like to connect to GitHub so that the Locadex AI Agent can translate your project automatically?`\n : `Next.js App Router detected. Would you like to connect to GitHub so that the Locadex AI Agent can set up your project automatically?`,\n defaultValue: false,\n }),\n });\n if (useLocadex) {\n session.assertResolved();\n const url = await setupLocadex(\n await generateSettings({ config: options.config }),\n { openBrowser: session.interactive }\n );\n session.emit({ type: 'handoff', url, reason: 'locadex' });\n logger.endCommand(\n 'Once installed, Locadex will open a PR to your repository. See the docs for more information: https://generaltranslation.com/docs/locadex'\n );\n return { outcome: 'needs_human_action', url };\n }\n } else if (options.locadex) {\n session.reject(\n '--locadex applies only to Mintlify and Next.js App Router projects'\n );\n }\n\n const shownFramework = reactDetected && {\n ...reactDetected,\n name: options.framework ?? configuredReact ?? reactDetected.name,\n };\n // Without --defaults, a noninteractive run uses no defaults.\n session.defaults =\n (await session.answer('--defaults', {\n explicit: options.defaults,\n fallback: false,\n ask: () =>\n promptConfirm({\n message: `Would you like to use the recommended General Translation defaults? ${chalk.dim(`(${describeDefaults(shownFramework)})`)}`,\n defaultValue: true,\n }),\n })) === true;\n\n const reactSetup = reactDetected\n ? await resolveReactSetup(\n session,\n options,\n reactDetected,\n configuredReact\n )\n : undefined;\n // flag > gt.config.json > detection, used for every later step.\n const framework =\n reactSetup?.framework ??\n options.framework ??\n configured ??\n detected.name;\n await this.handleInitCommand(session, options, {\n configFilepath,\n framework,\n saveFramework: Boolean(reactSetup || options.framework),\n reactSetup,\n keepAppSource: !reactSetup,\n });\n\n logger.endCommand(\n 'Done! Check out our docs for more information on how to use General Translation: https://generaltranslation.com/docs'\n );\n return { outcome: 'success' };\n });\n }\n\n protected setupConfigureCommand(): void {\n attachConfigureFlags(\n this.program\n .command('configure')\n .description(\n 'Configure your project for General Translation. This will create a gt.config.json file in your codebase. Flags answer its questions; unanswered ones are asked, or listed as missing with --no-interactive'\n ),\n INIT_SOURCE_HELP\n ).action((options: ConfigureOptions) =>\n this.handleConfigureCommand(options)\n );\n }\n\n protected async handleConfigureCommand(\n options: ConfigureOptions,\n command: string = 'configure'\n ): Promise<void> {\n await runOnboarding(command, options, async (session) => {\n await exitIfUnsupportedSetupTarget();\n displaySetupHeader(session, 'Configuring project...');\n\n logger.info(\n 'Welcome! This tool will help you configure your gt.config.json file. See the docs: https://generaltranslation.com/docs/cli/reference/config for more information.'\n );\n\n // Configure only offers the defaults when asked with --defaults.\n session.defaults = options.defaults ?? false;\n const detected = await detectFramework();\n const configFilepath = setupConfigPath(options);\n // Detection only picks env names here; it is not saved.\n const framework =\n getConfiguredFramework(readSetupConfig(configFilepath)) ??\n detected.name;\n await this.handleInitCommand(session, options, {\n configFilepath,\n framework,\n });\n\n logger.endCommand(\n 'Done! Make sure you have an API key and project ID to use General Translation. Get them on the dashboard: https://generaltranslation.com/dashboard'\n );\n return { outcome: 'success' };\n });\n }\n\n protected async handleUploadCommand(\n settings: Settings & UploadOptions\n ): Promise<void> {\n if (!settings.files) {\n return;\n }\n\n // Process all file types at once with a single call\n await upload(settings);\n }\n\n /** Describes installed runtimes without changing historical package lookup. */\n protected getInlineRuntimeSetup(\n packageJson: Record<string, unknown>,\n ranReactSetup: boolean = false\n ): InlineRuntimeSetup {\n return {\n hasOtherInlineRuntime: INLINE_LIBRARIES.some(\n (lib) =>\n lib !== Libraries.GT_VUE && isPackageInstalled(lib, packageJson)\n ),\n hasVueRuntime: manifestDirectlyDeclaresGTVue(packageJson),\n ranReactSetup,\n };\n }\n\n /** Returns whether any inline runtime is installed for setup. */\n protected isInlineRuntimeInstalled(\n packageJson: Record<string, unknown>\n ): boolean {\n const { hasOtherInlineRuntime, hasVueRuntime } =\n this.getInlineRuntimeSetup(packageJson);\n return hasOtherInlineRuntime || hasVueRuntime;\n }\n\n /** Returns whether every installed runtime can consume CDN translations. */\n protected supportsCDNStorage(runtimeSetup: InlineRuntimeSetup): boolean {\n return !runtimeSetup.hasVueRuntime;\n }\n\n /** Returns whether setup should generate a local runtime loader. */\n protected shouldGenerateLocalTranslationLoader(\n buildToolOwnsLoader: boolean,\n runtimeSetup: InlineRuntimeSetup\n ): boolean {\n if (buildToolOwnsLoader) return false;\n if (!runtimeSetup.hasVueRuntime) return true;\n return runtimeSetup.hasOtherInlineRuntime || runtimeSetup.ranReactSetup;\n }\n\n /** Returns framework guidance after selecting local translation storage. */\n protected getLocalTranslationGuidance({\n generatedLoader,\n runtimeSetup,\n translationsDir,\n }: LocalTranslationGuidanceOptions): string | undefined {\n const guidance: string[] = [];\n if (generatedLoader) {\n guidance.push(`Created ${chalk.cyan('loadTranslations.js')} file for local translations.\nMake sure to add this function to your app configuration.\nSee https://generaltranslation.com/en/docs/next/guides/local-tx`);\n }\n if (runtimeSetup.hasVueRuntime) {\n guidance.push(`GT will write local translation files to ${translationsDir}.\nConfigure createGT({ loadTranslations }) to load files from that directory.\nSee https://www.npmjs.com/package/gt-vue`);\n }\n return guidance.length > 0 ? guidance.join('\\n') : undefined;\n }\n\n /**\n * Resolves every configuration answer and validates the resulting config,\n * checks the project and signs in before the first change, then applies\n * the React setup, gt.config.json, installs and development credentials.\n */\n protected async handleInitCommand(\n session: OnboardingSession,\n options: ConfigureOptions,\n setup: {\n /** Chosen once by the entry point from the detected framework. */\n configFilepath: string;\n /** Resolved framework; drives storage, env names and build-tool setup. */\n framework?: SupportedFrameworks;\n /** Write the framework even when no build-tool setup saves it. */\n saveFramework?: boolean;\n reactSetup?: ReactSetupPlan;\n /** Init without the React setup never changes application source. */\n keepAppSource?: boolean;\n }\n ): Promise<void> {\n const { configFilepath, reactSetup } = setup;\n const buildTool = getBuildToolSetup(setup.framework);\n const cwd = process.cwd();\n const existingConfig = readSetupConfig(configFilepath);\n const { defaultLocale, locales } = await getDesiredLocales(\n session,\n existingConfig,\n options\n );\n\n const packageJson =\n reactSetup?.packageJson ?? (await searchForPackageJson());\n const runtimeSetup: InlineRuntimeSetup = packageJson\n ? this.getInlineRuntimeSetup(packageJson, Boolean(reactSetup))\n : {\n hasOtherInlineRuntime: false,\n hasVueRuntime: false,\n ranReactSetup: false,\n };\n const isUsingGT =\n runtimeSetup.ranReactSetup ||\n runtimeSetup.hasOtherInlineRuntime ||\n runtimeSetup.hasVueRuntime;\n const supportsCDN = this.supportsCDNStorage(runtimeSetup);\n const existingFiles = asRecord(existingConfig.files) ?? {};\n const existingGtOutput = asRecord(existingFiles.gt)?.output;\n const configuredOutput =\n typeof existingGtOutput === 'string' ? existingGtOutput : undefined;\n const configuredStorage = configuredOutput\n ? 'local'\n : existingConfig.publish === true\n ? 'cdn'\n : undefined;\n\n if (isUsingGT && !supportsCDN && options.storage === 'cdn') {\n session.reject(\n 'gt-vue cannot load translations from the CDN; use --storage local'\n );\n }\n // Where GT translations are stored\n const storage = !isUsingGT\n ? undefined\n : !supportsCDN\n ? 'local'\n : await session.answer<'local' | 'cdn'>('--storage', {\n explicit: options.storage,\n configured: configuredStorage,\n recommended: 'local',\n ask: () =>\n promptSelect<'local' | 'cdn'>({\n message: `Would you like to save translation files locally or use the General Translation CDN to store them?`,\n options: [\n { value: 'local', label: 'Save locally' },\n { value: 'cdn', label: 'Use CDN' },\n ],\n defaultValue: 'local',\n }),\n });\n\n const defaultTranslationsDir =\n buildTool?.defaultTranslationsDir ?? DEFAULT_TRANSLATIONS_DIR;\n const outputMatch = configuredOutput?.match(\n /^(?:(.+)[\\\\/])?\\[locale\\]\\.json$/\n );\n const configuredTranslationsDir = outputMatch\n ? (outputMatch[1] ?? '.')\n : undefined;\n const translationsDir =\n storage === 'local'\n ? await session.answer('--translations-dir', {\n explicit: options.translationsDir?.trim() || undefined,\n configured: configuredTranslationsDir,\n recommended: defaultTranslationsDir,\n ask: async () =>\n (\n await promptText({\n message:\n 'What is the path to the directory where you would like to store your translation files?',\n defaultValue: defaultTranslationsDir,\n })\n ).trim() || defaultTranslationsDir,\n })\n : undefined;\n\n const filePatterns = parseFilePatterns(session, options.filePatterns);\n const selectedFormats = options.fileFormats?.filter(\n (format): format is SetupFileFormat => format !== 'none'\n );\n if (\n options.fileFormats?.includes('none') &&\n (selectedFormats?.length ?? 0) > 0\n ) {\n session.reject('--file-formats none cannot be combined with formats');\n }\n const configuredFormats = SETUP_FILE_FORMATS.filter(\n (format) => format in existingFiles\n );\n // Formats setup does not offer stay as configured and count as files.\n const otherFormats = SUPPORTED_FILE_EXTENSIONS.filter(\n (format) =>\n format in existingFiles &&\n !(SETUP_FILE_FORMATS as readonly string[]).includes(format)\n );\n const hasOtherFormats = otherFormats.length > 0;\n if (options.fileFormats && hasOtherFormats) {\n const kept = otherFormats.map((format) => `files.${format}`).join(', ');\n logger.warn(\n createDiagnosticMessage({\n source: 'gt',\n severity: 'Warning',\n whatHappened: `${kept} stays in ${configFilepath}`,\n why: '--file-formats only changes the formats setup offers',\n fix: `Remove ${kept} from ${configFilepath} to stop translating those files`,\n })\n );\n }\n const fileFormats = await session.answer<SetupFileFormat[]>(\n '--file-formats',\n {\n explicit:\n selectedFormats ??\n (filePatterns.size > 0 ? [...filePatterns.keys()] : undefined),\n configured:\n configuredFormats.length > 0 || hasOtherFormats\n ? configuredFormats\n : undefined,\n // GT projects need no other files; others must choose a format.\n recommended: isUsingGT ? [] : undefined,\n ask: () =>\n promptMultiSelect({\n message: !isUsingGT\n ? 'What is the format of your language resource files? Select as many as applicable.\\nAdditionally, you can translate any other files you have in your project.'\n : `Do you have any additional files in this project to translate? For example, Markdown files for docs. ${chalk.dim(\n '(To continue without selecting press Enter)'\n )}`,\n options: SETUP_FILE_FORMATS.map((format) => ({\n value: format,\n label: FILE_EXT_TO_EXT_LABEL[format],\n })),\n required: !isUsingGT,\n }),\n }\n );\n if (\n fileFormats &&\n fileFormats.length === 0 &&\n !isUsingGT &&\n !hasOtherFormats\n ) {\n session.reject(\n 'No GT runtime is installed, so select at least one file format to translate'\n );\n }\n for (const format of filePatterns.keys()) {\n if (fileFormats && !fileFormats.includes(format)) {\n session.reject(\n `--file-patterns ${format}= needs ${format} in --file-formats`\n );\n }\n }\n\n const files: FilesOptions = {};\n for (const fileExtension of fileFormats ?? []) {\n const existingFormat = asRecord(existingFiles[fileExtension]);\n const configuredInclude = Array.isArray(existingFormat?.include)\n ? (existingFormat.include as string[])\n : undefined;\n const include = await session.answer(\n `--file-patterns ${fileExtension}=<glob>`,\n {\n explicit: filePatterns.get(fileExtension),\n configured: configuredInclude,\n recommended: [`./**/[locale]/*.${fileExtension}`],\n ask: async () =>\n parseGlobPatterns(\n await promptGlobPatterns({\n label: FILE_EXT_TO_EXT_LABEL[fileExtension],\n message: `${chalk.cyan(FILE_EXT_TO_EXT_LABEL[fileExtension])}: Enter a space-separated list of glob patterns matching the location of the ${FILE_EXT_TO_EXT_LABEL[fileExtension]} files you would like to translate.\\nMake sure to include [locale] in the patterns.\\nSee https://generaltranslation.com/docs/cli/reference/config#include for more information.`,\n defaultValue: `./**/[locale]/*.${fileExtension}`,\n validate: (value) =>\n parseGlobPatterns(value)\n .map(validateSetupPattern)\n .find((problem) => problem !== true) ?? true,\n })\n ),\n }\n );\n // Configured patterns stay untouched; new ones keep other entry options.\n if (include && include !== configuredInclude) {\n files[fileExtension] = { ...existingFormat, include };\n }\n }\n if (translationsDir && translationsDir !== configuredTranslationsDir) {\n files.gt = { output: path.join(translationsDir, `[locale].json`) };\n }\n\n const envFramework =\n setup.framework ?? getConfiguredFramework(existingConfig);\n // The effective project: an explicit ID replaces a configured one. The\n // framework's runtime project outranks a stale generic GT_PROJECT_ID.\n const projectId =\n options.projectId ||\n (typeof existingConfig.projectId === 'string'\n ? existingConfig.projectId\n : undefined) ||\n process.env[getDevelopmentEnvNames(envFramework).projectId];\n const configUpdate: SetupConfigUpdate = {\n defaultLocale,\n locales,\n src: options.src,\n files: Object.keys(files).length > 0 ? files : undefined,\n framework:\n (setup.saveFramework && setup.framework) || buildTool?.framework,\n publish: storage === 'cdn',\n // Selecting local storage drops stale CDN intent; a config that\n // already combines local files with publishing keeps it.\n clearPublish:\n storage === 'local' &&\n (options.storage === 'local' ||\n configuredStorage !== 'local' ||\n !supportsCDN),\n // An explicit switch to the CDN stops later runs inferring local files.\n clearGtOutput: storage === 'cdn' && configuredOutput !== undefined,\n // An explicit format list replaces the configured selection.\n removeFiles: selectedFormats\n ? configuredFormats.filter(\n (format) => !selectedFormats.includes(format)\n )\n : undefined,\n };\n session.assertResolved();\n\n // Validate what will be written, and use it for every later step.\n const { projectId: _writtenProjectId, ...effectiveConfig } =\n mergeSetupConfig(existingConfig, configUpdate);\n const settings = await generateSettings(\n { config: configFilepath, ...(projectId && { projectId }) },\n cwd,\n { resolvedConfig: effectiveConfig }\n );\n // Runtime credentials only count for the project this setup uses; the\n // framework's project variable is the one paired with its dev key.\n const runtimeProjectId =\n process.env[getDevelopmentEnvNames(envFramework).projectId] ??\n resolveProjectId();\n const runtimeProjectMatches =\n runtimeProjectId === undefined || runtimeProjectId === settings.projectId;\n const credentialsSet =\n runtimeProjectMatches && areCredentialsSet(settings, envFramework);\n const credentialsOption =\n (storage === 'local' && buildTool?.devCredentialsOption) ||\n '--dev-credentials';\n const provision =\n !credentialsSet &&\n (credentialsOption === '--live-translations'\n ? await session.answer('--live-translations', {\n explicit: options.liveTranslations ?? options.devCredentials,\n recommended: false,\n ask: () =>\n promptConfirm({\n message:\n 'Would you like to set up live development translations? This requires signing in or an API key.',\n defaultValue: false,\n }),\n })\n : await session.answer('--dev-credentials', {\n explicit: options.devCredentials,\n // Creating a key is never a default.\n ask: () =>\n promptConfirm({\n message:\n 'Would you like to set up a project ID and hot-reload key in .env.local?',\n defaultValue: true,\n }),\n })) === true;\n if (!runtimeProjectMatches && !provision) {\n session.reject(\n `The runtime credentials in the environment belong to project ${runtimeProjectId}, not ${settings.projectId}; pass --dev-credentials to replace them in .env.local`\n );\n }\n // An explicit ID is saved to gt.config.json when it replaces a\n // configured one or no new credentials will record it in .env.local.\n if (options.projectId && (existingConfig.projectId || !provision)) {\n configUpdate.projectId = options.projectId;\n }\n if (provision) {\n checkDevelopmentProjectInputs(\n session,\n settings,\n options,\n options.projectId\n ? '--project-id'\n : // An empty configured ID falls through to the environment.\n typeof existingConfig.projectId === 'string' &&\n existingConfig.projectId\n ? configFilepath\n : 'the environment'\n );\n await withCredentialsError(() =>\n inspectCredentialsEnvFile(cwd, { framework: envFramework })\n );\n }\n\n if (reactSetup && buildTool) await buildTool.preflight(cwd);\n const installGT =\n packageJson !== null &&\n !isPackageInstalled('gt', packageJson, true, true) &&\n !buildTool?.skipsGTInstall(isUsingGT);\n const packageManager =\n reactSetup?.install || installGT\n ? await resolvePackageManager(session, options.packageManager)\n : undefined;\n\n session.assertResolved();\n\n // Only creating credentials talks to GT, as the signed-in user unless an\n // API key is set. A development key in .env.local never stands in.\n if (\n provision &&\n !settings.apiKey &&\n !(await hasLogin({ baseUrl: settings.baseUrl }))\n ) {\n await signInForSetup(session, settings.baseUrl);\n }\n const project = provision\n ? await withCredentialsError(() =>\n resolveDevelopmentProject(session, settings, options, cwd)\n )\n : undefined;\n session.assertResolved();\n\n // ----- Changes start here ----- //\n const resolvedLocales = locales as string[];\n\n if (reactSetup) {\n logger.info(`${chalk.yellow('[EXPERIMENTAL]')} Configuring project...`);\n if (reactSetup.install && packageManager) {\n await installWithProgress(\n session,\n reactSetup.install,\n packageManager,\n false\n );\n }\n await executeReactSetup(session, reactSetup, options);\n logger.endCommand(\n `Done! Since this wizard is experimental, please review the changes and make modifications as needed.\n\\nNext step: start internationalizing! See the docs for more information: https://generaltranslation.com/docs/react/tutorials/quickstart`\n );\n logger.startCommand('Setting up project config...');\n }\n\n const reportManualAction = ({ whatHappened, fix }: ManualAction) => {\n session.humanActions.push(fix);\n logger.warn(\n createDiagnosticMessage({\n source: 'gt',\n severity: 'Warning',\n whatHappened,\n fix,\n })\n );\n };\n const reportSetupResult = ({ steps, manualActions }: SetupResult) => {\n for (const step of steps) session.step(step);\n manualActions.forEach(reportManualAction);\n };\n const translationFilesError = (error: unknown) =>\n new Error(\n createDiagnosticMessage({\n source: 'gt',\n severity: 'Error',\n whatHappened: `Could not create the translation files in ${translationsDir}`,\n details: formatDiagnosticErrorDetails(error),\n fix: 'Choose another --translations-dir or fix the path, then rerun the command',\n })\n );\n const buildToolContext = {\n appDirectory: cwd,\n configFilepath,\n defaultLocale: settings.defaultLocale,\n locales: resolvedLocales,\n translationsDir: storage === 'local' ? translationsDir : undefined,\n previousTranslationsDir: configuredTranslationsDir,\n };\n\n if (storage === 'local' && translationsDir) {\n if (buildTool && !reactSetup) {\n reportSetupResult(\n await buildTool\n .syncLoader({\n ...buildToolContext,\n translationsDir,\n keepAppSource: setup.keepAppSource,\n })\n .catch((error: unknown) => {\n throw translationFilesError(error);\n })\n );\n }\n const generatedLoader = this.shouldGenerateLocalTranslationLoader(\n buildTool?.ownsLoader ?? false,\n runtimeSetup\n );\n const loader = generatedLoader\n ? await createLoadTranslationsFile({\n appDirectory: cwd,\n translationsDir,\n defaultLocale: settings.defaultLocale,\n locales: resolvedLocales,\n previousTranslationsDir: configuredTranslationsDir,\n }).catch((error: unknown) => {\n throw translationFilesError(error);\n })\n : undefined;\n if (loader === 'created' || loader === 'updated') {\n session.step(`${loader} loadTranslations.js`);\n }\n // A loader left unchanged may not read the newly chosen directory.\n if (\n loader === 'custom' &&\n translationsDir !== configuredTranslationsDir\n ) {\n const loaderFile = path.relative(\n cwd,\n findLoadTranslationsFiles(cwd)[0] ?? 'loadTranslations.js'\n );\n reportManualAction({\n whatHappened: `Your custom ${loaderFile} was left unchanged, but translations now go to ${translationsDir}`,\n fix: `Update your custom ${loaderFile} to load translations from ${translationsDir}`,\n });\n }\n const guidance = this.getLocalTranslationGuidance({\n generatedLoader: generatedLoader && loader !== 'custom',\n runtimeSetup,\n translationsDir,\n });\n if (guidance) logger.message(guidance);\n } else if (\n storage === 'cdn' &&\n buildTool &&\n !reactSetup &&\n configuredTranslationsDir !== undefined\n ) {\n // Only the application setup rewrites the initializer; a loader passed\n // to it takes precedence over CDN loading.\n reportManualAction({\n whatHappened: `Translations now load from the CDN, but ${buildTool.initializer} may still receive the local loader for ${configuredTranslationsDir}`,\n fix: `Remove the loadTranslations option and its import from the ${buildTool.initializer}() call so translations load from the CDN`,\n });\n } else if (\n storage === 'cdn' &&\n !buildTool &&\n configuredTranslationsDir !== undefined\n ) {\n // gt-next uses a loadTranslations file whenever one exists, and a\n // loader passed to GTProvider takes precedence over the CDN. Name every\n // one: deleting only the first makes gt-next fall back to the next.\n const loaders = findLoadTranslationsFiles(cwd).map((loader) =>\n path.relative(cwd, loader)\n );\n if (loaders.length > 0) {\n const loaderFiles = loaders.join(', ');\n const [them, loads] =\n loaders.length === 1 ? ['it', 'loads'] : ['them', 'load'];\n reportManualAction({\n whatHappened: `Translations now load from the CDN, but ${loaderFiles} still ${loads} them from ${configuredTranslationsDir}`,\n fix: `Delete ${loaderFiles}, and remove ${them} from your GT setup if you pass ${them} there, so translations load from the CDN`,\n });\n }\n }\n\n await createOrUpdateConfig(configFilepath, configUpdate);\n session.step(`updated ${configFilepath}`);\n\n logger.success(\n `Edit ${chalk.cyan(\n configFilepath\n )} to customize your translation setup. Docs: https://generaltranslation.com/docs/cli/reference/config`\n );\n\n if (reactSetup && buildTool) {\n reportSetupResult(await buildTool.apply(buildToolContext));\n }\n\n if (installGT && packageManager) {\n await installWithProgress(session, 'gt', packageManager, true);\n }\n\n if (project) {\n await withCredentialsError(() =>\n provisionDevelopmentCredentials(\n session,\n project,\n settings,\n envFramework,\n cwd\n )\n );\n logger.message(productionRuntimeKeyGuidance(settings.dashboardUrl));\n }\n }\n}\n"],"mappings":"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"}
@@ -1,11 +1,11 @@
1
1
  import { exitSync } from "../../console/logging.js";
2
- import { loadConfig } from "../../fs/config/loadConfig.js";
2
+ import { loadConfig, withJsonExtension } from "../../fs/config/loadConfig.js";
3
3
  import { resolveProjectId } from "../../fs/utils.js";
4
4
  import { createUserTokenProvider } from "../../auth/oauth.js";
5
5
  import { resolveConfig } from "../../config/resolveConfig.js";
6
- import fs from "node:fs";
7
- import { createDiagnosticMessage, formatDiagnosticErrorDetails } from "generaltranslation/diagnostics";
8
6
  import { defaultBaseUrl } from "generaltranslation/internal";
7
+ import fs from "node:fs";
8
+ import { createDiagnosticMessage as createDiagnosticMessage$1, formatDiagnosticErrorDetails as formatDiagnosticErrorDetails$1 } from "generaltranslation/diagnostics";
9
9
  import { createApiClient } from "generaltranslation/api";
10
10
  import openApiSpec from "generaltranslation/api/openapi.json" with { type: "json" };
11
11
  //#region src/cli/commands/api.ts
@@ -24,7 +24,7 @@ function fail(diagnostic, { exit = exitSync, writeStderr = (output) => process.s
24
24
  }
25
25
  function parseMethod(value, dependencies) {
26
26
  const method = value.toUpperCase();
27
- if (!STANDARD_HTTP_METHODS.has(method)) fail(createDiagnosticMessage({
27
+ if (!STANDARD_HTTP_METHODS.has(method)) fail(createDiagnosticMessage$1({
28
28
  source: "gt",
29
29
  severity: "Error",
30
30
  whatHappened: "The API request method is invalid",
@@ -37,7 +37,7 @@ function parseHeaders(values, dependencies) {
37
37
  const headers = new Headers();
38
38
  for (const header of values) {
39
39
  const separator = header.indexOf(":");
40
- if (separator < 1) fail(createDiagnosticMessage({
40
+ if (separator < 1) fail(createDiagnosticMessage$1({
41
41
  source: "gt",
42
42
  severity: "Error",
43
43
  whatHappened: "The API request header is invalid",
@@ -52,12 +52,12 @@ function readInput(input, dependencies) {
52
52
  try {
53
53
  return fs.readFileSync(input === "-" ? 0 : input, "utf8");
54
54
  } catch (error) {
55
- return fail(createDiagnosticMessage({
55
+ return fail(createDiagnosticMessage$1({
56
56
  source: "gt",
57
57
  severity: "Error",
58
58
  whatHappened: "The API request body could not be read",
59
59
  fix: input === "-" ? "Pipe a request body to standard input or remove `--input -`" : "Check the `--input` file path and permissions",
60
- details: formatDiagnosticErrorDetails(error)
60
+ details: formatDiagnosticErrorDetails$1(error)
61
61
  }), dependencies);
62
62
  }
63
63
  }
@@ -71,14 +71,14 @@ function writeResponseMetadata(response, writeStdout) {
71
71
  function resolveApiProjectId(config, flagProjectId, dependencies) {
72
72
  const configProjectId = typeof config.projectId === "string" ? config.projectId : void 0;
73
73
  const environmentProjectId = resolveProjectId();
74
- if (configProjectId && flagProjectId && configProjectId !== flagProjectId) fail(createDiagnosticMessage({
74
+ if (configProjectId && flagProjectId && configProjectId !== flagProjectId) fail(createDiagnosticMessage$1({
75
75
  source: "gt",
76
76
  severity: "Error",
77
77
  whatHappened: "The project IDs do not match",
78
78
  details: [`Configuration: ${configProjectId}`, `--project-id: ${flagProjectId}`],
79
79
  fix: "Use the same project ID in all configurations"
80
80
  }), dependencies);
81
- if (configProjectId && environmentProjectId && configProjectId !== environmentProjectId) fail(createDiagnosticMessage({
81
+ if (configProjectId && environmentProjectId && configProjectId !== environmentProjectId) fail(createDiagnosticMessage$1({
82
82
  source: "gt",
83
83
  severity: "Error",
84
84
  whatHappened: "The project IDs do not match",
@@ -98,15 +98,14 @@ async function handleApiCommand(endpoint, options, dependencies = {}) {
98
98
  writeStdout(`${JSON.stringify(openApiSpec, null, 2)}\n`);
99
99
  return;
100
100
  }
101
- if (!endpoint) fail(createDiagnosticMessage({
101
+ if (!endpoint) fail(createDiagnosticMessage$1({
102
102
  source: "gt",
103
103
  severity: "Error",
104
104
  whatHappened: "No API endpoint was provided",
105
105
  fix: "Pass an endpoint or use `gt api --spec` to inspect the OpenAPI specification"
106
106
  }), dependencies);
107
107
  const method = parseMethod(options.method, dependencies);
108
- const configPath = options.config?.endsWith(".json") ? options.config : options.config ? `${options.config}.json` : void 0;
109
- const config = configPath ? loadConfig(configPath) : resolveConfig(process.cwd())?.config ?? {};
108
+ const config = options.config ? loadConfig(withJsonExtension(options.config)) : resolveConfig(process.cwd())?.config ?? {};
110
109
  const baseUrl = typeof config.baseUrl === "string" ? config.baseUrl : defaultBaseUrl;
111
110
  const client = createApiClient({
112
111
  apiKey: options.apiKey ?? process.env.GT_API_KEY,
@@ -132,17 +131,17 @@ async function handleApiCommand(endpoint, options, dependencies = {}) {
132
131
  parseAs: "stream",
133
132
  throwOnError: false,
134
133
  url: normalizedEndpoint
135
- }).catch((error) => fail(createDiagnosticMessage({
134
+ }).catch((error) => fail(createDiagnosticMessage$1({
136
135
  source: "gt",
137
136
  severity: "Error",
138
137
  whatHappened: "The API request failed before a response was received",
139
- details: formatDiagnosticErrorDetails(error)
138
+ details: formatDiagnosticErrorDetails$1(error)
140
139
  }), dependencies));
141
- if (!rawResponse) fail(createDiagnosticMessage({
140
+ if (!rawResponse) fail(createDiagnosticMessage$1({
142
141
  source: "gt",
143
142
  severity: "Error",
144
143
  whatHappened: "The API request did not return a response",
145
- details: formatDiagnosticErrorDetails(result?.error)
144
+ details: formatDiagnosticErrorDetails$1(result?.error)
146
145
  }), dependencies);
147
146
  if (options.include) writeResponseMetadata(rawResponse, writeStdout);
148
147
  writeStdout(Buffer.from(await rawResponse.arrayBuffer()));
@@ -1 +1 @@
1
- {"version":3,"file":"api.js","names":[],"sources":["../../../src/cli/commands/api.ts"],"sourcesContent":["import fs from 'node:fs';\nimport {\n createApiClient,\n type ApiClientConfig,\n type Client,\n} from 'generaltranslation/api';\nimport openApiSpec from 'generaltranslation/api/openapi.json' with { type: 'json' };\nimport {\n createDiagnosticMessage,\n formatDiagnosticErrorDetails,\n} from 'generaltranslation/diagnostics';\nimport { defaultBaseUrl } from 'generaltranslation/internal';\nimport { createUserTokenProvider } from '../../auth/oauth.js';\nimport { resolveConfig } from '../../config/resolveConfig.js';\nimport { exitSync } from '../../console/logging.js';\nimport { loadConfig } from '../../fs/config/loadConfig.js';\nimport { resolveProjectId } from '../../fs/utils.js';\nimport type { SharedFlags } from '../../types/index.js';\n\nexport type ApiCommandOptions = SharedFlags & {\n header?: string[];\n include?: boolean;\n input?: string;\n method: string;\n spec?: boolean;\n};\n\ntype ApiCommandDependencies = {\n exit?: (code: number) => never;\n fetch?: ApiClientConfig['fetch'];\n writeStderr?: (output: string) => void;\n writeStdout?: (output: string | Uint8Array) => void;\n};\n\ntype ApiRequestOptions = Parameters<Client['request']>[0];\n\nconst STANDARD_HTTP_METHODS = new Set([\n 'GET',\n 'HEAD',\n 'POST',\n 'PUT',\n 'PATCH',\n 'DELETE',\n 'OPTIONS',\n]);\n\nfunction fail(\n diagnostic: string,\n {\n exit = exitSync,\n writeStderr = (output) => process.stderr.write(output),\n }: ApiCommandDependencies\n): never {\n writeStderr(`${diagnostic}\\n`);\n return exit(1);\n}\n\nfunction parseMethod(\n value: string,\n dependencies: ApiCommandDependencies\n): ApiRequestOptions['method'] {\n const method = value.toUpperCase();\n if (!STANDARD_HTTP_METHODS.has(method)) {\n fail(\n createDiagnosticMessage({\n source: 'gt',\n severity: 'Error',\n whatHappened: 'The API request method is invalid',\n details: value,\n fix: `Use one of ${[...STANDARD_HTTP_METHODS].join(', ')}`,\n }),\n dependencies\n );\n }\n // The set validation narrows Commander input to the generated HTTP method union.\n return method as ApiRequestOptions['method'];\n}\n\nfunction parseHeaders(\n values: string[],\n dependencies: ApiCommandDependencies\n): Headers {\n const headers = new Headers();\n for (const header of values) {\n const separator = header.indexOf(':');\n if (separator < 1) {\n fail(\n createDiagnosticMessage({\n source: 'gt',\n severity: 'Error',\n whatHappened: 'The API request header is invalid',\n details: header,\n fix: 'Pass headers as `--header \"Key: Value\"`',\n }),\n dependencies\n );\n }\n headers.append(\n header.slice(0, separator).trim(),\n header.slice(separator + 1).trim()\n );\n }\n return headers;\n}\n\nfunction readInput(\n input: string,\n dependencies: ApiCommandDependencies\n): string {\n try {\n return fs.readFileSync(input === '-' ? 0 : input, 'utf8');\n } catch (error) {\n return fail(\n createDiagnosticMessage({\n source: 'gt',\n severity: 'Error',\n whatHappened: 'The API request body could not be read',\n fix:\n input === '-'\n ? 'Pipe a request body to standard input or remove `--input -`'\n : 'Check the `--input` file path and permissions',\n details: formatDiagnosticErrorDetails(error),\n }),\n dependencies\n );\n }\n}\n\nfunction writeResponseMetadata(\n response: Response,\n writeStdout: (output: string | Uint8Array) => void\n): void {\n writeStdout(\n `HTTP ${response.status}${response.statusText ? ` ${response.statusText}` : ''}\\n`\n );\n response.headers.forEach((value, name) => {\n writeStdout(`${name}: ${value}\\n`);\n });\n writeStdout('\\n');\n}\n\nfunction resolveApiProjectId(\n config: Record<string, unknown>,\n flagProjectId: string | undefined,\n dependencies: ApiCommandDependencies\n): string | undefined {\n const configProjectId =\n typeof config.projectId === 'string' ? config.projectId : undefined;\n const environmentProjectId = resolveProjectId();\n\n if (configProjectId && flagProjectId && configProjectId !== flagProjectId) {\n fail(\n createDiagnosticMessage({\n source: 'gt',\n severity: 'Error',\n whatHappened: 'The project IDs do not match',\n details: [\n `Configuration: ${configProjectId}`,\n `--project-id: ${flagProjectId}`,\n ],\n fix: 'Use the same project ID in all configurations',\n }),\n dependencies\n );\n }\n\n if (\n configProjectId &&\n environmentProjectId &&\n configProjectId !== environmentProjectId\n ) {\n fail(\n createDiagnosticMessage({\n source: 'gt',\n severity: 'Error',\n whatHappened: 'The project IDs do not match',\n details: [\n `Configuration: ${configProjectId}`,\n `Environment: ${environmentProjectId}`,\n ],\n fix: 'Use the same project ID in all configurations',\n }),\n dependencies\n );\n }\n\n return flagProjectId ?? configProjectId ?? environmentProjectId;\n}\n\nexport async function handleApiCommand(\n endpoint: string | undefined,\n options: ApiCommandOptions,\n dependencies: ApiCommandDependencies = {}\n): Promise<void> {\n if (!dependencies.writeStdout) {\n process.stdout.once('error', (error: NodeJS.ErrnoException) => {\n if (error.code === 'EPIPE') process.exit(0);\n throw error;\n });\n }\n const writeStdout =\n dependencies.writeStdout ?? ((output) => process.stdout.write(output));\n const writeStderr =\n dependencies.writeStderr ?? ((output) => process.stderr.write(output));\n\n if (options.spec) {\n writeStdout(`${JSON.stringify(openApiSpec, null, 2)}\\n`);\n return;\n }\n\n if (!endpoint) {\n fail(\n createDiagnosticMessage({\n source: 'gt',\n severity: 'Error',\n whatHappened: 'No API endpoint was provided',\n fix: 'Pass an endpoint or use `gt api --spec` to inspect the OpenAPI specification',\n }),\n dependencies\n );\n }\n\n const method = parseMethod(options.method, dependencies);\n const configPath = options.config?.endsWith('.json')\n ? options.config\n : options.config\n ? `${options.config}.json`\n : undefined;\n const config = configPath\n ? loadConfig(configPath)\n : (resolveConfig(process.cwd())?.config ?? {});\n const baseUrl =\n typeof config.baseUrl === 'string' ? config.baseUrl : defaultBaseUrl;\n const client = createApiClient({\n apiKey: options.apiKey ?? process.env.GT_API_KEY,\n userTokenProvider: createUserTokenProvider({ baseUrl }),\n baseUrl,\n fetch: dependencies.fetch,\n projectId: resolveApiProjectId(config, options.projectId, dependencies),\n retryPolicy: 'none',\n });\n const normalizedEndpoint = endpoint.startsWith('/')\n ? endpoint\n : `/${endpoint}`;\n const headers = parseHeaders(options.header ?? [], dependencies);\n const body = options.input\n ? readInput(options.input, dependencies)\n : undefined;\n let rawResponse: Response | undefined;\n\n client.interceptors.response.use((response) => {\n // Keep a clone because the generated client consumes non-2xx bodies.\n rawResponse = response.clone();\n return response;\n });\n\n const result = await client\n .request({\n body,\n bodySerializer: () => body,\n headers,\n method,\n parseAs: 'stream',\n throwOnError: false,\n url: normalizedEndpoint,\n })\n .catch((error) =>\n fail(\n createDiagnosticMessage({\n source: 'gt',\n severity: 'Error',\n whatHappened: 'The API request failed before a response was received',\n details: formatDiagnosticErrorDetails(error),\n }),\n dependencies\n )\n );\n\n if (!rawResponse) {\n fail(\n createDiagnosticMessage({\n source: 'gt',\n severity: 'Error',\n whatHappened: 'The API request did not return a response',\n details: formatDiagnosticErrorDetails(result?.error),\n }),\n dependencies\n );\n }\n\n if (options.include) writeResponseMetadata(rawResponse, writeStdout);\n writeStdout(Buffer.from(await rawResponse.arrayBuffer()));\n\n if (!rawResponse.ok) {\n writeStderr(\n `${method} ${normalizedEndpoint} returned HTTP ${rawResponse.status}${rawResponse.statusText ? ` ${rawResponse.statusText}` : ''}\\n`\n );\n (dependencies.exit ?? exitSync)(1);\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"api.js","names":["createDiagnosticMessage","formatDiagnosticErrorDetails"],"sources":["../../../src/cli/commands/api.ts"],"sourcesContent":["import fs from 'node:fs';\nimport {\n createApiClient,\n type ApiClientConfig,\n type Client,\n} from 'generaltranslation/api';\nimport openApiSpec from 'generaltranslation/api/openapi.json' with { type: 'json' };\nimport {\n createDiagnosticMessage,\n formatDiagnosticErrorDetails,\n} from 'generaltranslation/diagnostics';\nimport { defaultBaseUrl } from 'generaltranslation/internal';\nimport { createUserTokenProvider } from '../../auth/oauth.js';\nimport { resolveConfig } from '../../config/resolveConfig.js';\nimport { exitSync } from '../../console/logging.js';\nimport { loadConfig, withJsonExtension } from '../../fs/config/loadConfig.js';\nimport { resolveProjectId } from '../../fs/utils.js';\nimport type { SharedFlags } from '../../types/index.js';\n\nexport type ApiCommandOptions = SharedFlags & {\n header?: string[];\n include?: boolean;\n input?: string;\n method: string;\n spec?: boolean;\n};\n\ntype ApiCommandDependencies = {\n exit?: (code: number) => never;\n fetch?: ApiClientConfig['fetch'];\n writeStderr?: (output: string) => void;\n writeStdout?: (output: string | Uint8Array) => void;\n};\n\ntype ApiRequestOptions = Parameters<Client['request']>[0];\n\nconst STANDARD_HTTP_METHODS = new Set([\n 'GET',\n 'HEAD',\n 'POST',\n 'PUT',\n 'PATCH',\n 'DELETE',\n 'OPTIONS',\n]);\n\nfunction fail(\n diagnostic: string,\n {\n exit = exitSync,\n writeStderr = (output) => process.stderr.write(output),\n }: ApiCommandDependencies\n): never {\n writeStderr(`${diagnostic}\\n`);\n return exit(1);\n}\n\nfunction parseMethod(\n value: string,\n dependencies: ApiCommandDependencies\n): ApiRequestOptions['method'] {\n const method = value.toUpperCase();\n if (!STANDARD_HTTP_METHODS.has(method)) {\n fail(\n createDiagnosticMessage({\n source: 'gt',\n severity: 'Error',\n whatHappened: 'The API request method is invalid',\n details: value,\n fix: `Use one of ${[...STANDARD_HTTP_METHODS].join(', ')}`,\n }),\n dependencies\n );\n }\n // The set validation narrows Commander input to the generated HTTP method union.\n return method as ApiRequestOptions['method'];\n}\n\nfunction parseHeaders(\n values: string[],\n dependencies: ApiCommandDependencies\n): Headers {\n const headers = new Headers();\n for (const header of values) {\n const separator = header.indexOf(':');\n if (separator < 1) {\n fail(\n createDiagnosticMessage({\n source: 'gt',\n severity: 'Error',\n whatHappened: 'The API request header is invalid',\n details: header,\n fix: 'Pass headers as `--header \"Key: Value\"`',\n }),\n dependencies\n );\n }\n headers.append(\n header.slice(0, separator).trim(),\n header.slice(separator + 1).trim()\n );\n }\n return headers;\n}\n\nfunction readInput(\n input: string,\n dependencies: ApiCommandDependencies\n): string {\n try {\n return fs.readFileSync(input === '-' ? 0 : input, 'utf8');\n } catch (error) {\n return fail(\n createDiagnosticMessage({\n source: 'gt',\n severity: 'Error',\n whatHappened: 'The API request body could not be read',\n fix:\n input === '-'\n ? 'Pipe a request body to standard input or remove `--input -`'\n : 'Check the `--input` file path and permissions',\n details: formatDiagnosticErrorDetails(error),\n }),\n dependencies\n );\n }\n}\n\nfunction writeResponseMetadata(\n response: Response,\n writeStdout: (output: string | Uint8Array) => void\n): void {\n writeStdout(\n `HTTP ${response.status}${response.statusText ? ` ${response.statusText}` : ''}\\n`\n );\n response.headers.forEach((value, name) => {\n writeStdout(`${name}: ${value}\\n`);\n });\n writeStdout('\\n');\n}\n\nfunction resolveApiProjectId(\n config: Record<string, unknown>,\n flagProjectId: string | undefined,\n dependencies: ApiCommandDependencies\n): string | undefined {\n const configProjectId =\n typeof config.projectId === 'string' ? config.projectId : undefined;\n const environmentProjectId = resolveProjectId();\n\n if (configProjectId && flagProjectId && configProjectId !== flagProjectId) {\n fail(\n createDiagnosticMessage({\n source: 'gt',\n severity: 'Error',\n whatHappened: 'The project IDs do not match',\n details: [\n `Configuration: ${configProjectId}`,\n `--project-id: ${flagProjectId}`,\n ],\n fix: 'Use the same project ID in all configurations',\n }),\n dependencies\n );\n }\n\n if (\n configProjectId &&\n environmentProjectId &&\n configProjectId !== environmentProjectId\n ) {\n fail(\n createDiagnosticMessage({\n source: 'gt',\n severity: 'Error',\n whatHappened: 'The project IDs do not match',\n details: [\n `Configuration: ${configProjectId}`,\n `Environment: ${environmentProjectId}`,\n ],\n fix: 'Use the same project ID in all configurations',\n }),\n dependencies\n );\n }\n\n return flagProjectId ?? configProjectId ?? environmentProjectId;\n}\n\nexport async function handleApiCommand(\n endpoint: string | undefined,\n options: ApiCommandOptions,\n dependencies: ApiCommandDependencies = {}\n): Promise<void> {\n if (!dependencies.writeStdout) {\n process.stdout.once('error', (error: NodeJS.ErrnoException) => {\n if (error.code === 'EPIPE') process.exit(0);\n throw error;\n });\n }\n const writeStdout =\n dependencies.writeStdout ?? ((output) => process.stdout.write(output));\n const writeStderr =\n dependencies.writeStderr ?? ((output) => process.stderr.write(output));\n\n if (options.spec) {\n writeStdout(`${JSON.stringify(openApiSpec, null, 2)}\\n`);\n return;\n }\n\n if (!endpoint) {\n fail(\n createDiagnosticMessage({\n source: 'gt',\n severity: 'Error',\n whatHappened: 'No API endpoint was provided',\n fix: 'Pass an endpoint or use `gt api --spec` to inspect the OpenAPI specification',\n }),\n dependencies\n );\n }\n\n const method = parseMethod(options.method, dependencies);\n const config = options.config\n ? loadConfig(withJsonExtension(options.config))\n : (resolveConfig(process.cwd())?.config ?? {});\n const baseUrl =\n typeof config.baseUrl === 'string' ? config.baseUrl : defaultBaseUrl;\n const client = createApiClient({\n apiKey: options.apiKey ?? process.env.GT_API_KEY,\n userTokenProvider: createUserTokenProvider({ baseUrl }),\n baseUrl,\n fetch: dependencies.fetch,\n projectId: resolveApiProjectId(config, options.projectId, dependencies),\n retryPolicy: 'none',\n });\n const normalizedEndpoint = endpoint.startsWith('/')\n ? endpoint\n : `/${endpoint}`;\n const headers = parseHeaders(options.header ?? [], dependencies);\n const body = options.input\n ? readInput(options.input, dependencies)\n : undefined;\n let rawResponse: Response | undefined;\n\n client.interceptors.response.use((response) => {\n // Keep a clone because the generated client consumes non-2xx bodies.\n rawResponse = response.clone();\n return response;\n });\n\n const result = await client\n .request({\n body,\n bodySerializer: () => body,\n headers,\n method,\n parseAs: 'stream',\n throwOnError: false,\n url: normalizedEndpoint,\n })\n .catch((error) =>\n fail(\n createDiagnosticMessage({\n source: 'gt',\n severity: 'Error',\n whatHappened: 'The API request failed before a response was received',\n details: formatDiagnosticErrorDetails(error),\n }),\n dependencies\n )\n );\n\n if (!rawResponse) {\n fail(\n createDiagnosticMessage({\n source: 'gt',\n severity: 'Error',\n whatHappened: 'The API request did not return a response',\n details: formatDiagnosticErrorDetails(result?.error),\n }),\n dependencies\n );\n }\n\n if (options.include) writeResponseMetadata(rawResponse, writeStdout);\n writeStdout(Buffer.from(await rawResponse.arrayBuffer()));\n\n if (!rawResponse.ok) {\n writeStderr(\n `${method} ${normalizedEndpoint} returned HTTP ${rawResponse.status}${rawResponse.statusText ? ` ${rawResponse.statusText}` : ''}\\n`\n );\n (dependencies.exit ?? exitSync)(1);\n }\n}\n"],"mappings":";;;;;;;;;;;AAoCA,MAAM,wBAAwB,IAAI,IAAI;CACpC;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;AAEF,SAAS,KACP,YACA,EACE,OAAO,UACP,eAAe,WAAW,QAAQ,OAAO,MAAM,OAAO,IAEjD;AACP,aAAY,GAAG,WAAW,IAAI;AAC9B,QAAO,KAAK,EAAE;;AAGhB,SAAS,YACP,OACA,cAC6B;CAC7B,MAAM,SAAS,MAAM,aAAa;AAClC,KAAI,CAAC,sBAAsB,IAAI,OAAO,CACpC,MACEA,0BAAwB;EACtB,QAAQ;EACR,UAAU;EACV,cAAc;EACd,SAAS;EACT,KAAK,cAAc,CAAC,GAAG,sBAAsB,CAAC,KAAK,KAAK;EACzD,CAAC,EACF,aACD;AAGH,QAAO;;AAGT,SAAS,aACP,QACA,cACS;CACT,MAAM,UAAU,IAAI,SAAS;AAC7B,MAAK,MAAM,UAAU,QAAQ;EAC3B,MAAM,YAAY,OAAO,QAAQ,IAAI;AACrC,MAAI,YAAY,EACd,MACEA,0BAAwB;GACtB,QAAQ;GACR,UAAU;GACV,cAAc;GACd,SAAS;GACT,KAAK;GACN,CAAC,EACF,aACD;AAEH,UAAQ,OACN,OAAO,MAAM,GAAG,UAAU,CAAC,MAAM,EACjC,OAAO,MAAM,YAAY,EAAE,CAAC,MAAM,CACnC;;AAEH,QAAO;;AAGT,SAAS,UACP,OACA,cACQ;AACR,KAAI;AACF,SAAO,GAAG,aAAa,UAAU,MAAM,IAAI,OAAO,OAAO;UAClD,OAAO;AACd,SAAO,KACLA,0BAAwB;GACtB,QAAQ;GACR,UAAU;GACV,cAAc;GACd,KACE,UAAU,MACN,gEACA;GACN,SAASC,+BAA6B,MAAM;GAC7C,CAAC,EACF,aACD;;;AAIL,SAAS,sBACP,UACA,aACM;AACN,aACE,QAAQ,SAAS,SAAS,SAAS,aAAa,IAAI,SAAS,eAAe,GAAG,IAChF;AACD,UAAS,QAAQ,SAAS,OAAO,SAAS;AACxC,cAAY,GAAG,KAAK,IAAI,MAAM,IAAI;GAClC;AACF,aAAY,KAAK;;AAGnB,SAAS,oBACP,QACA,eACA,cACoB;CACpB,MAAM,kBACJ,OAAO,OAAO,cAAc,WAAW,OAAO,YAAY,KAAA;CAC5D,MAAM,uBAAuB,kBAAkB;AAE/C,KAAI,mBAAmB,iBAAiB,oBAAoB,cAC1D,MACED,0BAAwB;EACtB,QAAQ;EACR,UAAU;EACV,cAAc;EACd,SAAS,CACP,kBAAkB,mBAClB,iBAAiB,gBAClB;EACD,KAAK;EACN,CAAC,EACF,aACD;AAGH,KACE,mBACA,wBACA,oBAAoB,qBAEpB,MACEA,0BAAwB;EACtB,QAAQ;EACR,UAAU;EACV,cAAc;EACd,SAAS,CACP,kBAAkB,mBAClB,gBAAgB,uBACjB;EACD,KAAK;EACN,CAAC,EACF,aACD;AAGH,QAAO,iBAAiB,mBAAmB;;AAG7C,eAAsB,iBACpB,UACA,SACA,eAAuC,EAAE,EAC1B;AACf,KAAI,CAAC,aAAa,YAChB,SAAQ,OAAO,KAAK,UAAU,UAAiC;AAC7D,MAAI,MAAM,SAAS,QAAS,SAAQ,KAAK,EAAE;AAC3C,QAAM;GACN;CAEJ,MAAM,cACJ,aAAa,iBAAiB,WAAW,QAAQ,OAAO,MAAM,OAAO;CACvE,MAAM,cACJ,aAAa,iBAAiB,WAAW,QAAQ,OAAO,MAAM,OAAO;AAEvE,KAAI,QAAQ,MAAM;AAChB,cAAY,GAAG,KAAK,UAAU,aAAa,MAAM,EAAE,CAAC,IAAI;AACxD;;AAGF,KAAI,CAAC,SACH,MACEA,0BAAwB;EACtB,QAAQ;EACR,UAAU;EACV,cAAc;EACd,KAAK;EACN,CAAC,EACF,aACD;CAGH,MAAM,SAAS,YAAY,QAAQ,QAAQ,aAAa;CACxD,MAAM,SAAS,QAAQ,SACnB,WAAW,kBAAkB,QAAQ,OAAO,CAAC,GAC5C,cAAc,QAAQ,KAAK,CAAC,EAAE,UAAU,EAAE;CAC/C,MAAM,UACJ,OAAO,OAAO,YAAY,WAAW,OAAO,UAAU;CACxD,MAAM,SAAS,gBAAgB;EAC7B,QAAQ,QAAQ,UAAU,QAAQ,IAAI;EACtC,mBAAmB,wBAAwB,EAAE,SAAS,CAAC;EACvD;EACA,OAAO,aAAa;EACpB,WAAW,oBAAoB,QAAQ,QAAQ,WAAW,aAAa;EACvE,aAAa;EACd,CAAC;CACF,MAAM,qBAAqB,SAAS,WAAW,IAAI,GAC/C,WACA,IAAI;CACR,MAAM,UAAU,aAAa,QAAQ,UAAU,EAAE,EAAE,aAAa;CAChE,MAAM,OAAO,QAAQ,QACjB,UAAU,QAAQ,OAAO,aAAa,GACtC,KAAA;CACJ,IAAI;AAEJ,QAAO,aAAa,SAAS,KAAK,aAAa;AAE7C,gBAAc,SAAS,OAAO;AAC9B,SAAO;GACP;CAEF,MAAM,SAAS,MAAM,OAClB,QAAQ;EACP;EACA,sBAAsB;EACtB;EACA;EACA,SAAS;EACT,cAAc;EACd,KAAK;EACN,CAAC,CACD,OAAO,UACN,KACEA,0BAAwB;EACtB,QAAQ;EACR,UAAU;EACV,cAAc;EACd,SAASC,+BAA6B,MAAM;EAC7C,CAAC,EACF,aACD,CACF;AAEH,KAAI,CAAC,YACH,MACED,0BAAwB;EACtB,QAAQ;EACR,UAAU;EACV,cAAc;EACd,SAASC,+BAA6B,QAAQ,MAAM;EACrD,CAAC,EACF,aACD;AAGH,KAAI,QAAQ,QAAS,uBAAsB,aAAa,YAAY;AACpE,aAAY,OAAO,KAAK,MAAM,YAAY,aAAa,CAAC,CAAC;AAEzD,KAAI,CAAC,YAAY,IAAI;AACnB,cACE,GAAG,OAAO,GAAG,mBAAmB,iBAAiB,YAAY,SAAS,YAAY,aAAa,IAAI,YAAY,eAAe,GAAG,IAClI;AACD,GAAC,aAAa,QAAQ,UAAU,EAAE"}
package/dist/cli/node.js CHANGED
@@ -11,7 +11,7 @@ var NodeCLI = class extends InlineCLI {
11
11
  this.program.hook("preAction", (_thisCommand, actionCommand) => {
12
12
  if (this.program.opts().skipVersionCheck) return;
13
13
  if (actionCommand.parent?.name() === "git") return;
14
- checkMonorepoVersionConsistency(NODE_LIBRARIES);
14
+ checkMonorepoVersionConsistency(NODE_LIBRARIES, actionCommand.opts().config);
15
15
  });
16
16
  }
17
17
  };
@@ -1 +1 @@
1
- {"version":3,"file":"node.js","names":[],"sources":["../../src/cli/node.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { SupportedLibraries } from '../types/index.js';\nimport { InlineCLI } from './inline.js';\nimport { Libraries, NODE_LIBRARIES } from '../types/libraries.js';\nimport { checkMonorepoVersionConsistency } from '../utils/monorepoVersionCheck.js';\n\n/**\n * CLI tool for managing translations with gt-node\n */\nexport class NodeCLI extends InlineCLI {\n constructor(\n command: Command,\n library: typeof Libraries.GT_NODE,\n additionalModules?: SupportedLibraries[]\n ) {\n super(command, library, additionalModules);\n\n this.program.hook('preAction', (_thisCommand, actionCommand) => {\n if (this.program.opts().skipVersionCheck) return;\n if (actionCommand.parent?.name() === 'git') return;\n checkMonorepoVersionConsistency(NODE_LIBRARIES);\n });\n }\n}\n"],"mappings":";;;;;;;AASA,IAAa,UAAb,cAA6B,UAAU;CACrC,YACE,SACA,SACA,mBACA;AACA,QAAM,SAAS,SAAS,kBAAkB;AAE1C,OAAK,QAAQ,KAAK,cAAc,cAAc,kBAAkB;AAC9D,OAAI,KAAK,QAAQ,MAAM,CAAC,iBAAkB;AAC1C,OAAI,cAAc,QAAQ,MAAM,KAAK,MAAO;AAC5C,mCAAgC,eAAe;IAC/C"}
1
+ {"version":3,"file":"node.js","names":[],"sources":["../../src/cli/node.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { SupportedLibraries } from '../types/index.js';\nimport { InlineCLI } from './inline.js';\nimport { Libraries, NODE_LIBRARIES } from '../types/libraries.js';\nimport { checkMonorepoVersionConsistency } from '../utils/monorepoVersionCheck.js';\n\n/**\n * CLI tool for managing translations with gt-node\n */\nexport class NodeCLI extends InlineCLI {\n constructor(\n command: Command,\n library: typeof Libraries.GT_NODE,\n additionalModules?: SupportedLibraries[]\n ) {\n super(command, library, additionalModules);\n\n this.program.hook('preAction', (_thisCommand, actionCommand) => {\n if (this.program.opts().skipVersionCheck) return;\n if (actionCommand.parent?.name() === 'git') return;\n checkMonorepoVersionConsistency(\n NODE_LIBRARIES,\n actionCommand.opts().config\n );\n });\n }\n}\n"],"mappings":";;;;;;;AASA,IAAa,UAAb,cAA6B,UAAU;CACrC,YACE,SACA,SACA,mBACA;AACA,QAAM,SAAS,SAAS,kBAAkB;AAE1C,OAAK,QAAQ,KAAK,cAAc,cAAc,kBAAkB;AAC9D,OAAI,KAAK,QAAQ,MAAM,CAAC,iBAAkB;AAC1C,OAAI,cAAc,QAAQ,MAAM,KAAK,MAAO;AAC5C,mCACE,gBACA,cAAc,MAAM,CAAC,OACtB;IACD"}
package/dist/cli/react.js CHANGED
@@ -16,7 +16,7 @@ var ReactCLI = class extends InlineCLI {
16
16
  this.program.hook("preAction", (_thisCommand, actionCommand) => {
17
17
  if (this.program.opts().skipVersionCheck) return;
18
18
  if (actionCommand.parent?.name() === "git") return;
19
- checkMonorepoVersionConsistency([...REACT_LIBRARIES, "gt-i18n"]);
19
+ checkMonorepoVersionConsistency([...REACT_LIBRARIES, "gt-i18n"], actionCommand.opts().config);
20
20
  });
21
21
  }
22
22
  init() {
@@ -1 +1 @@
1
- {"version":3,"file":"react.js","names":[],"sources":["../../src/cli/react.ts"],"sourcesContent":["import { Command } from 'commander';\nimport {\n Framework,\n SupportedFrameworks,\n WrapOptions,\n SupportedLibraries,\n TranslateFlags,\n} from '../types/index.js';\nimport { displayHeader, exitSync, promptConfirm } from '../console/logging.js';\nimport { logger } from '../console/logger.js';\nimport chalk from 'chalk';\nimport { formatFiles } from '../hooks/postProcess.js';\nimport { wrapContentReact } from '../react/parse/wrapContent.js';\nimport { generateSettings } from '../config/generateSettings.js';\nimport { attachInlineTranslateFlags, attachTranslateFlags } from './flags.js';\nimport { InlineCLI } from './inline.js';\nimport { Libraries, REACT_LIBRARIES } from '../types/libraries.js';\nimport { checkMonorepoVersionConsistency } from '../utils/monorepoVersionCheck.js';\n\nconst pkg = Libraries.GT_REACT;\n\nexport class ReactCLI extends InlineCLI {\n constructor(\n command: Command,\n library: Framework,\n additionalModules?: SupportedLibraries[]\n ) {\n super(command, library, additionalModules);\n\n this.program.hook('preAction', (_thisCommand, actionCommand) => {\n if (this.program.opts().skipVersionCheck) return;\n if (actionCommand.parent?.name() === 'git') return;\n checkMonorepoVersionConsistency([...REACT_LIBRARIES, Libraries.GT_I18N]);\n });\n }\n public init() {\n super.init();\n this.setupSetupProjectCommand();\n }\n\n protected wrapContent(\n options: WrapOptions,\n framework: SupportedFrameworks,\n errors: string[],\n warnings: string[]\n ): Promise<{ filesUpdated: string[] }> {\n return wrapContentReact(options, pkg, framework, errors, warnings);\n }\n\n protected setupSetupProjectCommand(): void {\n attachInlineTranslateFlags(\n attachTranslateFlags(\n this.program\n .command('setup')\n .description(\n 'Upload source files and setup the project for translation'\n )\n )\n ).action(async (options: TranslateFlags) => {\n displayHeader('Uploading source files and setting up project...');\n await this.handleSetupProject(options);\n logger.endCommand('Done!');\n });\n }\n\n protected async handleScanCommand(options: WrapOptions): Promise<void> {\n // Ask user for confirmation using inquirer\n const answer = await promptConfirm({\n message: chalk.yellow(\n 'Warning: This operation will modify your source files! Make sure you have committed or stashed your current changes. Do you want to continue?'\n ),\n defaultValue: true,\n });\n\n if (!answer) {\n logger.error('Operation cancelled.');\n exitSync(0);\n }\n\n // ----- Create a starter gt.config.json file -----\n await generateSettings(options);\n\n // ----- //\n const includeTId = await promptConfirm({\n message: 'Do you want to include an unique id for each <T> tag?',\n defaultValue: true,\n });\n options.disableIds = !includeTId;\n\n const errors: string[] = [];\n const warnings: string[] = [];\n // Wrap all JSX elements in the src directory with a <T> tag, with unique ids\n const { filesUpdated } = await this.wrapContent(\n options,\n 'react',\n errors,\n warnings\n );\n\n if (errors.length > 0) {\n logger.error(chalk.red('Failed to write files:\\n') + errors.join('\\n'));\n }\n\n // Format updated files if formatters are available\n if (!options.disableFormatting) await formatFiles(filesUpdated);\n\n logger.success(\n `Success! Added <T> tags and updated ${chalk.bold.cyan(\n filesUpdated.length\n )} files:\\n` +\n filesUpdated.map((file) => `${chalk.green('-')} ${file}`).join('\\n')\n );\n if (filesUpdated.length > 0) {\n logger.step(chalk.green('Verify the changes before committing.'));\n }\n\n if (warnings.length > 0) {\n logger.warn(\n chalk.yellow('Warnings encountered:') +\n '\\n' +\n warnings\n .map((warning) => `${chalk.yellow('-')} ${warning}`)\n .join('\\n')\n );\n }\n }\n}\n"],"mappings":";;;;;;;;;;;AAmBA,MAAM,MAAA;AAEN,IAAa,WAAb,cAA8B,UAAU;CACtC,YACE,SACA,SACA,mBACA;AACA,QAAM,SAAS,SAAS,kBAAkB;AAE1C,OAAK,QAAQ,KAAK,cAAc,cAAc,kBAAkB;AAC9D,OAAI,KAAK,QAAQ,MAAM,CAAC,iBAAkB;AAC1C,OAAI,cAAc,QAAQ,MAAM,KAAK,MAAO;AAC5C,mCAAgC,CAAC,GAAG,iBAAA,UAAmC,CAAC;IACxE;;CAEJ,OAAc;AACZ,QAAM,MAAM;AACZ,OAAK,0BAA0B;;CAGjC,YACE,SACA,WACA,QACA,UACqC;AACrC,SAAO,iBAAiB,SAAS,KAAK,WAAW,QAAQ,SAAS;;CAGpE,2BAA2C;AACzC,6BACE,qBACE,KAAK,QACF,QAAQ,QAAQ,CAChB,YACC,4DACD,CACJ,CACF,CAAC,OAAO,OAAO,YAA4B;AAC1C,iBAAc,mDAAmD;AACjE,SAAM,KAAK,mBAAmB,QAAQ;AACtC,UAAO,WAAW,QAAQ;IAC1B;;CAGJ,MAAgB,kBAAkB,SAAqC;AASrE,MAAI,CAAC,MAPgB,cAAc;GACjC,SAAS,MAAM,OACb,gJACD;GACD,cAAc;GACf,CAAC,EAEW;AACX,UAAO,MAAM,uBAAuB;AACpC,YAAS,EAAE;;AAIb,QAAM,iBAAiB,QAAQ;AAO/B,UAAQ,aAAa,CAAC,MAJG,cAAc;GACrC,SAAS;GACT,cAAc;GACf,CAAC;EAGF,MAAM,SAAmB,EAAE;EAC3B,MAAM,WAAqB,EAAE;EAE7B,MAAM,EAAE,iBAAiB,MAAM,KAAK,YAClC,SACA,SACA,QACA,SACD;AAED,MAAI,OAAO,SAAS,EAClB,QAAO,MAAM,MAAM,IAAI,2BAA2B,GAAG,OAAO,KAAK,KAAK,CAAC;AAIzE,MAAI,CAAC,QAAQ,kBAAmB,OAAM,YAAY,aAAa;AAE/D,SAAO,QACL,uCAAuC,MAAM,KAAK,KAChD,aAAa,OACd,CAAC,aACA,aAAa,KAAK,SAAS,GAAG,MAAM,MAAM,IAAI,CAAC,GAAG,OAAO,CAAC,KAAK,KAAK,CACvE;AACD,MAAI,aAAa,SAAS,EACxB,QAAO,KAAK,MAAM,MAAM,wCAAwC,CAAC;AAGnE,MAAI,SAAS,SAAS,EACpB,QAAO,KACL,MAAM,OAAO,wBAAwB,GACnC,OACA,SACG,KAAK,YAAY,GAAG,MAAM,OAAO,IAAI,CAAC,GAAG,UAAU,CACnD,KAAK,KAAK,CAChB"}
1
+ {"version":3,"file":"react.js","names":[],"sources":["../../src/cli/react.ts"],"sourcesContent":["import { Command } from 'commander';\nimport {\n Framework,\n SupportedFrameworks,\n WrapOptions,\n SupportedLibraries,\n TranslateFlags,\n} from '../types/index.js';\nimport { displayHeader, exitSync, promptConfirm } from '../console/logging.js';\nimport { logger } from '../console/logger.js';\nimport chalk from 'chalk';\nimport { formatFiles } from '../hooks/postProcess.js';\nimport { wrapContentReact } from '../react/parse/wrapContent.js';\nimport { generateSettings } from '../config/generateSettings.js';\nimport { attachInlineTranslateFlags, attachTranslateFlags } from './flags.js';\nimport { InlineCLI } from './inline.js';\nimport { Libraries, REACT_LIBRARIES } from '../types/libraries.js';\nimport { checkMonorepoVersionConsistency } from '../utils/monorepoVersionCheck.js';\n\nconst pkg = Libraries.GT_REACT;\n\nexport class ReactCLI extends InlineCLI {\n constructor(\n command: Command,\n library: Framework,\n additionalModules?: SupportedLibraries[]\n ) {\n super(command, library, additionalModules);\n\n this.program.hook('preAction', (_thisCommand, actionCommand) => {\n if (this.program.opts().skipVersionCheck) return;\n if (actionCommand.parent?.name() === 'git') return;\n checkMonorepoVersionConsistency(\n [...REACT_LIBRARIES, Libraries.GT_I18N],\n actionCommand.opts().config\n );\n });\n }\n public init() {\n super.init();\n this.setupSetupProjectCommand();\n }\n\n protected wrapContent(\n options: WrapOptions,\n framework: SupportedFrameworks,\n errors: string[],\n warnings: string[]\n ): Promise<{ filesUpdated: string[] }> {\n return wrapContentReact(options, pkg, framework, errors, warnings);\n }\n\n protected setupSetupProjectCommand(): void {\n attachInlineTranslateFlags(\n attachTranslateFlags(\n this.program\n .command('setup')\n .description(\n 'Upload source files and setup the project for translation'\n )\n )\n ).action(async (options: TranslateFlags) => {\n displayHeader('Uploading source files and setting up project...');\n await this.handleSetupProject(options);\n logger.endCommand('Done!');\n });\n }\n\n protected async handleScanCommand(options: WrapOptions): Promise<void> {\n // Ask user for confirmation using inquirer\n const answer = await promptConfirm({\n message: chalk.yellow(\n 'Warning: This operation will modify your source files! Make sure you have committed or stashed your current changes. Do you want to continue?'\n ),\n defaultValue: true,\n });\n\n if (!answer) {\n logger.error('Operation cancelled.');\n exitSync(0);\n }\n\n // ----- Create a starter gt.config.json file -----\n await generateSettings(options);\n\n // ----- //\n const includeTId = await promptConfirm({\n message: 'Do you want to include an unique id for each <T> tag?',\n defaultValue: true,\n });\n options.disableIds = !includeTId;\n\n const errors: string[] = [];\n const warnings: string[] = [];\n // Wrap all JSX elements in the src directory with a <T> tag, with unique ids\n const { filesUpdated } = await this.wrapContent(\n options,\n 'react',\n errors,\n warnings\n );\n\n if (errors.length > 0) {\n logger.error(chalk.red('Failed to write files:\\n') + errors.join('\\n'));\n }\n\n // Format updated files if formatters are available\n if (!options.disableFormatting) await formatFiles(filesUpdated);\n\n logger.success(\n `Success! Added <T> tags and updated ${chalk.bold.cyan(\n filesUpdated.length\n )} files:\\n` +\n filesUpdated.map((file) => `${chalk.green('-')} ${file}`).join('\\n')\n );\n if (filesUpdated.length > 0) {\n logger.step(chalk.green('Verify the changes before committing.'));\n }\n\n if (warnings.length > 0) {\n logger.warn(\n chalk.yellow('Warnings encountered:') +\n '\\n' +\n warnings\n .map((warning) => `${chalk.yellow('-')} ${warning}`)\n .join('\\n')\n );\n }\n }\n}\n"],"mappings":";;;;;;;;;;;AAmBA,MAAM,MAAA;AAEN,IAAa,WAAb,cAA8B,UAAU;CACtC,YACE,SACA,SACA,mBACA;AACA,QAAM,SAAS,SAAS,kBAAkB;AAE1C,OAAK,QAAQ,KAAK,cAAc,cAAc,kBAAkB;AAC9D,OAAI,KAAK,QAAQ,MAAM,CAAC,iBAAkB;AAC1C,OAAI,cAAc,QAAQ,MAAM,KAAK,MAAO;AAC5C,mCACE,CAAC,GAAG,iBAAA,UAAmC,EACvC,cAAc,MAAM,CAAC,OACtB;IACD;;CAEJ,OAAc;AACZ,QAAM,MAAM;AACZ,OAAK,0BAA0B;;CAGjC,YACE,SACA,WACA,QACA,UACqC;AACrC,SAAO,iBAAiB,SAAS,KAAK,WAAW,QAAQ,SAAS;;CAGpE,2BAA2C;AACzC,6BACE,qBACE,KAAK,QACF,QAAQ,QAAQ,CAChB,YACC,4DACD,CACJ,CACF,CAAC,OAAO,OAAO,YAA4B;AAC1C,iBAAc,mDAAmD;AACjE,SAAM,KAAK,mBAAmB,QAAQ;AACtC,UAAO,WAAW,QAAQ;IAC1B;;CAGJ,MAAgB,kBAAkB,SAAqC;AASrE,MAAI,CAAC,MAPgB,cAAc;GACjC,SAAS,MAAM,OACb,gJACD;GACD,cAAc;GACf,CAAC,EAEW;AACX,UAAO,MAAM,uBAAuB;AACpC,YAAS,EAAE;;AAIb,QAAM,iBAAiB,QAAQ;AAO/B,UAAQ,aAAa,CAAC,MAJG,cAAc;GACrC,SAAS;GACT,cAAc;GACf,CAAC;EAGF,MAAM,SAAmB,EAAE;EAC3B,MAAM,WAAqB,EAAE;EAE7B,MAAM,EAAE,iBAAiB,MAAM,KAAK,YAClC,SACA,SACA,QACA,SACD;AAED,MAAI,OAAO,SAAS,EAClB,QAAO,MAAM,MAAM,IAAI,2BAA2B,GAAG,OAAO,KAAK,KAAK,CAAC;AAIzE,MAAI,CAAC,QAAQ,kBAAmB,OAAM,YAAY,aAAa;AAE/D,SAAO,QACL,uCAAuC,MAAM,KAAK,KAChD,aAAa,OACd,CAAC,aACA,aAAa,KAAK,SAAS,GAAG,MAAM,MAAM,IAAI,CAAC,GAAG,OAAO,CAAC,KAAK,KAAK,CACvE;AACD,MAAI,aAAa,SAAS,EACxB,QAAO,KAAK,MAAM,MAAM,wCAAwC,CAAC;AAGnE,MAAI,SAAS,SAAS,EACpB,QAAO,KACL,MAAM,OAAO,wBAAwB,GACnC,OACA,SACG,KAAK,YAAY,GAAG,MAAM,OAAO,IAAI,CAAC,GAAG,UAAU,CACnD,KAAK,KAAK,CAChB"}
package/dist/cli/vue.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { logger } from "../console/logger.js";
2
2
  import "../types/libraries.js";
3
3
  import { displayHeader } from "../console/logging.js";
4
- import findFilepath from "../fs/findFilepath.js";
4
+ import { attachConfigureFlags } from "../setup/onboarding.js";
5
5
  import { attachInlineTranslateFlags, attachTranslateFlags } from "./flags.js";
6
6
  import { InlineCLI } from "./inline.js";
7
7
  //#region src/cli/vue.ts
@@ -25,7 +25,7 @@ var VueCLI = class extends InlineCLI {
25
25
  }
26
26
  /** Configure Vue without entering the React application setup wizard. */
27
27
  setupInitCommand() {
28
- this.program.command("init").description("Configure a gt-vue project for General Translation without modifying application source").option("--src <paths...>", VUE_SOURCE_HELP).option("-c, --config <path>", "Filepath to config file, by default gt.config.json", findFilepath(["gt.config.json"])).action((options) => this.handleConfigureCommand(options));
28
+ attachConfigureFlags(this.program.command("init").description("Configure a gt-vue project for General Translation without modifying application source. Flags answer its questions; unanswered ones are asked, or listed as missing with --no-interactive"), VUE_SOURCE_HELP).action((options) => this.handleConfigureCommand(options, "init"));
29
29
  }
30
30
  /** Uploads Vue inline sources with the same targeting flags as extraction. */
31
31
  setupSetupProjectCommand() {