gt 2.19.0 → 2.20.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.
- package/CHANGELOG.md +30 -0
- package/dist/api/collectUserEditDiffs.js +23 -23
- package/dist/api/collectUserEditDiffs.js.map +1 -1
- package/dist/api/downloadFileBatch.js +7 -4
- package/dist/api/downloadFileBatch.js.map +1 -1
- package/dist/api/saveLocalEdits.js +2 -2
- package/dist/api/saveLocalEdits.js.map +1 -1
- package/dist/cli/base.d.ts +2 -0
- package/dist/cli/base.js +45 -2
- package/dist/cli/base.js.map +1 -1
- package/dist/cli/commands/api.d.ts +17 -0
- package/dist/cli/commands/api.js +153 -0
- package/dist/cli/commands/api.js.map +1 -0
- package/dist/cli/commands/upload.js +15 -5
- package/dist/cli/commands/upload.js.map +1 -1
- package/dist/cli/commands/utils/validation.d.ts +4 -0
- package/dist/cli/commands/utils/validation.js +12 -5
- package/dist/cli/commands/utils/validation.js.map +1 -1
- package/dist/config/generateSettings.js +7 -0
- package/dist/config/generateSettings.js.map +1 -1
- package/dist/console/index.d.ts +1 -0
- package/dist/console/index.js +2 -1
- package/dist/console/index.js.map +1 -1
- package/dist/formats/files/aggregateFiles.js +14 -6
- package/dist/formats/files/aggregateFiles.js.map +1 -1
- package/dist/fs/fileContent.d.ts +65 -0
- package/dist/fs/fileContent.js +171 -0
- package/dist/fs/fileContent.js.map +1 -0
- package/dist/generated/version.d.ts +1 -1
- package/dist/generated/version.js +1 -1
- package/dist/generated/version.js.map +1 -1
- package/dist/state/recentDownloads.d.ts +3 -2
- package/dist/state/recentDownloads.js.map +1 -1
- package/dist/translation/reviewSetupWarning.js +3 -3
- package/dist/translation/reviewSetupWarning.js.map +1 -1
- package/dist/utils/api.d.ts +194 -0
- package/dist/utils/api.js +268 -0
- package/dist/utils/api.js.map +1 -0
- package/dist/utils/persistPostprocessHashes.d.ts +1 -7
- package/dist/utils/persistPostprocessHashes.js +15 -1
- package/dist/utils/persistPostprocessHashes.js.map +1 -1
- package/dist/workflows/download.js +4 -4
- package/dist/workflows/download.js.map +1 -1
- package/dist/workflows/enqueue.js +4 -4
- package/dist/workflows/enqueue.js.map +1 -1
- package/dist/workflows/publish.js +2 -2
- package/dist/workflows/publish.js.map +1 -1
- package/dist/workflows/setupProject.js +4 -4
- package/dist/workflows/setupProject.js.map +1 -1
- package/dist/workflows/stage.js +7 -7
- package/dist/workflows/stage.js.map +1 -1
- package/dist/workflows/steps/BranchStep.d.ts +2 -2
- package/dist/workflows/steps/BranchStep.js +9 -9
- package/dist/workflows/steps/BranchStep.js.map +1 -1
- package/dist/workflows/steps/DownloadStep.d.ts +3 -3
- package/dist/workflows/steps/DownloadStep.js +3 -3
- package/dist/workflows/steps/DownloadStep.js.map +1 -1
- package/dist/workflows/steps/EnqueueStep.d.ts +5 -3
- package/dist/workflows/steps/EnqueueStep.js.map +1 -1
- package/dist/workflows/steps/PollJobsStep.d.ts +3 -3
- package/dist/workflows/steps/PollJobsStep.js +6 -6
- package/dist/workflows/steps/PollJobsStep.js.map +1 -1
- package/dist/workflows/steps/PublishStep.d.ts +3 -3
- package/dist/workflows/steps/PublishStep.js +3 -3
- package/dist/workflows/steps/PublishStep.js.map +1 -1
- package/dist/workflows/steps/SetupStep.d.ts +6 -4
- package/dist/workflows/steps/SetupStep.js.map +1 -1
- package/dist/workflows/steps/TagStep.d.ts +3 -3
- package/dist/workflows/steps/TagStep.js +3 -3
- package/dist/workflows/steps/TagStep.js.map +1 -1
- package/dist/workflows/steps/UploadSourcesStep.d.ts +3 -3
- package/dist/workflows/steps/UploadSourcesStep.js +8 -6
- package/dist/workflows/steps/UploadSourcesStep.js.map +1 -1
- package/dist/workflows/steps/UploadTranslationsStep.d.ts +3 -3
- package/dist/workflows/steps/UploadTranslationsStep.js +24 -6
- package/dist/workflows/steps/UploadTranslationsStep.js.map +1 -1
- package/dist/workflows/upload.js +4 -4
- package/dist/workflows/upload.js.map +1 -1
- package/dist/workflows/utils/filterFilesForEnqueue.d.ts +2 -2
- package/dist/workflows/utils/filterFilesForEnqueue.js.map +1 -1
- package/dist/workflows/utils/queryCompletedTranslations.d.ts +3 -3
- package/dist/workflows/utils/queryCompletedTranslations.js +2 -2
- package/dist/workflows/utils/queryCompletedTranslations.js.map +1 -1
- package/package.json +5 -5
package/dist/cli/base.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base.js","names":[],"sources":["../../src/cli/base.ts"],"sourcesContent":["import { Command } from 'commander';\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 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 { retrieveCredentials, setCredentials } from '../utils/credentials.js';\nimport { areCredentialsSet } from '../utils/credentials.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 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, type MergeDriverName } from '../git/mergeDrivers.js';\nimport { setupGitMergeDrivers } from '../git/setupMergeDrivers.js';\nimport { warnReactPackageCompatibility } from '../utils/reactPackageCompatibility.js';\nimport { createDiagnosticMessage } from 'generaltranslation/internal';\nimport { setupViteSPA } from '../setup/setupViteSPA.js';\nimport { manifestDirectlyDeclaresGTVue } from '@generaltranslation/vue-extractor/integration';\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});\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\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 LoginOptions = {\n config?: string;\n keyType?: 'development' | 'production' | 'all';\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 // 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.setupLoginCommand();\n this.setupSendDiffsCommand();\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 await saveLocalEdits(settings);\n logger.endCommand('Saved local edits');\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(\n driver as MergeDriverName,\n base,\n ours,\n theirs\n );\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 setupLoginCommand(): void {\n this.program\n .command('auth')\n .description('Generate General Translation API keys and project ID')\n .option(\n '-c, --config <path>',\n 'Filepath to config file, by default gt.config.json',\n findFilepath(['gt.config.json'])\n )\n .option(\n '-t, --key-type <type>',\n 'Type of key to generate, production | development | all'\n )\n .action(async (options: LoginOptions) => {\n displayHeader('Authenticating with General Translation...');\n if (!options.keyType) {\n options.keyType = await promptSelect<\n 'development' | 'production' | 'all'\n >({\n message: 'What type of API key would you like to generate?',\n options: [\n { value: 'development', label: 'Development' },\n { value: 'production', label: 'Production' },\n { value: 'all', label: 'Both' },\n ],\n defaultValue: 'all',\n });\n } else {\n if (\n options.keyType !== 'development' &&\n options.keyType !== 'production' &&\n options.keyType !== 'all'\n ) {\n logErrorAndExit(\n 'Invalid key type, must be development, production, or all'\n );\n }\n }\n await this.handleLoginCommand(options);\n logger.endCommand(\n `Done! ${options.keyType} keys have been generated and saved to your .env.local file.`\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 );\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 ): 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 // Set credentials\n if ((!isVite || !isUsingGT || usingCDN) && !areCredentialsSet()) {\n const loginQuestion = useDefaults\n ? true\n : await promptConfirm({\n message:\n 'Would you like the wizard to automatically generate API keys and a project ID for you?',\n defaultValue: true,\n });\n if (loginQuestion) {\n const settings = await generateSettings({});\n const keyType = useDefaults\n ? 'all'\n : await promptSelect<'development' | 'production' | 'all'>({\n message: 'What type of API key would you like to generate?',\n options: [\n { value: 'development', label: 'Development' },\n { value: 'production', label: 'Production' },\n { value: 'all', label: 'Both' },\n ],\n defaultValue: 'all',\n });\n const credentials = await retrieveCredentials(settings, keyType);\n await setCredentials(credentials, isVite ? 'vite' : settings.framework);\n }\n }\n }\n protected async handleLoginCommand(options: LoginOptions): Promise<void> {\n const settings = await generateSettings({ config: options.config });\n const keyType = options.keyType || 'all';\n const credentials = await retrieveCredentials(settings, keyType);\n await setCredentials(credentials, settings.framework);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiFA,MAAM,oCAAoC,IAAI,IAAI;CAChD;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;AACF,MAAM,0BAA0B,wBAAwB;CACtD,QAAQ;CACR,UAAU;CACV,cAAc;CACd,KAAK;CACL,KAAK;CACN,CAAC;AACF,MAAM,qBAAqB,wBAAwB;CACjD,QAAQ;CACR,UAAU;CACV,cACE;CACF,SAAS;CACV,CAAC;AAEF,eAAe,+BAA8C;CAC3D,MAAM,cAAc,MAAM,sBAAsB;AAChD,KAAI,eAAe,mBAAmB,YAAY,aAAa,OAAO,KAAK,CACzE,iBAAgB,mBAAmB;AAErC,KACE,GAAG,WAAW,KAAK,KAAK,QAAQ,KAAK,EAAE,sBAAsB,CAAC,IAC9D,aAAa,WAEb,iBAAgB,wBAAwB;;AAmC5C,IAAa,UAAb,MAAqB;CACnB;CACA;CACA;CAEA,YACE,SACA,SACA,mBACA;AACA,OAAK,UAAU;AACf,OAAK,UAAU;AACf,OAAK,oBAAoB,qBAAqB,EAAE;AAEhD,OAAK,QAAQ,OACX,wBACA,yDACD;AACD,OAAK,QAAQ,OACX,uCACA,sDACD;AACD,OAAK,QAAQ,OACX,eACA,oEACD;AAKD,OAAK,QAAQ,KAAK,mBAAmB;AACnC,UAAO,SAAS,QAAQ,KAAK,QAAQ,MAAM,CAAC,MAAM,CAAC;IACnD;AACF,OAAK,QAAQ,KAAK,aAAa,OAAO,aAAa,kBAAkB;AAGnE,OAAI,cAAc,WAAW,YAAa;AAC1C,OAAI,CAAC,kCAAkC,IAAI,cAAc,MAAM,CAAC,CAAE;AAClE,SAAM,8BACJ,QAAQ,KAAK,QAAQ,MAAM,CAAC,+BAA+B,CAC5D;IACD;AAEF,OAAK,kBAAkB;AACvB,OAAK,uBAAuB;AAC5B,OAAK,oBAAoB;AACzB,OAAK,mBAAmB;AACxB,OAAK,uBAAuB;AAC5B,OAAK,iBAAiB;;CAGxB,OAAc;AACZ,OAAK,0BAA0B;AAC/B,OAAK,mBAAmB;AACxB,OAAK,uBAAuB;AAC5B,OAAK,sBAAsB;AAC3B,OAAK,qBAAqB;;CAG5B,UAAiB;AAEf,MAAI,QAAQ,KAAK,UAAU,EACzB,SAAQ,KAAK,KAAK,OAAO;;CAI7B,2BAA2C;AACzC,uBACE,KAAK,QACF,QAAQ,QAAQ,CAChB,YACC,4DACD,CACJ,CAAC,OAAO,OAAO,gBAAgC;AAC9C,iBAAc,mDAAmD;AACjE,SAAM,KAAK,mBAAmB,YAAY;AAC1C,UAAO,WAAW,QAAQ;IAC1B;;CAGJ,oBAAoC;AAClC,uBACE,KAAK,QACF,QAAQ,QAAQ,CAChB,YACC,2IACD,CACJ,CAAC,OAAO,OAAO,gBAAgC;AAC9C,iBACE,4DACD;AACD,SAAM,KAAK,YAAY,YAAY;AACnC,UAAO,WAAW,QAAQ;IAC1B;;;;;;;CAQJ,sBAAsC;AACpC,uBACE,KAAK,QACF,QAAQ,UAAU,CAClB,YAAY,iDAAiD,CACjE,CAAC,OAAO,OAAO,gBAAgC;AAC9C,iBAAc,4BAA4B;AAC1C,SAAM,KAAK,cAAc,YAAY;AACrC,UAAO,WAAW,QAAQ;IAC1B;;;;;;;CAQJ,uBAAuC;AACrC,uBACE,KAAK,QACF,QAAQ,WAAW,CACnB,YAAY,oDAAoD,CACpE,CAAC,OAAO,OAAO,gBAAgC;AAC9C,iBAAc,8BAA8B;AAC5C,SAAM,KAAK,eAAe,YAAY;AACtC,UAAO,WAAW,QAAQ;IAC1B;;CAGJ,wBAAwC;AACtC,uBACE,KAAK,QACF,QAAQ,YAAY,CACpB,YAAY,mDAAmD,CACnE,CAAC,OAAO,OAAO,gBAAgC;AAC9C,iBAAc,0BAA0B;AACxC,SAAM,KAAK,gBAAgB,YAAY;AACvC,UAAO,WAAW,QAAQ;IAC1B;;CAGJ,wBAAwC;AACtC,oBACE,KAAK,QACF,QAAQ,aAAa,CACrB,YACC,uFACD,CACJ,CACE,OAAO,aAAa,mCAAmC,MAAM,CAC7D,OAAO,OAAO,gBAA6B;AAC1C,iBAAc,wBAAwB;AAItC,SAAM,eAAe,MAHE,iBAAiB,aAAa,KAAA,GAAW,EAC9D,eAAe,MAChB,CAAC,CAC4B;AAC9B,UAAO,WAAW,oBAAoB;IACtC;;CAGN,kBAAkC;EAChC,MAAM,aAAa,KAAK,QACrB,QAAQ,MAAM,CACd,YAAY,qDAAqD;AAEpE,aACG,QAAQ,QAAQ,CAChB,YAAY,0DAA0D,CACtE,OACC,uBACA,sDACA,aAAa,CAAC,iBAAiB,CAAC,CACjC,CACA,OAAO,aAAa,uCAAuC,MAAM,CACjE,OACC,qBACA,wDACD,CACA,OACC,8BACA,6DACD,CACA,OAAO,OAAO,YAA6B;AAC1C,iBAAc,qCAAqC;GACnD,MAAM,WAAW,MAAM,iBAAiB,SAAS,KAAA,GAAW,EAC1D,eAAe,MAChB,CAAC;GACF,MAAM,gBAAgB,MAAM,KAAK,6BAC/B,SACA,SACD;GACD,MAAM,SAAS,MAAM,qBAAqB,UAAU;IAClD,QAAQ,QAAQ;IAChB;IACA,eAAe,QAAQ;IACxB,CAAC;AAEF,QAAK,MAAM,QAAQ,OAAO,gBACxB,QAAO,KACL,GAAG,QAAQ,SAAS,cAAc,QAAQ,GAAG,MAAM,KACjD,KACD,CAAC,MAAM,MAAM,KAAK,OAAO,kBAAkB,GAC7C;AAEH,OAAI,OAAO,gBAAgB,WAAW,EACpC,QAAO,KAAK,GAAG,MAAM,KAAK,iBAAiB,CAAC,yBAAyB;AAGvE,QAAK,MAAM,QAAQ,OAAO,kBACxB,QAAO,KACL,GAAG,QAAQ,SAAS,cAAc,aAAa,GAAG,MAAM,KACtD,sBAAsB,KAAK,KAAK,IAAI,GACrC,GACF;AAGH,OAAI,OAAO,cACT,QAAO,KACL,GAAG,QAAQ,SAAS,kBAAkB,YAAY,GAAG,MAAM,KACzD,sBACD,CAAC,MAAM,MAAM,KAAK,SAAS,OAAO,GACpC;YACQ,QAAQ,UAAU,CAAC,SAAS,cACrC,QAAO,KACL,eAAe,MAAM,KAAK,YAAY,CAAC,6BAA6B,MAAM,KACxE,sBACD,CAAC,YAAY,MAAM,KAAK,oBAAoB,CAAC,GAC/C;AAGH,QAAK,MAAM,WAAW,OAAO,SAC3B,QAAO,KAAK,MAAM,OAAO,QAAQ,CAAC;AAGpC,UAAO,WACL,QAAQ,SACJ,sBACA,mCACL;IACD;AAEJ,aACG,QAAQ,gBAAgB,EAAE,QAAQ,MAAM,CAAC,CACzC,SAAS,YAAY,oBAAoB,CACzC,SAAS,UAAU,uBAAuB,CAC1C,SAAS,UAAU,sBAAsB,CACzC,SAAS,YAAY,uBAAuB,CAC5C,SAAS,UAAU,cAAc,CACjC,QAAQ,QAAgB,MAAc,MAAc,WAAmB;AACtE,OAAI,WAAW,aAAa,WAAW,UAAU;AAC/C,WAAO,MAAM,4BAA4B,SAAS;AAClD,aAAS,EAAE;;GAEb,MAAM,SAAS,eACb,QACA,MACA,MACA,OACD;AACD,OAAI,CAAC,OAAO,IAAI;AACd,WAAO,MAAM,OAAO,OAAO;AAC3B,aAAS,EAAE;;IAEb;;CAGN,MAAgB,6BACd,SACA,UACkB;AAClB,MAAI,QAAQ,cAAe,QAAO;AAElC,MAAI,SAAS,cAAe,QAAO;AACnC,MAAI,QAAQ,UAAU,CAAC,QAAQ,MAAM,SAAS,CAAC,QAAQ,OAAO,MAC5D,QAAO;AAET,SAAO,cAAc;GACnB,SACE;GACF,cAAc;GACf,CAAC;;CAGJ,MAAgB,mBACd,aACe;EACf,MAAM,WAAW,MAAM,iBAAiB,aAAa,KAAA,GAAW,EAC9D,eAAe,MAChB,CAAC;AAGF,QAAM,0BAA0B,SAAS;AAEzC,QAAM,mBAAmB,aAAa,UAAU,KAAK,QAAQ;;CAG/D,MAAgB,YAAY,aAA4C;EACtE,MAAM,WAAW,MAAM,iBAAiB,aAAa,KAAA,GAAW,EAC9D,eAAe,MAChB,CAAC;AAGF,QAAM,0BAA0B,SAAS;AAEzC,MAAI,CAAC,SAAS,mBAAmB;AAE/B,YAAS,oBAAoB;AAC7B,SAAM,aAAa,SAAS,QAAQ,EAClC,mBAAmB,MACpB,CAAC;;AAEJ,QAAM,YAAY,aAAa,UAAU,KAAK,SAAS,KAAK;;;;;;;CAQ9D,MAAgB,cAAc,aAA4C;AAIxE,QAAM,cAAc,aAAa,MAHV,iBAAiB,aAAa,KAAA,GAAW,EAC9D,eAAe,MAChB,CAAC,EACyC,KAAK,QAAQ;;;;;;;CAQ1D,MAAgB,eAAe,aAA4C;AAIzE,QAAM,eAAe,aAAa,MAHX,iBAAiB,aAAa,KAAA,GAAW,EAC9D,eAAe,MAChB,CAAC,EAC0C,KAAK,QAAQ;;CAG3D,MAAgB,gBAAgB,aAA4C;EAC1E,MAAM,WAAW,MAAM,iBAAiB,aAAa,KAAA,GAAW,EAC9D,eAAe,MAChB,CAAC;AAGF,QAAM,0BAA0B,SAAS;AAEzC,MAAI,CAAC,SAAS,mBAAmB;AAK/B,OAAI,SAAS,OAAO,cAAc,QAAQ,OACxC,QAAO,gBAAgB,qBAAqB;GAE9C,MAAM,UAAU,MAAM,YACpB,aACA,UACA,KAAK,SACL,MACD;AACD,OAAI,QACF,OAAM,gBACJ,aACA,UACA,QAAQ,iBACR,QAAQ,SACR,QAAQ,YACR,QAAQ,YACR,QAAQ,cACT;QAGH,OAAM,eAAe,aAAa,UAAU,KAAK,QAAQ;EAG3D,MAAM,UAAU,wBAAwB;AACxC,MAAI,QAAQ,OAAO,EACjB,OAAM,wBAAwB,UAAU,QAAQ;AAGlD,QAAM,0BAA0B,SAAS;AAEzC,QAAM,sBAAsB,SAAS;AACrC,mBAAiB;AACjB,2BAAyB;AACzB,iBAAe;;CAGjB,qBAAqC;AACnC,uBACE,KAAK,QACF,QAAQ,SAAS,CACjB,YACC,2EACD,CACJ,CAAC,OAAO,OAAO,gBAA+B;AAC7C,iBAAc,qBAAqB;GACnC,MAAM,WAAW,MAAM,iBAAiB,aAAa,KAAA,GAAW,EAC9D,eAAe,MAChB,CAAC;GAEF,MAAM,UAAU;IAAE,GAAG;IAAa,GAAG;IAAU;AAE/C,SAAM,KAAK,oBAAoB,QAAQ;AACvC,UAAO,WAAW,QAAQ;IAC1B;;CAGJ,oBAAoC;AAClC,OAAK,QACF,QAAQ,OAAO,CACf,YAAY,uDAAuD,CACnE,OACC,uBACA,sDACA,aAAa,CAAC,iBAAiB,CAAC,CACjC,CACA,OACC,yBACA,0DACD,CACA,OAAO,OAAO,YAA0B;AACvC,iBAAc,6CAA6C;AAC3D,OAAI,CAAC,QAAQ,QACX,SAAQ,UAAU,MAAM,aAEtB;IACA,SAAS;IACT,SAAS;KACP;MAAE,OAAO;MAAe,OAAO;MAAe;KAC9C;MAAE,OAAO;MAAc,OAAO;MAAc;KAC5C;MAAE,OAAO;MAAO,OAAO;MAAQ;KAChC;IACD,cAAc;IACf,CAAC;YAGA,QAAQ,YAAY,iBACpB,QAAQ,YAAY,gBACpB,QAAQ,YAAY,MAEpB,iBACE,4DACD;AAGL,SAAM,KAAK,mBAAmB,QAAQ;AACtC,UAAO,WACL,SAAS,QAAQ,QAAQ,8DAC1B;IACD;;CAGN,mBAAmC;AACjC,OAAK,QACF,QAAQ,OAAO,CACf,YACC,yEACD,CACA,OACC,oBACA,0MACD,CACA,OACC,uBACA,sDACA,aAAa,CAAC,iBAAiB,CAAC,CACjC,CACA,OAAO,OAAO,YAA0B;AACvC,SAAM,8BAA8B;GACpC,MAAM,WAAW,MAAM,iBAAiB,QAAQ;AAChD,iBAAc,0BAA0B;GAExC,MAAM,YAAY,MAAM,iBAAiB;AAmBzC,OAAI,OAjBoB,YAAY;IAClC,IAAI;AACJ,QAAI,UAAU,SAAS,WACrB,mBAAkB;AAEpB,QAAI,UAAU,SAAS,WACrB,mBAAkB;AAEpB,QAAI,gBACF,QAAO,MAAM,cAAc;KACzB,SAAS;KACT,cAAc;KACf,CAAC;AAEJ,WAAO;OACL,EAEU;AACZ,UAAM,aAAa,SAAS;AAC5B,WAAO,WACL,4IACD;UACI;IAEL,MAAM,uBACJ,UAAU,SAAS,UACf,wBAAwB,UAAU,GAClC;IACN,MAAM,UACJ,UAAU,SAAS,UACf,yBAAyB,UAAU,GACnC;IAGN,MAAM,yBACJ,UAAU,SAAS,SACf,gCACA;IAEN,MAAM,sBACJ,UAAU,SAAS,SACf,GAAG,QAAQ,sBAAsB,qBAAqB,2BAA2B,2BACjF,UAAU,SAAS,UACjB,GAAG,QAAQ,iBAAiB,qBAAqB,2BAA2B,2BAC5E,0BAA0B;IAGlC,MAAM,cAAc,MAAM,cAAc;KACtC,SAAS,uEAAuE,MAAM,IAAI,IAAI,oBAAoB,GAAG;KACrH,cAAc;KACf,CAAC;IAEF,IAAI,gBAAgB;AAGpB,QAAI,UAAU,SAAS;SACR,cACT,OACA,MAAM,cAAc;MAClB,SACE,UAAU,SAAS,SACf,6BAA6B,QAAQ,qIACrC,6BAA6B,QAAQ;MAC3C,cAAc;MACf,CAAC,EAEI;AACR,aAAO,KACL,GAAG,MAAM,OAAO,iBAAiB,CAAC,yBACnC;AACD,YAAM,wBAAwB,SAAS,WAAW,YAAY;AAC9D,aAAO,WACL;0IAED;AACD,sBAAgB;;;AAIpB,QAAI,cACF,QAAO,aAAa,+BAA+B;AAGrD,UAAM,KAAK,kBACT,eACA,aACA,UAAU,SAAS,OACpB;AAED,WAAO,WACL,uHACD;;IAEH;;CAGN,wBAAwC;AACtC,OAAK,QACF,QAAQ,YAAY,CACpB,YACC,2GACD,CACA,aAAa,KAAK,wBAAwB,CAAC;;CAGhD,MAAgB,uBACd,SACe;AACf,QAAM,8BAA8B;AACpC,gBAAc,yBAAyB;AAEvC,SAAO,KACL,oKACD;EAGD,MAAM,YAAY,MAAM,iBAAiB;AACzC,QAAM,KAAK,kBACT,OACA,OACA,UAAU,SAAS,QACnB,QACD;AAED,SAAO,WACL,qJACD;;CAGH,MAAgB,oBACd,UACe;AACf,MAAI,CAAC,SAAS,MACZ;AAIF,QAAM,OAAO,SAAS;;;CAIxB,sBACE,aACA,gBAAyB,OACL;AACpB,SAAO;GACL,uBAAuB,iBAAiB,MACrC,QACC,QAAA,YAA4B,mBAAmB,KAAK,YAAY,CACnE;GACD,eAAe,8BAA8B,YAAY;GACzD;GACD;;;CAIH,yBACE,aACS;EACT,MAAM,EAAE,uBAAuB,kBAC7B,KAAK,sBAAsB,YAAY;AACzC,SAAO,yBAAyB;;;CAIlC,mBAA6B,cAA2C;AACtE,SAAO,CAAC,aAAa;;;CAIvB,qCACE,QACA,cACS;AACT,MAAI,OAAQ,QAAO;AACnB,MAAI,CAAC,aAAa,cAAe,QAAO;AACxC,SAAO,aAAa,yBAAyB,aAAa;;;CAI5D,4BAAsC,EACpC,iBACA,cACA,mBACsD;EACtD,MAAM,WAAqB,EAAE;AAC7B,MAAI,gBACF,UAAS,KAAK,WAAW,MAAM,KAAK,sBAAsB,CAAC;;iEAEA;AAE7D,MAAI,aAAa,cACf,UAAS,KAAK,4CAA4C,gBAAgB;;0CAEtC;AAEtC,SAAO,SAAS,SAAS,IAAI,SAAS,KAAK,KAAK,GAAG,KAAA;;CAIrD,MAAgB,kBACd,eACA,cAAuB,OACvB,SAAkB,OAClB,SACe;EACf,MAAM,iBACJ,SAAS,WACR,CAAC,UAAU,GAAG,WAAW,qBAAqB,GAC3C,uBACA;EAEN,MAAM,EAAE,eAAe,YAAY,MAAM,kBADlB,WAAW,eACuC,CAAC;EAE1E,MAAM,cAAc,MAAM,sBAAsB;EAGhD,MAAM,eAAmC,cACrC,KAAK,sBAAsB,aAAa,cAAc,GACtD;GACE,uBAAuB;GACvB,eAAe;GACf;GACD;EACL,MAAM,YACJ,aAAa,iBACb,aAAa,yBACb,aAAa;EAGf,MAAM,WAAW,OAAO,YAAY;AAClC,OAAI,CAAC,UAAW,QAAO;AACvB,OAAI,YAAa,QAAO;AACxB,OAAI,CAAC,KAAK,mBAAmB,aAAa,CAAE,QAAO;AASnD,UAAO,MARqB,aAAa;IACvC,SAAS;IACT,SAAS,CACP;KAAE,OAAO;KAAS,OAAO;KAAgB,EACzC;KAAE,OAAO;KAAO,OAAO;KAAW,CACnC;IACD,cAAc;IACf,CAAC,KACuB;MACvB;EAEJ,MAAM,yBAAyB,SAC3B,gCACA;EAeJ,MAAM,wBAXJ,aAAa,CAAC,WACV,cACE,yBACA,MAAM,WAAW;GACf,SACE;GACF,cAAc;GACf,CAAC,GACJ,OAIa,MAAM,IAAI;AAE7B,MAAI,aAAa,CAAC,UAAU;GAC1B,MAAM,kBAAkB,KAAK,qCAC3B,QACA,aACD;AACD,OAAI,gBACF,OAAM,2BACJ,QAAQ,KAAK,EACb,sBACA,QACD;GAEH,MAAM,WAAW,KAAK,4BAA4B;IAChD;IACA;IACA,iBAAiB;IAClB,CAAC;AACF,OAAI,SAAU,QAAO,QAAQ,SAAS;;EAGxC,MAAM,UAAU,CAAC,YACb,iKACA,wGAAwG,MAAM,IAC5G,8CACD;EACL,MAAM,iBACJ,eAAe,YACX,EAAE,GACF,MAAM,kBAAkB;GACtB;GACA,SAAS;IACP;KAAE,OAAO;KAAQ,OAAO,sBAAsB;KAAM;IACpD;KAAE,OAAO;KAAM,OAAO,sBAAsB;KAAI;IAChD;KAAE,OAAO;KAAO,OAAO,sBAAsB;KAAK;IAClD;KAAE,OAAO;KAAM,OAAO,sBAAsB;KAAI;IAChD;KAAE,OAAO;KAAM,OAAO,sBAAsB;KAAI;IAChD;KAAE,OAAO;KAAQ,OAAO,sBAAsB;KAAM;IAErD;GACD,UAAU,CAAC;GACZ,CAAC;EAER,MAAM,QAAsB,EAAE;AAC9B,OAAK,MAAM,iBAAiB,gBAAgB;GAC1C,MAAM,QAAQ,sBAAsB;AAOpC,SAAM,iBAAiB,EACrB,SAAS,kBAAkB,MAPT,mBAAmB;IACrC;IACA,SAAS,GAAG,MAAM,KAAK,sBAAsB,eAAe,CAAC,+EAA+E,sBAAsB,eAAe;IACjL,cAAc,mBAAmB;IAClC,CAAC,CAGiC,EAClC;;AAIH,MAAI,aAAa,CAAC,SAChB,OAAM,KAAK,EACT,QAAQ,KAAK,KAAK,sBAAsB,gBAAgB,EACzD;AAIH,QAAM,qBAAqB,gBAAgB;GACzC;GACA;GACA,KAAK,SAAS;GACd,OAAO,OAAO,KAAK,MAAM,CAAC,SAAS,IAAI,QAAQ,KAAA;GAC/C,WAAW,SAAS,SAAS,KAAA;GAC7B,SAAS,aAAa;GACtB,cAAc,aAAa,iBAAiB,CAAC;GAC9C,CAAC;AAEF,SAAO,QACL,QAAQ,MAAM,KACZ,eACD,CAAC,sGACH;AAED,MAAI,iBAAiB,OACnB,OAAM,aAAa;GACjB,cAAc,QAAQ,KAAK;GAC3B;GACA;GACA;GACA,iBAAiB,WAAW,KAAA,IAAY;GACzC,CAAC;AAQJ,MAAI,EAJmB,cACnB,mBAAmB,MAAM,aAAa,MAAM,KAAK,GACjD,SAEmB,EAAE,aAAa,SAAS;GAC7C,MAAM,iBAAiB,MAAM,mBAAmB;GAChD,MAAM,UAAU,OAAO,eAAe;AACtC,WAAQ,MACN,0CAA0C,eAAe,KAAK,KAC/D;AACD,SAAM,eAAe,MAAM,gBAAgB,KAAK;AAChD,WAAQ,KAAK,MAAM,MAAM,gBAAgB,CAAC;;AAI5C,OAAK,CAAC,UAAU,CAAC,aAAa,aAAa,CAAC,mBAAmB;OACvC,cAClB,OACA,MAAM,cAAc;IAClB,SACE;IACF,cAAc;IACf,CAAC,EACa;IACjB,MAAM,WAAW,MAAM,iBAAiB,EAAE,CAAC;AAa3C,UAAM,eAAe,MADK,oBAAoB,UAX9B,cACZ,QACA,MAAM,aAAmD;KACvD,SAAS;KACT,SAAS;MACP;OAAE,OAAO;OAAe,OAAO;OAAe;MAC9C;OAAE,OAAO;OAAc,OAAO;OAAc;MAC5C;OAAE,OAAO;OAAO,OAAO;OAAQ;MAChC;KACD,cAAc;KACf,CAAC,CAC0D,EAC9B,SAAS,SAAS,SAAS,UAAU;;;;CAI7E,MAAgB,mBAAmB,SAAsC;EACvE,MAAM,WAAW,MAAM,iBAAiB,EAAE,QAAQ,QAAQ,QAAQ,CAAC;AAGnE,QAAM,eAAe,MADK,oBAAoB,UAD9B,QAAQ,WAAW,MAC6B,EAC9B,SAAS,UAAU"}
|
|
1
|
+
{"version":3,"file":"base.js","names":[],"sources":["../../src/cli/base.ts"],"sourcesContent":["import { Command } from 'commander';\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 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 { retrieveCredentials, setCredentials } from '../utils/credentials.js';\nimport { areCredentialsSet } from '../utils/credentials.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 hasValidApiKey,\n hasValidCredentials,\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/internal';\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 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\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 LoginOptions = {\n config?: string;\n keyType?: 'development' | 'production' | 'all';\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 // 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.setupLoginCommand();\n this.setupSendDiffsCommand();\n this.setupApiCommand();\n this.setupProjectCommands();\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)) 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('--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 uses an organization key before a project ID exists.\n if (!hasValidApiKey(settings)) return exitSync(1);\n const { project } = await api.createProject({\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 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 setupLoginCommand(): void {\n this.program\n .command('auth')\n .description('Generate General Translation API keys and project ID')\n .option(\n '-c, --config <path>',\n 'Filepath to config file, by default gt.config.json',\n findFilepath(['gt.config.json'])\n )\n .option(\n '-t, --key-type <type>',\n 'Type of key to generate, production | development | all'\n )\n .action(async (options: LoginOptions) => {\n displayHeader('Authenticating with General Translation...');\n if (!options.keyType) {\n options.keyType = await promptSelect<\n 'development' | 'production' | 'all'\n >({\n message: 'What type of API key would you like to generate?',\n options: [\n { value: 'development', label: 'Development' },\n { value: 'production', label: 'Production' },\n { value: 'all', label: 'Both' },\n ],\n defaultValue: 'all',\n });\n } else {\n if (\n options.keyType !== 'development' &&\n options.keyType !== 'production' &&\n options.keyType !== 'all'\n ) {\n logErrorAndExit(\n 'Invalid key type, must be development, production, or all'\n );\n }\n }\n await this.handleLoginCommand(options);\n logger.endCommand(\n `Done! ${options.keyType} keys have been generated and saved to your .env.local file.`\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 );\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 ): 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 // Set credentials\n if ((!isVite || !isUsingGT || usingCDN) && !areCredentialsSet()) {\n const loginQuestion = useDefaults\n ? true\n : await promptConfirm({\n message:\n 'Would you like the wizard to automatically generate API keys and a project ID for you?',\n defaultValue: true,\n });\n if (loginQuestion) {\n const settings = await generateSettings({});\n const keyType = useDefaults\n ? 'all'\n : await promptSelect<'development' | 'production' | 'all'>({\n message: 'What type of API key would you like to generate?',\n options: [\n { value: 'development', label: 'Development' },\n { value: 'production', label: 'Production' },\n { value: 'all', label: 'Both' },\n ],\n defaultValue: 'all',\n });\n const credentials = await retrieveCredentials(settings, keyType);\n await setCredentials(credentials, isVite ? 'vite' : settings.framework);\n }\n }\n }\n protected async handleLoginCommand(options: LoginOptions): Promise<void> {\n const settings = await generateSettings({ config: options.config });\n const keyType = options.keyType || 'all';\n const credentials = await retrieveCredentials(settings, keyType);\n await setCredentials(credentials, settings.framework);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0FA,MAAM,oCAAoC,IAAI,IAAI;CAChD;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;AACF,MAAM,0BAA0B,wBAAwB;CACtD,QAAQ;CACR,UAAU;CACV,cAAc;CACd,KAAK;CACL,KAAK;CACN,CAAC;AACF,SAAS,0BACP,cACA,OACQ;AACR,QAAO,wBAAwB;EAC7B,QAAQ;EACR,UAAU;EACV;EACA,SAAS,6BAA6B,MAAM;EAC7C,CAAC;;AAGJ,MAAM,qBAAqB,wBAAwB;CACjD,QAAQ;CACR,UAAU;CACV,cACE;CACF,SAAS;CACV,CAAC;AAEF,eAAe,+BAA8C;CAC3D,MAAM,cAAc,MAAM,sBAAsB;AAChD,KAAI,eAAe,mBAAmB,YAAY,aAAa,OAAO,KAAK,CACzE,iBAAgB,mBAAmB;AAErC,KACE,GAAG,WAAW,KAAK,KAAK,QAAQ,KAAK,EAAE,sBAAsB,CAAC,IAC9D,aAAa,WAEb,iBAAgB,wBAAwB;;AAmC5C,IAAa,UAAb,MAAqB;CACnB;CACA;CACA;CAEA,YACE,SACA,SACA,mBACA;AACA,OAAK,UAAU;AACf,OAAK,UAAU;AACf,OAAK,oBAAoB,qBAAqB,EAAE;AAEhD,OAAK,QAAQ,OACX,wBACA,yDACD;AACD,OAAK,QAAQ,OACX,uCACA,sDACD;AACD,OAAK,QAAQ,OACX,eACA,oEACD;AAKD,OAAK,QAAQ,KAAK,mBAAmB;AACnC,UAAO,SAAS,QAAQ,KAAK,QAAQ,MAAM,CAAC,MAAM,CAAC;IACnD;AACF,OAAK,QAAQ,KAAK,aAAa,OAAO,aAAa,kBAAkB;AAGnE,OAAI,cAAc,WAAW,YAAa;AAC1C,OAAI,CAAC,kCAAkC,IAAI,cAAc,MAAM,CAAC,CAAE;AAClE,SAAM,8BACJ,QAAQ,KAAK,QAAQ,MAAM,CAAC,+BAA+B,CAC5D;IACD;AAEF,OAAK,kBAAkB;AACvB,OAAK,uBAAuB;AAC5B,OAAK,oBAAoB;AACzB,OAAK,mBAAmB;AACxB,OAAK,uBAAuB;AAC5B,OAAK,iBAAiB;AACtB,OAAK,sBAAsB;AAC3B,OAAK,iBAAiB;;CAGxB,OAAc;AACZ,OAAK,0BAA0B;AAC/B,OAAK,mBAAmB;AACxB,OAAK,uBAAuB;AAC5B,OAAK,sBAAsB;AAC3B,OAAK,qBAAqB;;CAG5B,UAAiB;AAEf,MAAI,QAAQ,KAAK,UAAU,EACzB,SAAQ,KAAK,KAAK,OAAO;;CAI7B,2BAA2C;AACzC,uBACE,KAAK,QACF,QAAQ,QAAQ,CAChB,YACC,4DACD,CACJ,CAAC,OAAO,OAAO,gBAAgC;AAC9C,iBAAc,mDAAmD;AACjE,SAAM,KAAK,mBAAmB,YAAY;AAC1C,UAAO,WAAW,QAAQ;IAC1B;;CAGJ,oBAAoC;AAClC,uBACE,KAAK,QACF,QAAQ,QAAQ,CAChB,YACC,2IACD,CACJ,CAAC,OAAO,OAAO,gBAAgC;AAC9C,iBACE,4DACD;AACD,SAAM,KAAK,YAAY,YAAY;AACnC,UAAO,WAAW,QAAQ;IAC1B;;;;;;;CAQJ,sBAAsC;AACpC,uBACE,KAAK,QACF,QAAQ,UAAU,CAClB,YAAY,iDAAiD,CACjE,CAAC,OAAO,OAAO,gBAAgC;AAC9C,iBAAc,4BAA4B;AAC1C,SAAM,KAAK,cAAc,YAAY;AACrC,UAAO,WAAW,QAAQ;IAC1B;;;;;;;CAQJ,uBAAuC;AACrC,uBACE,KAAK,QACF,QAAQ,WAAW,CACnB,YAAY,oDAAoD,CACpE,CAAC,OAAO,OAAO,gBAAgC;AAC9C,iBAAc,8BAA8B;AAC5C,SAAM,KAAK,eAAe,YAAY;AACtC,UAAO,WAAW,QAAQ;IAC1B;;CAGJ,wBAAwC;AACtC,uBACE,KAAK,QACF,QAAQ,YAAY,CACpB,YAAY,mDAAmD,CACnE,CAAC,OAAO,OAAO,gBAAgC;AAC9C,iBAAc,0BAA0B;AACxC,SAAM,KAAK,gBAAgB,YAAY;AACvC,UAAO,WAAW,QAAQ;IAC1B;;CAGJ,wBAAwC;AACtC,oBACE,KAAK,QACF,QAAQ,aAAa,CACrB,YACC,uFACD,CACJ,CACE,OAAO,aAAa,mCAAmC,MAAM,CAC7D,OAAO,OAAO,gBAA6B;AAC1C,iBAAc,wBAAwB;GACtC,MAAM,WAAW,MAAM,iBAAiB,aAAa,KAAA,GAAW,EAC9D,eAAe,MAChB,CAAC;AACF,OAAI,CAAC,oBAAoB,SAAS,CAAE,QAAO,SAAS,EAAE;AACtD,SAAM,eAAe,SAAS;AAC9B,UAAO,WAAW,oBAAoB;IACtC;;CAGN,kBAAkC;AAChC,oBACE,KAAK,QACF,QAAQ,iBAAiB,CACzB,YAAY,8CAA8C,CAC1D,OAAO,yBAAyB,eAAe,MAAM,CACrD,OAAO,kBAAkB,6CAA6C,CACtE,OACC,yBACA,4CACC,QAAQ,YAAkC,CACzC,GAAI,WAAW,EAAE,EACjB,OACD,CACF,CACA,OAAO,iBAAiB,sCAAsC,CAC9D,OAAO,UAAU,0CAA0C,CAC/D,CAAC,QAAQ,UAAU,YAClB,iBAAiB,UAAU,QAAQ,CACpC;;CAGH,uBAAuC;EACrC,MAAM,iBAAiB,KAAK,QACzB,QAAQ,UAAU,CAClB,YAAY,sCAAsC;AAErD,oBACE,eACG,QAAQ,SAAS,CACjB,YACC,qEACD,CACA,eAAe,iBAAiB,eAAe,CAC/C,eAAe,6BAA6B,yBAAyB,CACrE,OAAO,iBAAiB,uBAAuB,MAAM,CACzD,CAAC,OAAO,OAAO,YAAY;AAC1B,OAAI;AAGF,QAAI,CAAC,eAAe,MAFG,iBAAiB,QAAQ,CAEnB,CAAE,QAAO,SAAS,EAAE;IACjD,MAAM,EAAE,YAAY,MAAM,IAAI,cAAc;KAC1C,MAAM,QAAQ;KACd,eAAe,QAAQ;KACvB,YAAY,QAAQ;KACrB,CAAC;AACF,WAAO,KAAK,WAAW,QAAQ,KAAK,IAAI,QAAQ,GAAG,GAAG;YAC/C,OAAO;AACd,WAAO,gBACL,0BAA0B,gCAAgC,MAAM,CACjE;;IAEH;AAEF,oBACE,eACG,QAAQ,SAAS,CACjB,YAAY,0CAA0C,CACtD,SAAS,YAAY,eAAe,CACxC,CAAC,OAAO,OAAO,OAAO,YAAY;AACjC,OAAI;AAEF,QAAI,CAAC,oBAAoB,MADF,iBAAiB,QAAQ,CACd,CAAE,QAAO,SAAS,EAAE;IACtD,MAAM,CAAC,UAAU,MAAM,IAAI,eAAe,CAAC,MAAM,CAAC;AAClD,WAAO,KAAK,QAAQ,UAAU,UAAU;YACjC,OAAO;AACd,WAAO,gBACL,0BACE,4CACA,MACD,CACF;;IAEH;;CAGJ,kBAAkC;EAChC,MAAM,aAAa,KAAK,QACrB,QAAQ,MAAM,CACd,YAAY,qDAAqD;AAEpE,aACG,QAAQ,QAAQ,CAChB,YAAY,0DAA0D,CACtE,OACC,uBACA,sDACA,aAAa,CAAC,iBAAiB,CAAC,CACjC,CACA,OAAO,aAAa,uCAAuC,MAAM,CACjE,OACC,qBACA,wDACD,CACA,OACC,8BACA,6DACD,CACA,OAAO,OAAO,YAA6B;AAC1C,iBAAc,qCAAqC;GACnD,MAAM,WAAW,MAAM,iBAAiB,SAAS,KAAA,GAAW,EAC1D,eAAe,MAChB,CAAC;GACF,MAAM,gBAAgB,MAAM,KAAK,6BAC/B,SACA,SACD;GACD,MAAM,SAAS,MAAM,qBAAqB,UAAU;IAClD,QAAQ,QAAQ;IAChB;IACA,eAAe,QAAQ;IACxB,CAAC;AAEF,QAAK,MAAM,QAAQ,OAAO,gBACxB,QAAO,KACL,GAAG,QAAQ,SAAS,cAAc,QAAQ,GAAG,MAAM,KACjD,KACD,CAAC,MAAM,MAAM,KAAK,OAAO,kBAAkB,GAC7C;AAEH,OAAI,OAAO,gBAAgB,WAAW,EACpC,QAAO,KAAK,GAAG,MAAM,KAAK,iBAAiB,CAAC,yBAAyB;AAGvE,QAAK,MAAM,QAAQ,OAAO,kBACxB,QAAO,KACL,GAAG,QAAQ,SAAS,cAAc,aAAa,GAAG,MAAM,KACtD,sBAAsB,KAAK,KAAK,IAAI,GACrC,GACF;AAGH,OAAI,OAAO,cACT,QAAO,KACL,GAAG,QAAQ,SAAS,kBAAkB,YAAY,GAAG,MAAM,KACzD,sBACD,CAAC,MAAM,MAAM,KAAK,SAAS,OAAO,GACpC;YACQ,QAAQ,UAAU,CAAC,SAAS,cACrC,QAAO,KACL,eAAe,MAAM,KAAK,YAAY,CAAC,6BAA6B,MAAM,KACxE,sBACD,CAAC,YAAY,MAAM,KAAK,oBAAoB,CAAC,GAC/C;AAGH,QAAK,MAAM,WAAW,OAAO,SAC3B,QAAO,KAAK,MAAM,OAAO,QAAQ,CAAC;AAGpC,UAAO,WACL,QAAQ,SACJ,sBACA,mCACL;IACD;AAEJ,aACG,QAAQ,gBAAgB,EAAE,QAAQ,MAAM,CAAC,CACzC,SAAS,YAAY,oBAAoB,CACzC,SAAS,UAAU,uBAAuB,CAC1C,SAAS,UAAU,sBAAsB,CACzC,SAAS,YAAY,uBAAuB,CAC5C,SAAS,UAAU,cAAc,CACjC,QAAQ,QAAgB,MAAc,MAAc,WAAmB;AACtE,OAAI,WAAW,aAAa,WAAW,UAAU;AAC/C,WAAO,MAAM,4BAA4B,SAAS;AAClD,aAAS,EAAE;;GAEb,MAAM,SAAS,eAAe,QAAQ,MAAM,MAAM,OAAO;AACzD,OAAI,CAAC,OAAO,IAAI;AACd,WAAO,MAAM,OAAO,OAAO;AAC3B,aAAS,EAAE;;IAEb;;CAGN,MAAgB,6BACd,SACA,UACkB;AAClB,MAAI,QAAQ,cAAe,QAAO;AAElC,MAAI,SAAS,cAAe,QAAO;AACnC,MAAI,QAAQ,UAAU,CAAC,QAAQ,MAAM,SAAS,CAAC,QAAQ,OAAO,MAC5D,QAAO;AAET,SAAO,cAAc;GACnB,SACE;GACF,cAAc;GACf,CAAC;;CAGJ,MAAgB,mBACd,aACe;EACf,MAAM,WAAW,MAAM,iBAAiB,aAAa,KAAA,GAAW,EAC9D,eAAe,MAChB,CAAC;AAGF,QAAM,0BAA0B,SAAS;AAEzC,QAAM,mBAAmB,aAAa,UAAU,KAAK,QAAQ;;CAG/D,MAAgB,YAAY,aAA4C;EACtE,MAAM,WAAW,MAAM,iBAAiB,aAAa,KAAA,GAAW,EAC9D,eAAe,MAChB,CAAC;AAGF,QAAM,0BAA0B,SAAS;AAEzC,MAAI,CAAC,SAAS,mBAAmB;AAE/B,YAAS,oBAAoB;AAC7B,SAAM,aAAa,SAAS,QAAQ,EAClC,mBAAmB,MACpB,CAAC;;AAEJ,QAAM,YAAY,aAAa,UAAU,KAAK,SAAS,KAAK;;;;;;;CAQ9D,MAAgB,cAAc,aAA4C;AAIxE,QAAM,cAAc,aAAa,MAHV,iBAAiB,aAAa,KAAA,GAAW,EAC9D,eAAe,MAChB,CAAC,EACyC,KAAK,QAAQ;;;;;;;CAQ1D,MAAgB,eAAe,aAA4C;AAIzE,QAAM,eAAe,aAAa,MAHX,iBAAiB,aAAa,KAAA,GAAW,EAC9D,eAAe,MAChB,CAAC,EAC0C,KAAK,QAAQ;;CAG3D,MAAgB,gBAAgB,aAA4C;EAC1E,MAAM,WAAW,MAAM,iBAAiB,aAAa,KAAA,GAAW,EAC9D,eAAe,MAChB,CAAC;AAGF,QAAM,0BAA0B,SAAS;AAEzC,MAAI,CAAC,SAAS,mBAAmB;AAK/B,OAAI,SAAS,OAAO,cAAc,QAAQ,OACxC,QAAO,gBAAgB,qBAAqB;GAE9C,MAAM,UAAU,MAAM,YACpB,aACA,UACA,KAAK,SACL,MACD;AACD,OAAI,QACF,OAAM,gBACJ,aACA,UACA,QAAQ,iBACR,QAAQ,SACR,QAAQ,YACR,QAAQ,YACR,QAAQ,cACT;QAGH,OAAM,eAAe,aAAa,UAAU,KAAK,QAAQ;EAG3D,MAAM,UAAU,wBAAwB;AACxC,MAAI,QAAQ,OAAO,EACjB,OAAM,wBAAwB,UAAU,QAAQ;AAGlD,QAAM,0BAA0B,SAAS;AAEzC,QAAM,sBAAsB,SAAS;AACrC,mBAAiB;AACjB,2BAAyB;AACzB,iBAAe;;CAGjB,qBAAqC;AACnC,uBACE,KAAK,QACF,QAAQ,SAAS,CACjB,YACC,2EACD,CACJ,CAAC,OAAO,OAAO,gBAA+B;AAC7C,iBAAc,qBAAqB;GACnC,MAAM,WAAW,MAAM,iBAAiB,aAAa,KAAA,GAAW,EAC9D,eAAe,MAChB,CAAC;GAEF,MAAM,UAAU;IAAE,GAAG;IAAa,GAAG;IAAU;AAE/C,SAAM,KAAK,oBAAoB,QAAQ;AACvC,UAAO,WAAW,QAAQ;IAC1B;;CAGJ,oBAAoC;AAClC,OAAK,QACF,QAAQ,OAAO,CACf,YAAY,uDAAuD,CACnE,OACC,uBACA,sDACA,aAAa,CAAC,iBAAiB,CAAC,CACjC,CACA,OACC,yBACA,0DACD,CACA,OAAO,OAAO,YAA0B;AACvC,iBAAc,6CAA6C;AAC3D,OAAI,CAAC,QAAQ,QACX,SAAQ,UAAU,MAAM,aAEtB;IACA,SAAS;IACT,SAAS;KACP;MAAE,OAAO;MAAe,OAAO;MAAe;KAC9C;MAAE,OAAO;MAAc,OAAO;MAAc;KAC5C;MAAE,OAAO;MAAO,OAAO;MAAQ;KAChC;IACD,cAAc;IACf,CAAC;YAGA,QAAQ,YAAY,iBACpB,QAAQ,YAAY,gBACpB,QAAQ,YAAY,MAEpB,iBACE,4DACD;AAGL,SAAM,KAAK,mBAAmB,QAAQ;AACtC,UAAO,WACL,SAAS,QAAQ,QAAQ,8DAC1B;IACD;;CAGN,mBAAmC;AACjC,OAAK,QACF,QAAQ,OAAO,CACf,YACC,yEACD,CACA,OACC,oBACA,0MACD,CACA,OACC,uBACA,sDACA,aAAa,CAAC,iBAAiB,CAAC,CACjC,CACA,OAAO,OAAO,YAA0B;AACvC,SAAM,8BAA8B;GACpC,MAAM,WAAW,MAAM,iBAAiB,QAAQ;AAChD,iBAAc,0BAA0B;GAExC,MAAM,YAAY,MAAM,iBAAiB;AAmBzC,OAAI,OAjBoB,YAAY;IAClC,IAAI;AACJ,QAAI,UAAU,SAAS,WACrB,mBAAkB;AAEpB,QAAI,UAAU,SAAS,WACrB,mBAAkB;AAEpB,QAAI,gBACF,QAAO,MAAM,cAAc;KACzB,SAAS;KACT,cAAc;KACf,CAAC;AAEJ,WAAO;OACL,EAEU;AACZ,UAAM,aAAa,SAAS;AAC5B,WAAO,WACL,4IACD;UACI;IAEL,MAAM,uBACJ,UAAU,SAAS,UACf,wBAAwB,UAAU,GAClC;IACN,MAAM,UACJ,UAAU,SAAS,UACf,yBAAyB,UAAU,GACnC;IAGN,MAAM,yBACJ,UAAU,SAAS,SACf,gCACA;IAEN,MAAM,sBACJ,UAAU,SAAS,SACf,GAAG,QAAQ,sBAAsB,qBAAqB,2BAA2B,2BACjF,UAAU,SAAS,UACjB,GAAG,QAAQ,iBAAiB,qBAAqB,2BAA2B,2BAC5E,0BAA0B;IAGlC,MAAM,cAAc,MAAM,cAAc;KACtC,SAAS,uEAAuE,MAAM,IAAI,IAAI,oBAAoB,GAAG;KACrH,cAAc;KACf,CAAC;IAEF,IAAI,gBAAgB;AAGpB,QAAI,UAAU,SAAS;SACR,cACT,OACA,MAAM,cAAc;MAClB,SACE,UAAU,SAAS,SACf,6BAA6B,QAAQ,qIACrC,6BAA6B,QAAQ;MAC3C,cAAc;MACf,CAAC,EAEI;AACR,aAAO,KACL,GAAG,MAAM,OAAO,iBAAiB,CAAC,yBACnC;AACD,YAAM,wBAAwB,SAAS,WAAW,YAAY;AAC9D,aAAO,WACL;0IAED;AACD,sBAAgB;;;AAIpB,QAAI,cACF,QAAO,aAAa,+BAA+B;AAGrD,UAAM,KAAK,kBACT,eACA,aACA,UAAU,SAAS,OACpB;AAED,WAAO,WACL,uHACD;;IAEH;;CAGN,wBAAwC;AACtC,OAAK,QACF,QAAQ,YAAY,CACpB,YACC,2GACD,CACA,aAAa,KAAK,wBAAwB,CAAC;;CAGhD,MAAgB,uBACd,SACe;AACf,QAAM,8BAA8B;AACpC,gBAAc,yBAAyB;AAEvC,SAAO,KACL,oKACD;EAGD,MAAM,YAAY,MAAM,iBAAiB;AACzC,QAAM,KAAK,kBACT,OACA,OACA,UAAU,SAAS,QACnB,QACD;AAED,SAAO,WACL,qJACD;;CAGH,MAAgB,oBACd,UACe;AACf,MAAI,CAAC,SAAS,MACZ;AAIF,QAAM,OAAO,SAAS;;;CAIxB,sBACE,aACA,gBAAyB,OACL;AACpB,SAAO;GACL,uBAAuB,iBAAiB,MACrC,QACC,QAAA,YAA4B,mBAAmB,KAAK,YAAY,CACnE;GACD,eAAe,8BAA8B,YAAY;GACzD;GACD;;;CAIH,yBACE,aACS;EACT,MAAM,EAAE,uBAAuB,kBAC7B,KAAK,sBAAsB,YAAY;AACzC,SAAO,yBAAyB;;;CAIlC,mBAA6B,cAA2C;AACtE,SAAO,CAAC,aAAa;;;CAIvB,qCACE,QACA,cACS;AACT,MAAI,OAAQ,QAAO;AACnB,MAAI,CAAC,aAAa,cAAe,QAAO;AACxC,SAAO,aAAa,yBAAyB,aAAa;;;CAI5D,4BAAsC,EACpC,iBACA,cACA,mBACsD;EACtD,MAAM,WAAqB,EAAE;AAC7B,MAAI,gBACF,UAAS,KAAK,WAAW,MAAM,KAAK,sBAAsB,CAAC;;iEAEA;AAE7D,MAAI,aAAa,cACf,UAAS,KAAK,4CAA4C,gBAAgB;;0CAEtC;AAEtC,SAAO,SAAS,SAAS,IAAI,SAAS,KAAK,KAAK,GAAG,KAAA;;CAIrD,MAAgB,kBACd,eACA,cAAuB,OACvB,SAAkB,OAClB,SACe;EACf,MAAM,iBACJ,SAAS,WACR,CAAC,UAAU,GAAG,WAAW,qBAAqB,GAC3C,uBACA;EAEN,MAAM,EAAE,eAAe,YAAY,MAAM,kBADlB,WAAW,eACuC,CAAC;EAE1E,MAAM,cAAc,MAAM,sBAAsB;EAGhD,MAAM,eAAmC,cACrC,KAAK,sBAAsB,aAAa,cAAc,GACtD;GACE,uBAAuB;GACvB,eAAe;GACf;GACD;EACL,MAAM,YACJ,aAAa,iBACb,aAAa,yBACb,aAAa;EAGf,MAAM,WAAW,OAAO,YAAY;AAClC,OAAI,CAAC,UAAW,QAAO;AACvB,OAAI,YAAa,QAAO;AACxB,OAAI,CAAC,KAAK,mBAAmB,aAAa,CAAE,QAAO;AASnD,UAAO,MARqB,aAAa;IACvC,SAAS;IACT,SAAS,CACP;KAAE,OAAO;KAAS,OAAO;KAAgB,EACzC;KAAE,OAAO;KAAO,OAAO;KAAW,CACnC;IACD,cAAc;IACf,CAAC,KACuB;MACvB;EAEJ,MAAM,yBAAyB,SAC3B,gCACA;EAeJ,MAAM,wBAXJ,aAAa,CAAC,WACV,cACE,yBACA,MAAM,WAAW;GACf,SACE;GACF,cAAc;GACf,CAAC,GACJ,OAIa,MAAM,IAAI;AAE7B,MAAI,aAAa,CAAC,UAAU;GAC1B,MAAM,kBAAkB,KAAK,qCAC3B,QACA,aACD;AACD,OAAI,gBACF,OAAM,2BACJ,QAAQ,KAAK,EACb,sBACA,QACD;GAEH,MAAM,WAAW,KAAK,4BAA4B;IAChD;IACA;IACA,iBAAiB;IAClB,CAAC;AACF,OAAI,SAAU,QAAO,QAAQ,SAAS;;EAGxC,MAAM,UAAU,CAAC,YACb,iKACA,wGAAwG,MAAM,IAC5G,8CACD;EACL,MAAM,iBACJ,eAAe,YACX,EAAE,GACF,MAAM,kBAAkB;GACtB;GACA,SAAS;IACP;KAAE,OAAO;KAAQ,OAAO,sBAAsB;KAAM;IACpD;KAAE,OAAO;KAAM,OAAO,sBAAsB;KAAI;IAChD;KAAE,OAAO;KAAO,OAAO,sBAAsB;KAAK;IAClD;KAAE,OAAO;KAAM,OAAO,sBAAsB;KAAI;IAChD;KAAE,OAAO;KAAM,OAAO,sBAAsB;KAAI;IAChD;KAAE,OAAO;KAAQ,OAAO,sBAAsB;KAAM;IAErD;GACD,UAAU,CAAC;GACZ,CAAC;EAER,MAAM,QAAsB,EAAE;AAC9B,OAAK,MAAM,iBAAiB,gBAAgB;GAC1C,MAAM,QAAQ,sBAAsB;AAOpC,SAAM,iBAAiB,EACrB,SAAS,kBAAkB,MAPT,mBAAmB;IACrC;IACA,SAAS,GAAG,MAAM,KAAK,sBAAsB,eAAe,CAAC,+EAA+E,sBAAsB,eAAe;IACjL,cAAc,mBAAmB;IAClC,CAAC,CAGiC,EAClC;;AAIH,MAAI,aAAa,CAAC,SAChB,OAAM,KAAK,EACT,QAAQ,KAAK,KAAK,sBAAsB,gBAAgB,EACzD;AAIH,QAAM,qBAAqB,gBAAgB;GACzC;GACA;GACA,KAAK,SAAS;GACd,OAAO,OAAO,KAAK,MAAM,CAAC,SAAS,IAAI,QAAQ,KAAA;GAC/C,WAAW,SAAS,SAAS,KAAA;GAC7B,SAAS,aAAa;GACtB,cAAc,aAAa,iBAAiB,CAAC;GAC9C,CAAC;AAEF,SAAO,QACL,QAAQ,MAAM,KACZ,eACD,CAAC,sGACH;AAED,MAAI,iBAAiB,OACnB,OAAM,aAAa;GACjB,cAAc,QAAQ,KAAK;GAC3B;GACA;GACA;GACA,iBAAiB,WAAW,KAAA,IAAY;GACzC,CAAC;AAQJ,MAAI,EAJmB,cACnB,mBAAmB,MAAM,aAAa,MAAM,KAAK,GACjD,SAEmB,EAAE,aAAa,SAAS;GAC7C,MAAM,iBAAiB,MAAM,mBAAmB;GAChD,MAAM,UAAU,OAAO,eAAe;AACtC,WAAQ,MACN,0CAA0C,eAAe,KAAK,KAC/D;AACD,SAAM,eAAe,MAAM,gBAAgB,KAAK;AAChD,WAAQ,KAAK,MAAM,MAAM,gBAAgB,CAAC;;AAI5C,OAAK,CAAC,UAAU,CAAC,aAAa,aAAa,CAAC,mBAAmB;OACvC,cAClB,OACA,MAAM,cAAc;IAClB,SACE;IACF,cAAc;IACf,CAAC,EACa;IACjB,MAAM,WAAW,MAAM,iBAAiB,EAAE,CAAC;AAa3C,UAAM,eAAe,MADK,oBAAoB,UAX9B,cACZ,QACA,MAAM,aAAmD;KACvD,SAAS;KACT,SAAS;MACP;OAAE,OAAO;OAAe,OAAO;OAAe;MAC9C;OAAE,OAAO;OAAc,OAAO;OAAc;MAC5C;OAAE,OAAO;OAAO,OAAO;OAAQ;MAChC;KACD,cAAc;KACf,CAAC,CAC0D,EAC9B,SAAS,SAAS,SAAS,UAAU;;;;CAI7E,MAAgB,mBAAmB,SAAsC;EACvE,MAAM,WAAW,MAAM,iBAAiB,EAAE,QAAQ,QAAQ,QAAQ,CAAC;AAGnE,QAAM,eAAe,MADK,oBAAoB,UAD9B,QAAQ,WAAW,MAC6B,EAC9B,SAAS,UAAU"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type ApiClientConfig } from 'generaltranslation/api';
|
|
2
|
+
import type { SharedFlags } from '../../types/index.js';
|
|
3
|
+
export type ApiCommandOptions = SharedFlags & {
|
|
4
|
+
header?: string[];
|
|
5
|
+
include?: boolean;
|
|
6
|
+
input?: string;
|
|
7
|
+
method: string;
|
|
8
|
+
spec?: boolean;
|
|
9
|
+
};
|
|
10
|
+
type ApiCommandDependencies = {
|
|
11
|
+
exit?: (code: number) => never;
|
|
12
|
+
fetch?: ApiClientConfig['fetch'];
|
|
13
|
+
writeStderr?: (output: string) => void;
|
|
14
|
+
writeStdout?: (output: string | Uint8Array) => void;
|
|
15
|
+
};
|
|
16
|
+
export declare function handleApiCommand(endpoint: string | undefined, options: ApiCommandOptions, dependencies?: ApiCommandDependencies): Promise<void>;
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { exitSync } from "../../console/logging.js";
|
|
2
|
+
import { loadConfig } from "../../fs/config/loadConfig.js";
|
|
3
|
+
import { resolveProjectId } from "../../fs/utils.js";
|
|
4
|
+
import { resolveConfig } from "../../config/resolveConfig.js";
|
|
5
|
+
import fs from "node:fs";
|
|
6
|
+
import { createDiagnosticMessage, defaultBaseUrl, formatDiagnosticErrorDetails } from "generaltranslation/internal";
|
|
7
|
+
import { createApiClient } from "generaltranslation/api";
|
|
8
|
+
import openApiSpec from "generaltranslation/api/openapi.json" with { type: "json" };
|
|
9
|
+
//#region src/cli/commands/api.ts
|
|
10
|
+
const STANDARD_HTTP_METHODS = new Set([
|
|
11
|
+
"GET",
|
|
12
|
+
"HEAD",
|
|
13
|
+
"POST",
|
|
14
|
+
"PUT",
|
|
15
|
+
"PATCH",
|
|
16
|
+
"DELETE",
|
|
17
|
+
"OPTIONS"
|
|
18
|
+
]);
|
|
19
|
+
function fail(diagnostic, { exit = exitSync, writeStderr = (output) => process.stderr.write(output) }) {
|
|
20
|
+
writeStderr(`${diagnostic}\n`);
|
|
21
|
+
return exit(1);
|
|
22
|
+
}
|
|
23
|
+
function parseMethod(value, dependencies) {
|
|
24
|
+
const method = value.toUpperCase();
|
|
25
|
+
if (!STANDARD_HTTP_METHODS.has(method)) fail(createDiagnosticMessage({
|
|
26
|
+
source: "gt",
|
|
27
|
+
severity: "Error",
|
|
28
|
+
whatHappened: "The API request method is invalid",
|
|
29
|
+
details: value,
|
|
30
|
+
fix: `Use one of ${[...STANDARD_HTTP_METHODS].join(", ")}`
|
|
31
|
+
}), dependencies);
|
|
32
|
+
return method;
|
|
33
|
+
}
|
|
34
|
+
function parseHeaders(values, dependencies) {
|
|
35
|
+
const headers = new Headers();
|
|
36
|
+
for (const header of values) {
|
|
37
|
+
const separator = header.indexOf(":");
|
|
38
|
+
if (separator < 1) fail(createDiagnosticMessage({
|
|
39
|
+
source: "gt",
|
|
40
|
+
severity: "Error",
|
|
41
|
+
whatHappened: "The API request header is invalid",
|
|
42
|
+
details: header,
|
|
43
|
+
fix: "Pass headers as `--header \"Key: Value\"`"
|
|
44
|
+
}), dependencies);
|
|
45
|
+
headers.append(header.slice(0, separator).trim(), header.slice(separator + 1).trim());
|
|
46
|
+
}
|
|
47
|
+
return headers;
|
|
48
|
+
}
|
|
49
|
+
function readInput(input, dependencies) {
|
|
50
|
+
try {
|
|
51
|
+
return fs.readFileSync(input === "-" ? 0 : input, "utf8");
|
|
52
|
+
} catch (error) {
|
|
53
|
+
return fail(createDiagnosticMessage({
|
|
54
|
+
source: "gt",
|
|
55
|
+
severity: "Error",
|
|
56
|
+
whatHappened: "The API request body could not be read",
|
|
57
|
+
fix: input === "-" ? "Pipe a request body to standard input or remove `--input -`" : "Check the `--input` file path and permissions",
|
|
58
|
+
details: formatDiagnosticErrorDetails(error)
|
|
59
|
+
}), dependencies);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
function writeResponseMetadata(response, writeStdout) {
|
|
63
|
+
writeStdout(`HTTP ${response.status}${response.statusText ? ` ${response.statusText}` : ""}\n`);
|
|
64
|
+
response.headers.forEach((value, name) => {
|
|
65
|
+
writeStdout(`${name}: ${value}\n`);
|
|
66
|
+
});
|
|
67
|
+
writeStdout("\n");
|
|
68
|
+
}
|
|
69
|
+
function resolveApiProjectId(config, flagProjectId, dependencies) {
|
|
70
|
+
const configProjectId = typeof config.projectId === "string" ? config.projectId : void 0;
|
|
71
|
+
const environmentProjectId = resolveProjectId();
|
|
72
|
+
if (configProjectId && flagProjectId && configProjectId !== flagProjectId) fail(createDiagnosticMessage({
|
|
73
|
+
source: "gt",
|
|
74
|
+
severity: "Error",
|
|
75
|
+
whatHappened: "The project IDs do not match",
|
|
76
|
+
details: [`Configuration: ${configProjectId}`, `--project-id: ${flagProjectId}`],
|
|
77
|
+
fix: "Use the same project ID in all configurations"
|
|
78
|
+
}), dependencies);
|
|
79
|
+
if (configProjectId && environmentProjectId && configProjectId !== environmentProjectId) fail(createDiagnosticMessage({
|
|
80
|
+
source: "gt",
|
|
81
|
+
severity: "Error",
|
|
82
|
+
whatHappened: "The project IDs do not match",
|
|
83
|
+
details: [`Configuration: ${configProjectId}`, `Environment: ${environmentProjectId}`],
|
|
84
|
+
fix: "Use the same project ID in all configurations"
|
|
85
|
+
}), dependencies);
|
|
86
|
+
return flagProjectId ?? configProjectId ?? environmentProjectId;
|
|
87
|
+
}
|
|
88
|
+
async function handleApiCommand(endpoint, options, dependencies = {}) {
|
|
89
|
+
if (!dependencies.writeStdout) process.stdout.once("error", (error) => {
|
|
90
|
+
if (error.code === "EPIPE") process.exit(0);
|
|
91
|
+
throw error;
|
|
92
|
+
});
|
|
93
|
+
const writeStdout = dependencies.writeStdout ?? ((output) => process.stdout.write(output));
|
|
94
|
+
const writeStderr = dependencies.writeStderr ?? ((output) => process.stderr.write(output));
|
|
95
|
+
if (options.spec) {
|
|
96
|
+
writeStdout(`${JSON.stringify(openApiSpec, null, 2)}\n`);
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
if (!endpoint) fail(createDiagnosticMessage({
|
|
100
|
+
source: "gt",
|
|
101
|
+
severity: "Error",
|
|
102
|
+
whatHappened: "No API endpoint was provided",
|
|
103
|
+
fix: "Pass an endpoint or use `gt api --spec` to inspect the OpenAPI specification"
|
|
104
|
+
}), dependencies);
|
|
105
|
+
const method = parseMethod(options.method, dependencies);
|
|
106
|
+
const configPath = options.config?.endsWith(".json") ? options.config : options.config ? `${options.config}.json` : void 0;
|
|
107
|
+
const config = configPath ? loadConfig(configPath) : resolveConfig(process.cwd())?.config ?? {};
|
|
108
|
+
const client = createApiClient({
|
|
109
|
+
apiKey: options.apiKey ?? process.env.GT_API_KEY,
|
|
110
|
+
baseUrl: typeof config.baseUrl === "string" ? config.baseUrl : defaultBaseUrl,
|
|
111
|
+
fetch: dependencies.fetch,
|
|
112
|
+
projectId: resolveApiProjectId(config, options.projectId, dependencies),
|
|
113
|
+
retryPolicy: "none"
|
|
114
|
+
});
|
|
115
|
+
const normalizedEndpoint = endpoint.startsWith("/") ? endpoint : `/${endpoint}`;
|
|
116
|
+
const headers = parseHeaders(options.header ?? [], dependencies);
|
|
117
|
+
const body = options.input ? readInput(options.input, dependencies) : void 0;
|
|
118
|
+
let rawResponse;
|
|
119
|
+
client.interceptors.response.use((response) => {
|
|
120
|
+
rawResponse = response.clone();
|
|
121
|
+
return response;
|
|
122
|
+
});
|
|
123
|
+
const result = await client.request({
|
|
124
|
+
body,
|
|
125
|
+
bodySerializer: () => body,
|
|
126
|
+
headers,
|
|
127
|
+
method,
|
|
128
|
+
parseAs: "stream",
|
|
129
|
+
throwOnError: false,
|
|
130
|
+
url: normalizedEndpoint
|
|
131
|
+
}).catch((error) => fail(createDiagnosticMessage({
|
|
132
|
+
source: "gt",
|
|
133
|
+
severity: "Error",
|
|
134
|
+
whatHappened: "The API request failed before a response was received",
|
|
135
|
+
details: formatDiagnosticErrorDetails(error)
|
|
136
|
+
}), dependencies));
|
|
137
|
+
if (!rawResponse) fail(createDiagnosticMessage({
|
|
138
|
+
source: "gt",
|
|
139
|
+
severity: "Error",
|
|
140
|
+
whatHappened: "The API request did not return a response",
|
|
141
|
+
details: formatDiagnosticErrorDetails(result?.error)
|
|
142
|
+
}), dependencies);
|
|
143
|
+
if (options.include) writeResponseMetadata(rawResponse, writeStdout);
|
|
144
|
+
writeStdout(Buffer.from(await rawResponse.arrayBuffer()));
|
|
145
|
+
if (!rawResponse.ok) {
|
|
146
|
+
writeStderr(`${method} ${normalizedEndpoint} returned HTTP ${rawResponse.status}${rawResponse.statusText ? ` ${rawResponse.statusText}` : ""}\n`);
|
|
147
|
+
(dependencies.exit ?? exitSync)(1);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
//#endregion
|
|
151
|
+
export { handleApiCommand };
|
|
152
|
+
|
|
153
|
+
//# sourceMappingURL=api.js.map
|
|
@@ -0,0 +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 defaultBaseUrl,\n formatDiagnosticErrorDetails,\n} from 'generaltranslation/internal';\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 client = createApiClient({\n apiKey: options.apiKey ?? process.env.GT_API_KEY,\n baseUrl:\n typeof config.baseUrl === 'string' ? config.baseUrl : defaultBaseUrl,\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,16 +1,17 @@
|
|
|
1
1
|
import { logger } from "../../console/logger.js";
|
|
2
2
|
import { exitSync, logErrorAndExit } from "../../console/logging.js";
|
|
3
|
-
import { getRelative,
|
|
4
|
-
import { noDefaultLocaleError } from "../../console/index.js";
|
|
3
|
+
import { getRelative, readFile } from "../../fs/findFilepath.js";
|
|
4
|
+
import { fileEncodingSkipReason, noDefaultLocaleError } from "../../console/index.js";
|
|
5
|
+
import { readFileContent } from "../../fs/fileContent.js";
|
|
5
6
|
import { validateJsonSchema } from "../../formats/json/utils.js";
|
|
6
7
|
import { extractJson } from "../../formats/json/extractJson.js";
|
|
8
|
+
import { recordWarning } from "../../state/translateWarnings.js";
|
|
7
9
|
import { runUploadFilesWorkflow } from "../../workflows/upload.js";
|
|
8
10
|
import { createFileMapping } from "../../formats/files/fileMapping.js";
|
|
9
11
|
import { hasValidCredentials } from "./utils/validation.js";
|
|
10
12
|
import { runPublishWorkflow } from "../../workflows/publish.js";
|
|
11
13
|
import { aggregateFiles } from "../../formats/files/aggregateFiles.js";
|
|
12
|
-
import { existsSync
|
|
13
|
-
import { isBinaryFileFormat } from "generaltranslation/types";
|
|
14
|
+
import { existsSync } from "node:fs";
|
|
14
15
|
//#region src/cli/commands/upload.ts
|
|
15
16
|
/**
|
|
16
17
|
* Sends multiple files to the API for translation
|
|
@@ -61,7 +62,16 @@ async function upload(settings) {
|
|
|
61
62
|
const translatedFileName = fileMapping[locale]?.[file.fileName];
|
|
62
63
|
if (translatedFileName && existsSync(translatedFileName)) {
|
|
63
64
|
const translationFormat = file.transformFormat ?? file.fileFormat;
|
|
64
|
-
|
|
65
|
+
let translatedContent;
|
|
66
|
+
try {
|
|
67
|
+
translatedContent = readFileContent(translatedFileName, translationFormat);
|
|
68
|
+
} catch (error) {
|
|
69
|
+
const relativePath = getRelative(translatedFileName);
|
|
70
|
+
const reason = fileEncodingSkipReason(error);
|
|
71
|
+
logger.warn(`Skipping ${relativePath}: ${reason}`);
|
|
72
|
+
recordWarning("skipped_file", relativePath, reason);
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
65
75
|
translations.push({
|
|
66
76
|
content: translatedContent,
|
|
67
77
|
fileName: translatedFileName,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"upload.js","names":[],"sources":["../../../src/cli/commands/upload.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"upload.js","names":[],"sources":["../../../src/cli/commands/upload.ts"],"sourcesContent":["import {\n fileEncodingSkipReason,\n noDefaultLocaleError,\n} from '../../console/index.js';\nimport { exitSync, logErrorAndExit } from '../../console/logging.js';\nimport { logger } from '../../console/logger.js';\nimport { getRelative, readFile } from '../../fs/findFilepath.js';\nimport { readFileContent } from '../../fs/fileContent.js';\nimport { Settings } from '../../types/index.js';\nimport { UploadOptions } from '../base.js';\nimport { extractJson } from '../../formats/json/extractJson.js';\nimport { validateJsonSchema } from '../../formats/json/utils.js';\nimport { runUploadFilesWorkflow } from '../../workflows/upload.js';\nimport { existsSync } from 'node:fs';\nimport { createFileMapping } from '../../formats/files/fileMapping.js';\nimport type { FileToUpload } from 'generaltranslation/types';\nimport { hasValidCredentials } from './utils/validation.js';\nimport { runPublishWorkflow } from '../../workflows/publish.js';\nimport { aggregateFiles } from '../../formats/files/aggregateFiles.js';\nimport { recordWarning } from '../../state/translateWarnings.js';\n\n/**\n * Sends multiple files to the API for translation\n * @param settings - Translation options including API settings\n * @returns Promise that resolves when translation is complete\n */\nexport async function upload(\n settings: Settings & UploadOptions\n): Promise<void> {\n if (!settings.files) {\n return;\n }\n\n const additionalOptions = settings.options || {};\n const {\n resolvedPaths: filePaths,\n placeholderPaths,\n transformPaths,\n transformFormats,\n } = settings.files;\n\n // Reuse the same source aggregation path as translate/stage so source\n // parsing behavior stays consistent across commands.\n const { files: allFiles, publishMap } = await aggregateFiles(settings);\n const compositeJsonFiles = new Map<\n string,\n { filePath: string; content: string }\n >();\n\n if (filePaths.json) {\n const sourceFileNames = new Set(allFiles.map((file) => file.fileName));\n for (const filePath of filePaths.json) {\n const relativePath = getRelative(filePath);\n if (!sourceFileNames.has(relativePath)) continue;\n\n const jsonSchema = validateJsonSchema(additionalOptions, filePath);\n if (jsonSchema?.composite) {\n compositeJsonFiles.set(relativePath, {\n filePath,\n content: readFile(filePath),\n });\n }\n }\n }\n\n if (allFiles.length === 0) {\n logger.error(\n 'No files to upload were found. Check your configuration and try again.'\n );\n return;\n }\n\n if (!settings.defaultLocale) {\n return logErrorAndExit(noDefaultLocaleError);\n }\n if (!hasValidCredentials(settings)) return exitSync(1);\n\n const locales = settings.locales || [];\n // Create file mapping for all file types\n const fileMapping = createFileMapping(\n filePaths,\n placeholderPaths,\n transformPaths,\n transformFormats,\n locales,\n settings.defaultLocale\n );\n\n // construct object\n const uploadData = allFiles.map((file) => {\n const sourceFile: FileToUpload = { ...file };\n\n const translations: FileToUpload[] = [];\n const compositeInfo = compositeJsonFiles.get(file.fileName);\n\n for (const locale of locales) {\n if (compositeInfo) {\n // Composite JSON: extract translations from the same source file\n const extracted = extractJson(\n compositeInfo.content,\n compositeInfo.filePath,\n additionalOptions,\n locale,\n settings.defaultLocale\n );\n if (extracted) {\n translations.push({\n content: extracted,\n fileName: file.fileName,\n fileFormat: file.transformFormat ?? file.fileFormat,\n dataFormat: file.dataFormat,\n locale,\n fileId: file.fileId,\n versionId: file.versionId,\n });\n }\n } else {\n // Non-composite: look for separate translation files\n const translatedFileName = fileMapping[locale]?.[file.fileName];\n if (translatedFileName && existsSync(translatedFileName)) {\n const translationFormat = file.transformFormat ?? file.fileFormat;\n let translatedContent: string;\n try {\n translatedContent = readFileContent(\n translatedFileName,\n translationFormat\n );\n } catch (error) {\n // One undecodable locale should not block the others: skip it and\n // report it in the summary.\n const relativePath = getRelative(translatedFileName);\n const reason = fileEncodingSkipReason(error);\n logger.warn(`Skipping ${relativePath}: ${reason}`);\n recordWarning('skipped_file', relativePath, reason);\n continue;\n }\n translations.push({\n content: translatedContent,\n fileName: translatedFileName,\n fileFormat: translationFormat,\n dataFormat: file.dataFormat,\n locale,\n fileId: file.fileId,\n versionId: file.versionId,\n });\n }\n }\n }\n return {\n source: sourceFile,\n translations,\n };\n });\n\n try {\n // Send all files in a single API call\n const { branchData } = await runUploadFilesWorkflow({\n files: uploadData,\n options: settings,\n });\n\n // Publish files to CDN if publish config exists\n await runPublishWorkflow(\n allFiles,\n publishMap,\n branchData.currentBranch.id,\n settings\n );\n } catch (error) {\n logErrorAndExit(`Error uploading files: ${error}`);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AA0BA,eAAsB,OACpB,UACe;AACf,KAAI,CAAC,SAAS,MACZ;CAGF,MAAM,oBAAoB,SAAS,WAAW,EAAE;CAChD,MAAM,EACJ,eAAe,WACf,kBACA,gBACA,qBACE,SAAS;CAIb,MAAM,EAAE,OAAO,UAAU,eAAe,MAAM,eAAe,SAAS;CACtE,MAAM,qCAAqB,IAAI,KAG5B;AAEH,KAAI,UAAU,MAAM;EAClB,MAAM,kBAAkB,IAAI,IAAI,SAAS,KAAK,SAAS,KAAK,SAAS,CAAC;AACtE,OAAK,MAAM,YAAY,UAAU,MAAM;GACrC,MAAM,eAAe,YAAY,SAAS;AAC1C,OAAI,CAAC,gBAAgB,IAAI,aAAa,CAAE;AAGxC,OADmB,mBAAmB,mBAAmB,SAC3C,EAAE,UACd,oBAAmB,IAAI,cAAc;IACnC;IACA,SAAS,SAAS,SAAS;IAC5B,CAAC;;;AAKR,KAAI,SAAS,WAAW,GAAG;AACzB,SAAO,MACL,yEACD;AACD;;AAGF,KAAI,CAAC,SAAS,cACZ,QAAO,gBAAgB,qBAAqB;AAE9C,KAAI,CAAC,oBAAoB,SAAS,CAAE,QAAO,SAAS,EAAE;CAEtD,MAAM,UAAU,SAAS,WAAW,EAAE;CAEtC,MAAM,cAAc,kBAClB,WACA,kBACA,gBACA,kBACA,SACA,SAAS,cACV;CAGD,MAAM,aAAa,SAAS,KAAK,SAAS;EACxC,MAAM,aAA2B,EAAE,GAAG,MAAM;EAE5C,MAAM,eAA+B,EAAE;EACvC,MAAM,gBAAgB,mBAAmB,IAAI,KAAK,SAAS;AAE3D,OAAK,MAAM,UAAU,QACnB,KAAI,eAAe;GAEjB,MAAM,YAAY,YAChB,cAAc,SACd,cAAc,UACd,mBACA,QACA,SAAS,cACV;AACD,OAAI,UACF,cAAa,KAAK;IAChB,SAAS;IACT,UAAU,KAAK;IACf,YAAY,KAAK,mBAAmB,KAAK;IACzC,YAAY,KAAK;IACjB;IACA,QAAQ,KAAK;IACb,WAAW,KAAK;IACjB,CAAC;SAEC;GAEL,MAAM,qBAAqB,YAAY,UAAU,KAAK;AACtD,OAAI,sBAAsB,WAAW,mBAAmB,EAAE;IACxD,MAAM,oBAAoB,KAAK,mBAAmB,KAAK;IACvD,IAAI;AACJ,QAAI;AACF,yBAAoB,gBAClB,oBACA,kBACD;aACM,OAAO;KAGd,MAAM,eAAe,YAAY,mBAAmB;KACpD,MAAM,SAAS,uBAAuB,MAAM;AAC5C,YAAO,KAAK,YAAY,aAAa,IAAI,SAAS;AAClD,mBAAc,gBAAgB,cAAc,OAAO;AACnD;;AAEF,iBAAa,KAAK;KAChB,SAAS;KACT,UAAU;KACV,YAAY;KACZ,YAAY,KAAK;KACjB;KACA,QAAQ,KAAK;KACb,WAAW,KAAK;KACjB,CAAC;;;AAIR,SAAO;GACL,QAAQ;GACR;GACD;GACD;AAEF,KAAI;EAEF,MAAM,EAAE,eAAe,MAAM,uBAAuB;GAClD,OAAO;GACP,SAAS;GACV,CAAC;AAGF,QAAM,mBACJ,UACA,YACA,WAAW,cAAc,IACzB,SACD;UACM,OAAO;AACd,kBAAgB,0BAA0B,QAAQ"}
|
|
@@ -5,6 +5,10 @@ import { Settings } from '../../../types/index.js';
|
|
|
5
5
|
* @returns True if has locales and default locale
|
|
6
6
|
*/
|
|
7
7
|
export declare function hasValidLocales(settings: Settings): boolean;
|
|
8
|
+
/**
|
|
9
|
+
* Validate an API key without requiring an existing project.
|
|
10
|
+
*/
|
|
11
|
+
export declare function hasValidApiKey(settings: Settings): boolean;
|
|
8
12
|
/**
|
|
9
13
|
* Validate credentials
|
|
10
14
|
* @param settings - The settings to validate
|
|
@@ -18,11 +18,9 @@ function hasValidLocales(settings) {
|
|
|
18
18
|
return true;
|
|
19
19
|
}
|
|
20
20
|
/**
|
|
21
|
-
* Validate
|
|
22
|
-
* @param settings - The settings to validate
|
|
23
|
-
* @returns True if has API key, project ID, and does not have a development API key
|
|
21
|
+
* Validate an API key without requiring an existing project.
|
|
24
22
|
*/
|
|
25
|
-
function
|
|
23
|
+
function hasValidApiKey(settings) {
|
|
26
24
|
if (!settings.apiKey) {
|
|
27
25
|
logger.error(noApiKeyError);
|
|
28
26
|
return false;
|
|
@@ -31,6 +29,15 @@ function hasValidCredentials(settings) {
|
|
|
31
29
|
logger.error(devApiKeyError);
|
|
32
30
|
return false;
|
|
33
31
|
}
|
|
32
|
+
return true;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Validate credentials
|
|
36
|
+
* @param settings - The settings to validate
|
|
37
|
+
* @returns True if has API key, project ID, and does not have a development API key
|
|
38
|
+
*/
|
|
39
|
+
function hasValidCredentials(settings) {
|
|
40
|
+
if (!hasValidApiKey(settings)) return false;
|
|
34
41
|
if (!settings.projectId) {
|
|
35
42
|
logger.error(noProjectIdError);
|
|
36
43
|
return false;
|
|
@@ -38,6 +45,6 @@ function hasValidCredentials(settings) {
|
|
|
38
45
|
return true;
|
|
39
46
|
}
|
|
40
47
|
//#endregion
|
|
41
|
-
export { hasValidCredentials, hasValidLocales };
|
|
48
|
+
export { hasValidApiKey, hasValidCredentials, hasValidLocales };
|
|
42
49
|
|
|
43
50
|
//# sourceMappingURL=validation.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation.js","names":[],"sources":["../../../../src/cli/commands/utils/validation.ts"],"sourcesContent":["import {\n noDefaultLocaleError,\n noLocalesError,\n noApiKeyError,\n devApiKeyError,\n noProjectIdError,\n} from '../../../console/index.js';\nimport { logger } from '../../../console/logger.js';\nimport { Settings } from '../../../types/index.js';\n\n/**\n * Validate locales\n * @param settings - The settings to validate\n * @returns True if has locales and default locale\n */\nexport function hasValidLocales(settings: Settings): boolean {\n if (!settings.locales) {\n logger.error(noLocalesError);\n return false;\n }\n if (!settings.defaultLocale) {\n logger.error(noDefaultLocaleError);\n return false;\n }\n return true;\n}\n\n/**\n * Validate
|
|
1
|
+
{"version":3,"file":"validation.js","names":[],"sources":["../../../../src/cli/commands/utils/validation.ts"],"sourcesContent":["import {\n noDefaultLocaleError,\n noLocalesError,\n noApiKeyError,\n devApiKeyError,\n noProjectIdError,\n} from '../../../console/index.js';\nimport { logger } from '../../../console/logger.js';\nimport { Settings } from '../../../types/index.js';\n\n/**\n * Validate locales\n * @param settings - The settings to validate\n * @returns True if has locales and default locale\n */\nexport function hasValidLocales(settings: Settings): boolean {\n if (!settings.locales) {\n logger.error(noLocalesError);\n return false;\n }\n if (!settings.defaultLocale) {\n logger.error(noDefaultLocaleError);\n return false;\n }\n return true;\n}\n\n/**\n * Validate an API key without requiring an existing project.\n */\nexport function hasValidApiKey(settings: Settings): boolean {\n if (!settings.apiKey) {\n logger.error(noApiKeyError);\n return false;\n }\n if (settings.apiKey.startsWith('gtx-dev-')) {\n logger.error(devApiKeyError);\n return false;\n }\n return true;\n}\n\n/**\n * Validate credentials\n * @param settings - The settings to validate\n * @returns True if has API key, project ID, and does not have a development API key\n */\nexport function hasValidCredentials(settings: Settings): boolean {\n if (!hasValidApiKey(settings)) return false;\n if (!settings.projectId) {\n logger.error(noProjectIdError);\n return false;\n }\n return true;\n}\n"],"mappings":";;;;;;;;AAeA,SAAgB,gBAAgB,UAA6B;AAC3D,KAAI,CAAC,SAAS,SAAS;AACrB,SAAO,MAAM,eAAe;AAC5B,SAAO;;AAET,KAAI,CAAC,SAAS,eAAe;AAC3B,SAAO,MAAM,qBAAqB;AAClC,SAAO;;AAET,QAAO;;;;;AAMT,SAAgB,eAAe,UAA6B;AAC1D,KAAI,CAAC,SAAS,QAAQ;AACpB,SAAO,MAAM,cAAc;AAC3B,SAAO;;AAET,KAAI,SAAS,OAAO,WAAW,WAAW,EAAE;AAC1C,SAAO,MAAM,eAAe;AAC5B,SAAO;;AAET,QAAO;;;;;;;AAQT,SAAgB,oBAAoB,UAA6B;AAC/D,KAAI,CAAC,eAAe,SAAS,CAAE,QAAO;AACtC,KAAI,CAAC,SAAS,WAAW;AACvB,SAAO,MAAM,iBAAiB;AAC9B,SAAO;;AAET,QAAO"}
|
|
@@ -9,6 +9,7 @@ import { resolveFiles } from "../fs/config/parseFilesConfig.js";
|
|
|
9
9
|
import { validateSettings } from "./validateSettings.js";
|
|
10
10
|
import { resolveProjectId } from "../fs/utils.js";
|
|
11
11
|
import { resolveConfig } from "./resolveConfig.js";
|
|
12
|
+
import { configureApiClient } from "../utils/api.js";
|
|
12
13
|
import { generatePreset } from "./optionPresets.js";
|
|
13
14
|
import { determineLibrary } from "../fs/determineFramework/index.js";
|
|
14
15
|
import chalk from "chalk";
|
|
@@ -161,6 +162,12 @@ async function generateSettings(flags, cwd = process.cwd(), options) {
|
|
|
161
162
|
}
|
|
162
163
|
mergedOptions.configDirectory = path.join(cwd, ".gt");
|
|
163
164
|
validateSettings(mergedOptions);
|
|
165
|
+
configureApiClient({
|
|
166
|
+
projectId: mergedOptions.projectId,
|
|
167
|
+
apiKey: mergedOptions.apiKey,
|
|
168
|
+
baseUrl: mergedOptions.baseUrl,
|
|
169
|
+
customMapping: mergedOptions.customMapping
|
|
170
|
+
});
|
|
164
171
|
gt.setConfig({
|
|
165
172
|
projectId: mergedOptions.projectId,
|
|
166
173
|
apiKey: mergedOptions.apiKey,
|