gt 2.14.50 → 2.14.51

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # gtx-cli
2
2
 
3
+ ## 2.14.51
4
+
5
+ ### Patch Changes
6
+
7
+ - [#1605](https://github.com/generaltranslation/gt/pull/1605) [`69172dc`](https://github.com/generaltranslation/gt/commit/69172dc72e3fe22b6072b4c60e26c3de2cd68494) Thanks [@fernando-aviles](https://github.com/fernando-aviles)! - Aggregate files on `upload` command. Ensures consistency with `stage` and `translate`
8
+
3
9
  ## 2.14.50
4
10
 
5
11
  ### Patch Changes
@@ -5,8 +5,8 @@ import { SUPPORTED_FILE_EXTENSIONS } from "../formats/files/supportedFiles.js";
5
5
  import { hasNonIdentityFileFormatTransformForType } from "../formats/files/transformFormat.js";
6
6
  import { validateJsonSchema } from "../formats/json/utils.js";
7
7
  import { extractJson } from "../formats/json/extractJson.js";
8
- import { resolveMintlifyRefs, shouldResolveRefs } from "../utils/resolveMintlifyRefs.js";
9
8
  import { recordWarning } from "../state/translateWarnings.js";
9
+ import { resolveMintlifyRefs, shouldResolveRefs } from "../utils/resolveMintlifyRefs.js";
10
10
  import { validateYamlSchema } from "../formats/yaml/utils.js";
11
11
  import { findOrCreateEntry, readLockfile, writeLockfile } from "../fs/config/downloadedVersions.js";
12
12
  import { extractYaml } from "../formats/yaml/extractYaml.js";
@@ -4,8 +4,8 @@ import { logErrorAndExit } from "../console/logging.js";
4
4
  import { branchResolutionError } from "../console/index.js";
5
5
  import { BranchStep } from "../workflows/steps/BranchStep.js";
6
6
  import { runPublishWorkflow } from "../workflows/publish.js";
7
- import { collectAndSendUserEditDiffs } from "./collectUserEditDiffs.js";
8
7
  import { aggregateFiles } from "../formats/files/aggregateFiles.js";
8
+ import { collectAndSendUserEditDiffs } from "./collectUserEditDiffs.js";
9
9
  import chalk from "chalk";
10
10
  //#region src/api/saveLocalEdits.ts
11
11
  /**
package/dist/cli/base.js CHANGED
@@ -250,14 +250,8 @@ var BaseCLI = class {
250
250
  });
251
251
  }
252
252
  async handleUploadCommand(settings) {
253
- let dataFormat;
254
- if (this.library === "next-intl") dataFormat = "ICU";
255
- else if (this.library === "i18next") if (this.additionalModules.includes("i18next-icu")) dataFormat = "ICU";
256
- else dataFormat = "I18NEXT";
257
- else dataFormat = "JSX";
258
253
  if (!settings.files) return;
259
- const { resolvedPaths: sourceFiles, placeholderPaths, transformPaths } = settings.files;
260
- await upload(sourceFiles, placeholderPaths, transformPaths, dataFormat, settings);
254
+ await upload(settings);
261
255
  }
262
256
  async handleInitCommand(ranReactSetup, useDefaults = false, isVite = false) {
263
257
  const { defaultLocale, locales } = await getDesiredLocales();
@@ -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 promptConfirm,\n promptMultiSelect,\n promptSelect,\n promptGlobPatterns,\n} from '../console/logging.js';\nimport { logger } from '../console/logger.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 { DataFormat } from '../types/data.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 { 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 } from '../types/libraries.js';\nimport { handleEnqueue } from './commands/enqueue.js';\nimport { splitMintlifyLanguageRefs } from '../utils/splitMintlifyLanguageRefs.js';\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 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\n this.setupInitCommand();\n this.setupConfigureCommand();\n this.setupUploadCommand();\n this.setupLoginCommand();\n this.setupSendDiffsCommand();\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 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 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 );\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 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.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: `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(async () => {\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(false, false, framework.name === 'vite');\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\n protected async handleUploadCommand(\n settings: Settings & UploadOptions\n ): Promise<void> {\n // dataFormat for JSONs\n let dataFormat: DataFormat;\n if (this.library === 'next-intl') {\n dataFormat = 'ICU';\n } else if (this.library === 'i18next') {\n if (this.additionalModules.includes('i18next-icu')) {\n dataFormat = 'ICU';\n } else {\n dataFormat = 'I18NEXT';\n }\n } else {\n dataFormat = 'JSX';\n }\n\n if (!settings.files) {\n return;\n }\n const {\n resolvedPaths: sourceFiles,\n placeholderPaths,\n transformPaths,\n } = settings.files;\n\n // Process all file types at once with a single call\n await upload(\n sourceFiles,\n placeholderPaths,\n transformPaths,\n dataFormat,\n settings\n );\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 ): Promise<void> {\n const { defaultLocale, locales } = await getDesiredLocales(); // Locales should still be asked for even if using defaults\n\n const packageJson = await searchForPackageJson();\n\n // Ask if using another i18n library\n const gtInstalled =\n !!packageJson &&\n INLINE_LIBRARIES.some((lib) => isPackageInstalled(lib, packageJson));\n const isUsingGT = ranReactSetup || gtInstalled;\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 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 // Create loadTranslations.js file for local translations\n await createLoadTranslationsFile(\n process.cwd(),\n finalTranslationsDir,\n locales\n );\n logger.message(\n `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 }\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 let configFilepath = 'gt.config.json';\n if (fs.existsSync('src/gt.config.json')) {\n configFilepath = 'src/gt.config.json';\n }\n\n // Create gt.config.json\n await createOrUpdateConfig(configFilepath, {\n defaultLocale,\n locales,\n files: Object.keys(files).length > 0 ? files : undefined,\n publish: isUsingGT && 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 // 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) {\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 (!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, 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":"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"}
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 promptConfirm,\n promptMultiSelect,\n promptSelect,\n promptGlobPatterns,\n} from '../console/logging.js';\nimport { logger } from '../console/logger.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 { 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 } from '../types/libraries.js';\nimport { handleEnqueue } from './commands/enqueue.js';\nimport { splitMintlifyLanguageRefs } from '../utils/splitMintlifyLanguageRefs.js';\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 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\n this.setupInitCommand();\n this.setupConfigureCommand();\n this.setupUploadCommand();\n this.setupLoginCommand();\n this.setupSendDiffsCommand();\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 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 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 );\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 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.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: `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(async () => {\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(false, false, framework.name === 'vite');\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\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 // Wizard for configuring gt.config.json\n protected async handleInitCommand(\n ranReactSetup: boolean,\n useDefaults: boolean = false,\n isVite: boolean = false\n ): Promise<void> {\n const { defaultLocale, locales } = await getDesiredLocales(); // Locales should still be asked for even if using defaults\n\n const packageJson = await searchForPackageJson();\n\n // Ask if using another i18n library\n const gtInstalled =\n !!packageJson &&\n INLINE_LIBRARIES.some((lib) => isPackageInstalled(lib, packageJson));\n const isUsingGT = ranReactSetup || gtInstalled;\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 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 // Create loadTranslations.js file for local translations\n await createLoadTranslationsFile(\n process.cwd(),\n finalTranslationsDir,\n locales\n );\n logger.message(\n `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 }\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 let configFilepath = 'gt.config.json';\n if (fs.existsSync('src/gt.config.json')) {\n configFilepath = 'src/gt.config.json';\n }\n\n // Create gt.config.json\n await createOrUpdateConfig(configFilepath, {\n defaultLocale,\n locales,\n files: Object.keys(files).length > 0 ? files : undefined,\n publish: isUsingGT && 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 // 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) {\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 (!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, 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":"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"}
@@ -13,6 +13,7 @@ async function handleSetupProject(options, settings, library) {
13
13
  logCollectedFiles(allFiles, reactComponents);
14
14
  return null;
15
15
  }
16
+ if (allFiles.length === 0) logger.error("No files to upload were found. Check your configuration and try again.");
16
17
  let fileVersionData;
17
18
  let branchData;
18
19
  if (allFiles.length > 0) {
@@ -1 +1 @@
1
- {"version":3,"file":"setupProject.js","names":[],"sources":["../../../src/cli/commands/setupProject.ts"],"sourcesContent":["import { logger } from '../../console/logger.js';\nimport { exitSync, logCollectedFiles } from '../../console/logging.js';\nimport {\n Settings,\n SupportedLibraries,\n TranslateFlags,\n} from '../../types/index.js';\nimport { FileTranslationData } from '../../workflows/download.js';\nimport { BranchData } from '../../types/branch.js';\nimport { collectFiles } from '../../formats/files/collectFiles.js';\nimport { runSetupProjectWorkflow } from '../../workflows/setupProject.js';\nimport { hasValidCredentials, hasValidLocales } from './utils/validation.js';\n\nexport async function handleSetupProject(\n options: TranslateFlags,\n settings: Settings,\n library: SupportedLibraries\n): Promise<{\n fileVersionData: FileTranslationData | undefined;\n branchData: BranchData | undefined;\n} | null> {\n if (!hasValidLocales(settings)) return exitSync(1);\n // Validate credentials if not in dry run\n if (!options.dryRun && !hasValidCredentials(settings)) return exitSync(1);\n\n const { files: allFiles, reactComponents } = await collectFiles(\n options,\n settings,\n library\n );\n\n // Dry run\n if (options.dryRun) {\n logger.success(`Dry run: No files were uploaded to General Translation.`);\n logCollectedFiles(allFiles, reactComponents);\n return null;\n }\n\n // Upload files and run setup step\n let fileVersionData: FileTranslationData | undefined;\n let branchData: BranchData | undefined;\n if (allFiles.length > 0) {\n const { branchData: branchDataResult } = await runSetupProjectWorkflow(\n allFiles,\n options,\n settings\n );\n branchData = branchDataResult;\n\n fileVersionData = Object.fromEntries(\n allFiles.map((file) => [\n file.fileId,\n {\n fileName: file.fileName,\n versionId: file.versionId,\n },\n ])\n );\n }\n return {\n fileVersionData,\n branchData,\n };\n}\n"],"mappings":";;;;;;AAaA,eAAsB,mBACpB,SACA,UACA,SAIQ;AACR,KAAI,CAAC,gBAAgB,SAAS,CAAE,QAAO,SAAS,EAAE;AAElD,KAAI,CAAC,QAAQ,UAAU,CAAC,oBAAoB,SAAS,CAAE,QAAO,SAAS,EAAE;CAEzE,MAAM,EAAE,OAAO,UAAU,oBAAoB,MAAM,aACjD,SACA,UACA,QACD;AAGD,KAAI,QAAQ,QAAQ;AAClB,SAAO,QAAQ,0DAA0D;AACzE,oBAAkB,UAAU,gBAAgB;AAC5C,SAAO;;CAIT,IAAI;CACJ,IAAI;AACJ,KAAI,SAAS,SAAS,GAAG;EACvB,MAAM,EAAE,YAAY,qBAAqB,MAAM,wBAC7C,UACA,SACA,SACD;AACD,eAAa;AAEb,oBAAkB,OAAO,YACvB,SAAS,KAAK,SAAS,CACrB,KAAK,QACL;GACE,UAAU,KAAK;GACf,WAAW,KAAK;GACjB,CACF,CAAC,CACH;;AAEH,QAAO;EACL;EACA;EACD"}
1
+ {"version":3,"file":"setupProject.js","names":[],"sources":["../../../src/cli/commands/setupProject.ts"],"sourcesContent":["import { logger } from '../../console/logger.js';\nimport { exitSync, logCollectedFiles } from '../../console/logging.js';\nimport {\n Settings,\n SupportedLibraries,\n TranslateFlags,\n} from '../../types/index.js';\nimport { FileTranslationData } from '../../workflows/download.js';\nimport { BranchData } from '../../types/branch.js';\nimport { collectFiles } from '../../formats/files/collectFiles.js';\nimport { runSetupProjectWorkflow } from '../../workflows/setupProject.js';\nimport { hasValidCredentials, hasValidLocales } from './utils/validation.js';\n\nexport async function handleSetupProject(\n options: TranslateFlags,\n settings: Settings,\n library: SupportedLibraries\n): Promise<{\n fileVersionData: FileTranslationData | undefined;\n branchData: BranchData | undefined;\n} | null> {\n if (!hasValidLocales(settings)) return exitSync(1);\n // Validate credentials if not in dry run\n if (!options.dryRun && !hasValidCredentials(settings)) return exitSync(1);\n\n const { files: allFiles, reactComponents } = await collectFiles(\n options,\n settings,\n library\n );\n\n // Dry run\n if (options.dryRun) {\n logger.success(`Dry run: No files were uploaded to General Translation.`);\n logCollectedFiles(allFiles, reactComponents);\n return null;\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 }\n\n // Upload files and run setup step\n let fileVersionData: FileTranslationData | undefined;\n let branchData: BranchData | undefined;\n if (allFiles.length > 0) {\n const { branchData: branchDataResult } = await runSetupProjectWorkflow(\n allFiles,\n options,\n settings\n );\n branchData = branchDataResult;\n\n fileVersionData = Object.fromEntries(\n allFiles.map((file) => [\n file.fileId,\n {\n fileName: file.fileName,\n versionId: file.versionId,\n },\n ])\n );\n }\n return {\n fileVersionData,\n branchData,\n };\n}\n"],"mappings":";;;;;;AAaA,eAAsB,mBACpB,SACA,UACA,SAIQ;AACR,KAAI,CAAC,gBAAgB,SAAS,CAAE,QAAO,SAAS,EAAE;AAElD,KAAI,CAAC,QAAQ,UAAU,CAAC,oBAAoB,SAAS,CAAE,QAAO,SAAS,EAAE;CAEzE,MAAM,EAAE,OAAO,UAAU,oBAAoB,MAAM,aACjD,SACA,UACA,QACD;AAGD,KAAI,QAAQ,QAAQ;AAClB,SAAO,QAAQ,0DAA0D;AACzE,oBAAkB,UAAU,gBAAgB;AAC5C,SAAO;;AAGT,KAAI,SAAS,WAAW,EACtB,QAAO,MACL,yEACD;CAIH,IAAI;CACJ,IAAI;AACJ,KAAI,SAAS,SAAS,GAAG;EACvB,MAAM,EAAE,YAAY,qBAAqB,MAAM,wBAC7C,UACA,SACA,SACD;AACD,eAAa;AAEb,oBAAkB,OAAO,YACvB,SAAS,KAAK,SAAS,CACrB,KAAK,QACL;GACE,UAAU,KAAK;GACf,WAAW,KAAK;GACjB,CACF,CAAC,CACH;;AAEH,QAAO;EACL;EACA;EACD"}
@@ -17,6 +17,7 @@ async function handleStage(options, settings, library, stage) {
17
17
  logCollectedFiles(allFiles, reactComponents);
18
18
  return null;
19
19
  }
20
+ if (allFiles.length === 0 && !settings.publish) logger.error("No files to translate were found. Check your configuration and try again.");
20
21
  let fileVersionData;
21
22
  let jobData;
22
23
  let branchData;
@@ -1 +1 @@
1
- {"version":3,"file":"stage.js","names":[],"sources":["../../../src/cli/commands/stage.ts"],"sourcesContent":["import { logger } from '../../console/logger.js';\nimport { exitSync, logCollectedFiles } from '../../console/logging.js';\nimport {\n Settings,\n SupportedLibraries,\n TranslateFlags,\n} from '../../types/index.js';\nimport { runStageFilesWorkflow } from '../../workflows/stage.js';\nimport { writeStagedEntries } from '../../fs/config/downloadedVersions.js';\nimport type { EnqueueFilesResult } from 'generaltranslation/types';\nimport updateConfig from '../../fs/config/updateConfig.js';\nimport { FileTranslationData } from '../../workflows/download.js';\nimport { BranchData } from '../../types/branch.js';\nimport { TEMPLATE_FILE_ID } from '../../utils/constants.js';\nimport { collectFiles } from '../../formats/files/collectFiles.js';\nimport { convertToFileTranslationData } from '../../formats/files/convertToFileTranslationData.js';\nimport { hasValidCredentials, hasValidLocales } from './utils/validation.js';\n\nexport async function handleStage(\n options: TranslateFlags,\n settings: Settings,\n library: SupportedLibraries,\n stage: boolean\n): Promise<{\n fileVersionData: FileTranslationData | undefined;\n jobData: EnqueueFilesResult | undefined;\n branchData: BranchData | undefined;\n publishMap: Map<string, boolean>;\n} | null> {\n if (!hasValidLocales(settings)) return exitSync(1);\n // Validate credentials if not in dry run\n if (!options.dryRun && !hasValidCredentials(settings)) return exitSync(1);\n\n const {\n files: allFiles,\n reactComponents,\n publishMap,\n } = await collectFiles(options, settings, library);\n\n // Dry run\n if (options.dryRun) {\n logger.success(`Dry run: No files were sent to General Translation.`);\n logCollectedFiles(allFiles, reactComponents);\n return null;\n }\n\n // Send translations to General Translation\n let fileVersionData: FileTranslationData | undefined;\n let jobData: EnqueueFilesResult | undefined;\n let branchData: BranchData | undefined;\n if (allFiles.length > 0) {\n const { branchData: branchDataResult, enqueueResult } =\n await runStageFilesWorkflow({ files: allFiles, options, settings });\n jobData = enqueueResult;\n branchData = branchDataResult;\n\n fileVersionData = convertToFileTranslationData(allFiles);\n\n // Write staged entries to the lockfile\n if (stage) {\n const stagedFiles = Object.entries(fileVersionData).map(\n ([fileId, data]) => ({\n fileId,\n versionId: data.versionId,\n fileName: data.fileName,\n })\n );\n writeStagedEntries(settings, stagedFiles, branchData.currentBranch.id);\n }\n const templateData = allFiles.find(\n (file) => file.fileId === TEMPLATE_FILE_ID\n );\n if (templateData?.versionId) {\n await updateConfig(settings.config, {\n _versionId: templateData.versionId,\n _branchId: branchData.currentBranch.id,\n });\n }\n }\n\n // Always delete branch id from config if branching is disabled\n // Avoids incorrect CDN queries at runtime\n if (!settings.branchOptions.enabled) {\n await updateConfig(settings.config, {\n _branchId: null,\n });\n }\n\n return {\n fileVersionData,\n jobData,\n branchData,\n publishMap,\n };\n}\n"],"mappings":";;;;;;;;;;AAkBA,eAAsB,YACpB,SACA,UACA,SACA,OAMQ;AACR,KAAI,CAAC,gBAAgB,SAAS,CAAE,QAAO,SAAS,EAAE;AAElD,KAAI,CAAC,QAAQ,UAAU,CAAC,oBAAoB,SAAS,CAAE,QAAO,SAAS,EAAE;CAEzE,MAAM,EACJ,OAAO,UACP,iBACA,eACE,MAAM,aAAa,SAAS,UAAU,QAAQ;AAGlD,KAAI,QAAQ,QAAQ;AAClB,SAAO,QAAQ,sDAAsD;AACrE,oBAAkB,UAAU,gBAAgB;AAC5C,SAAO;;CAIT,IAAI;CACJ,IAAI;CACJ,IAAI;AACJ,KAAI,SAAS,SAAS,GAAG;EACvB,MAAM,EAAE,YAAY,kBAAkB,kBACpC,MAAM,sBAAsB;GAAE,OAAO;GAAU;GAAS;GAAU,CAAC;AACrE,YAAU;AACV,eAAa;AAEb,oBAAkB,6BAA6B,SAAS;AAGxD,MAAI,MAQF,oBAAmB,UAPC,OAAO,QAAQ,gBAAgB,CAAC,KACjD,CAAC,QAAQ,WAAW;GACnB;GACA,WAAW,KAAK;GAChB,UAAU,KAAK;GAChB,EAEqC,EAAE,WAAW,cAAc,GAAG;EAExE,MAAM,eAAe,SAAS,MAC3B,SAAS,KAAK,WAAW,iBAC3B;AACD,MAAI,cAAc,UAChB,OAAM,aAAa,SAAS,QAAQ;GAClC,YAAY,aAAa;GACzB,WAAW,WAAW,cAAc;GACrC,CAAC;;AAMN,KAAI,CAAC,SAAS,cAAc,QAC1B,OAAM,aAAa,SAAS,QAAQ,EAClC,WAAW,MACZ,CAAC;AAGJ,QAAO;EACL;EACA;EACA;EACA;EACD"}
1
+ {"version":3,"file":"stage.js","names":[],"sources":["../../../src/cli/commands/stage.ts"],"sourcesContent":["import { logger } from '../../console/logger.js';\nimport { exitSync, logCollectedFiles } from '../../console/logging.js';\nimport {\n Settings,\n SupportedLibraries,\n TranslateFlags,\n} from '../../types/index.js';\nimport { runStageFilesWorkflow } from '../../workflows/stage.js';\nimport { writeStagedEntries } from '../../fs/config/downloadedVersions.js';\nimport type { EnqueueFilesResult } from 'generaltranslation/types';\nimport updateConfig from '../../fs/config/updateConfig.js';\nimport { FileTranslationData } from '../../workflows/download.js';\nimport { BranchData } from '../../types/branch.js';\nimport { TEMPLATE_FILE_ID } from '../../utils/constants.js';\nimport { collectFiles } from '../../formats/files/collectFiles.js';\nimport { convertToFileTranslationData } from '../../formats/files/convertToFileTranslationData.js';\nimport { hasValidCredentials, hasValidLocales } from './utils/validation.js';\n\nexport async function handleStage(\n options: TranslateFlags,\n settings: Settings,\n library: SupportedLibraries,\n stage: boolean\n): Promise<{\n fileVersionData: FileTranslationData | undefined;\n jobData: EnqueueFilesResult | undefined;\n branchData: BranchData | undefined;\n publishMap: Map<string, boolean>;\n} | null> {\n if (!hasValidLocales(settings)) return exitSync(1);\n // Validate credentials if not in dry run\n if (!options.dryRun && !hasValidCredentials(settings)) return exitSync(1);\n\n const {\n files: allFiles,\n reactComponents,\n publishMap,\n } = await collectFiles(options, settings, library);\n\n // Dry run\n if (options.dryRun) {\n logger.success(`Dry run: No files were sent to General Translation.`);\n logCollectedFiles(allFiles, reactComponents);\n return null;\n }\n\n if (allFiles.length === 0 && !settings.publish) {\n logger.error(\n 'No files to translate were found. Check your configuration and try again.'\n );\n }\n\n // Send translations to General Translation\n let fileVersionData: FileTranslationData | undefined;\n let jobData: EnqueueFilesResult | undefined;\n let branchData: BranchData | undefined;\n if (allFiles.length > 0) {\n const { branchData: branchDataResult, enqueueResult } =\n await runStageFilesWorkflow({ files: allFiles, options, settings });\n jobData = enqueueResult;\n branchData = branchDataResult;\n\n fileVersionData = convertToFileTranslationData(allFiles);\n\n // Write staged entries to the lockfile\n if (stage) {\n const stagedFiles = Object.entries(fileVersionData).map(\n ([fileId, data]) => ({\n fileId,\n versionId: data.versionId,\n fileName: data.fileName,\n })\n );\n writeStagedEntries(settings, stagedFiles, branchData.currentBranch.id);\n }\n const templateData = allFiles.find(\n (file) => file.fileId === TEMPLATE_FILE_ID\n );\n if (templateData?.versionId) {\n await updateConfig(settings.config, {\n _versionId: templateData.versionId,\n _branchId: branchData.currentBranch.id,\n });\n }\n }\n\n // Always delete branch id from config if branching is disabled\n // Avoids incorrect CDN queries at runtime\n if (!settings.branchOptions.enabled) {\n await updateConfig(settings.config, {\n _branchId: null,\n });\n }\n\n return {\n fileVersionData,\n jobData,\n branchData,\n publishMap,\n };\n}\n"],"mappings":";;;;;;;;;;AAkBA,eAAsB,YACpB,SACA,UACA,SACA,OAMQ;AACR,KAAI,CAAC,gBAAgB,SAAS,CAAE,QAAO,SAAS,EAAE;AAElD,KAAI,CAAC,QAAQ,UAAU,CAAC,oBAAoB,SAAS,CAAE,QAAO,SAAS,EAAE;CAEzE,MAAM,EACJ,OAAO,UACP,iBACA,eACE,MAAM,aAAa,SAAS,UAAU,QAAQ;AAGlD,KAAI,QAAQ,QAAQ;AAClB,SAAO,QAAQ,sDAAsD;AACrE,oBAAkB,UAAU,gBAAgB;AAC5C,SAAO;;AAGT,KAAI,SAAS,WAAW,KAAK,CAAC,SAAS,QACrC,QAAO,MACL,4EACD;CAIH,IAAI;CACJ,IAAI;CACJ,IAAI;AACJ,KAAI,SAAS,SAAS,GAAG;EACvB,MAAM,EAAE,YAAY,kBAAkB,kBACpC,MAAM,sBAAsB;GAAE,OAAO;GAAU;GAAS;GAAU,CAAC;AACrE,YAAU;AACV,eAAa;AAEb,oBAAkB,6BAA6B,SAAS;AAGxD,MAAI,MAQF,oBAAmB,UAPC,OAAO,QAAQ,gBAAgB,CAAC,KACjD,CAAC,QAAQ,WAAW;GACnB;GACA,WAAW,KAAK;GAChB,UAAU,KAAK;GAChB,EAEqC,EAAE,WAAW,cAAc,GAAG;EAExE,MAAM,eAAe,SAAS,MAC3B,SAAS,KAAK,WAAW,iBAC3B;AACD,MAAI,cAAc,UAChB,OAAM,aAAa,SAAS,QAAQ;GAClC,YAAY,aAAa;GACzB,WAAW,WAAW,cAAc;GACrC,CAAC;;AAMN,KAAI,CAAC,SAAS,cAAc,QAC1B,OAAM,aAAa,SAAS,QAAQ,EAClC,WAAW,MACZ,CAAC;AAGJ,QAAO;EACL;EACA;EACA;EACA;EACD"}
@@ -1,13 +1,8 @@
1
- import { ResolvedFiles, Settings, TransformFiles } from '../../types/index.js';
2
- import { DataFormat } from '../../types/data.js';
1
+ import { Settings } from '../../types/index.js';
3
2
  import { UploadOptions } from '../base.js';
4
3
  /**
5
4
  * Sends multiple files to the API for translation
6
- * @param filePaths - Resolved file paths for different file types
7
- * @param placeholderPaths - Placeholder paths for translated files
8
- * @param transformPaths - Transform paths for file naming
9
- * @param dataFormat - Format of the data within the files
10
5
  * @param settings - Translation options including API settings
11
6
  * @returns Promise that resolves when translation is complete
12
7
  */
13
- export declare function upload(filePaths: ResolvedFiles, placeholderPaths: ResolvedFiles, transformPaths: TransformFiles, dataFormat: DataFormat | undefined, settings: Settings & UploadOptions): Promise<void>;
8
+ export declare function upload(settings: Settings & UploadOptions): Promise<void>;
@@ -1,122 +1,36 @@
1
1
  import { logger } from "../../console/logger.js";
2
- import { hashStringSync } from "../../utils/hash.js";
3
2
  import { exitSync, logErrorAndExit } from "../../console/logging.js";
4
3
  import { getRelative, readFile } from "../../fs/findFilepath.js";
5
- import { noDefaultLocaleError, noSupportedFormatError } from "../../console/index.js";
6
- import { SUPPORTED_FILE_EXTENSIONS } from "../../formats/files/supportedFiles.js";
7
- import { getTransformFormatProperty } from "../../formats/files/transformFormat.js";
8
- import sanitizeFileContent from "../../utils/sanitizeFileContent.js";
4
+ import { noDefaultLocaleError } from "../../console/index.js";
9
5
  import { validateJsonSchema } from "../../formats/json/utils.js";
10
- import { parseJson } from "../../formats/json/parseJson.js";
11
6
  import { extractJson } from "../../formats/json/extractJson.js";
12
- import { resolveMintlifyRefs, shouldResolveRefs } from "../../utils/resolveMintlifyRefs.js";
13
7
  import { runUploadFilesWorkflow } from "../../workflows/upload.js";
14
8
  import { createFileMapping } from "../../formats/files/fileMapping.js";
15
- import parseYaml from "../../formats/yaml/parseYaml.js";
16
9
  import { hasValidCredentials } from "./utils/validation.js";
17
- import { buildPublishMap } from "../../utils/resolvePublish.js";
18
10
  import { runPublishWorkflow } from "../../workflows/publish.js";
11
+ import { aggregateFiles } from "../../formats/files/aggregateFiles.js";
19
12
  import { existsSync, readFileSync } from "node:fs";
20
13
  //#region src/cli/commands/upload.ts
21
- const SUPPORTED_DATA_FORMATS = [
22
- "JSX",
23
- "ICU",
24
- "I18NEXT"
25
- ];
26
14
  /**
27
15
  * Sends multiple files to the API for translation
28
- * @param filePaths - Resolved file paths for different file types
29
- * @param placeholderPaths - Placeholder paths for translated files
30
- * @param transformPaths - Transform paths for file naming
31
- * @param dataFormat - Format of the data within the files
32
16
  * @param settings - Translation options including API settings
33
17
  * @returns Promise that resolves when translation is complete
34
18
  */
35
- async function upload(filePaths, placeholderPaths, transformPaths, dataFormat = "JSX", settings) {
36
- const allFiles = [];
19
+ async function upload(settings) {
20
+ if (!settings.files) return;
37
21
  const additionalOptions = settings.options || {};
22
+ const { resolvedPaths: filePaths, placeholderPaths, transformPaths, transformFormats } = settings.files;
23
+ const { files: allFiles, publishMap } = await aggregateFiles(settings);
38
24
  const compositeJsonFiles = /* @__PURE__ */ new Map();
39
25
  if (filePaths.json) {
40
- if (!SUPPORTED_DATA_FORMATS.includes(dataFormat)) logErrorAndExit(noSupportedFormatError);
41
- const jsonFiles = filePaths.json.map((filePath) => {
42
- const content = readFile(filePath);
43
- let contentForParsing = content;
44
- if (shouldResolveRefs(filePath, additionalOptions)) try {
45
- const { resolved } = resolveMintlifyRefs(JSON.parse(content), filePath);
46
- contentForParsing = JSON.stringify(resolved, null, 2);
47
- } catch {}
48
- const parsedJson = parseJson(contentForParsing, filePath, additionalOptions, settings.defaultLocale);
26
+ const sourceFileNames = new Set(allFiles.map((file) => file.fileName));
27
+ for (const filePath of filePaths.json) {
49
28
  const relativePath = getRelative(filePath);
29
+ if (!sourceFileNames.has(relativePath)) continue;
50
30
  if (validateJsonSchema(additionalOptions, filePath)?.composite) compositeJsonFiles.set(relativePath, {
51
31
  filePath,
52
- content
32
+ content: readFile(filePath)
53
33
  });
54
- return {
55
- content: parsedJson,
56
- fileName: relativePath,
57
- fileFormat: "JSON",
58
- ...getTransformFormatProperty(settings, "json"),
59
- dataFormat,
60
- locale: settings.defaultLocale,
61
- fileId: hashStringSync(relativePath),
62
- versionId: hashStringSync(parsedJson)
63
- };
64
- });
65
- allFiles.push(...jsonFiles);
66
- }
67
- if (filePaths.yaml) {
68
- if (!SUPPORTED_DATA_FORMATS.includes(dataFormat)) logErrorAndExit(noSupportedFormatError);
69
- const yamlFiles = filePaths.yaml.map((filePath) => {
70
- const { content: parsedYaml, fileFormat } = parseYaml(readFile(filePath), filePath, additionalOptions);
71
- const relativePath = getRelative(filePath);
72
- return {
73
- content: parsedYaml,
74
- fileName: relativePath,
75
- fileFormat,
76
- ...getTransformFormatProperty(settings, "yaml"),
77
- dataFormat,
78
- locale: settings.defaultLocale,
79
- fileId: hashStringSync(relativePath),
80
- versionId: hashStringSync(parsedYaml)
81
- };
82
- });
83
- allFiles.push(...yamlFiles);
84
- }
85
- if (filePaths.twilioContentJson) {
86
- const twilioContentJsonFiles = filePaths.twilioContentJson.map((filePath) => {
87
- const parsedJson = parseJson(readFile(filePath), filePath, additionalOptions, settings.defaultLocale);
88
- const relativePath = getRelative(filePath);
89
- return {
90
- content: parsedJson,
91
- fileName: relativePath,
92
- fileFormat: "TWILIO_CONTENT_JSON",
93
- ...getTransformFormatProperty(settings, "twilioContentJson"),
94
- dataFormat: "STRING",
95
- locale: settings.defaultLocale,
96
- fileId: hashStringSync(relativePath),
97
- versionId: hashStringSync(parsedJson)
98
- };
99
- });
100
- allFiles.push(...twilioContentJsonFiles);
101
- }
102
- for (const fileType of SUPPORTED_FILE_EXTENSIONS) {
103
- if (fileType === "json" || fileType === "yaml" || fileType === "twilioContentJson") continue;
104
- if (filePaths[fileType]) {
105
- const files = filePaths[fileType].map((filePath) => {
106
- const sanitizedContent = sanitizeFileContent(readFile(filePath));
107
- const relativePath = getRelative(filePath);
108
- return {
109
- content: sanitizedContent,
110
- fileName: relativePath,
111
- fileFormat: fileType.toUpperCase(),
112
- ...getTransformFormatProperty(settings, fileType),
113
- dataFormat,
114
- locale: settings.defaultLocale,
115
- fileId: hashStringSync(relativePath),
116
- versionId: hashStringSync(sanitizedContent)
117
- };
118
- });
119
- allFiles.push(...files);
120
34
  }
121
35
  }
122
36
  if (allFiles.length === 0) {
@@ -126,18 +40,9 @@ async function upload(filePaths, placeholderPaths, transformPaths, dataFormat =
126
40
  if (!settings.defaultLocale) return logErrorAndExit(noDefaultLocaleError);
127
41
  if (!hasValidCredentials(settings)) return exitSync(1);
128
42
  const locales = settings.locales || [];
129
- const fileMapping = createFileMapping(filePaths, placeholderPaths, transformPaths, settings.files?.transformFormats || {}, locales, settings.defaultLocale);
43
+ const fileMapping = createFileMapping(filePaths, placeholderPaths, transformPaths, transformFormats, locales, settings.defaultLocale);
130
44
  const uploadData = allFiles.map((file) => {
131
- const sourceFile = {
132
- content: file.content,
133
- fileName: file.fileName,
134
- fileFormat: file.fileFormat,
135
- transformFormat: file.transformFormat,
136
- dataFormat: file.dataFormat,
137
- locale: file.locale,
138
- fileId: file.fileId,
139
- versionId: file.versionId
140
- };
45
+ const sourceFile = { ...file };
141
46
  const translations = [];
142
47
  const compositeInfo = compositeJsonFiles.get(file.fileName);
143
48
  for (const locale of locales) if (compositeInfo) {
@@ -176,7 +81,7 @@ async function upload(filePaths, placeholderPaths, transformPaths, dataFormat =
176
81
  files: uploadData,
177
82
  options: settings
178
83
  });
179
- await runPublishWorkflow(allFiles, buildPublishMap(filePaths, settings), branchData.currentBranch.id, settings);
84
+ await runPublishWorkflow(allFiles, publishMap, branchData.currentBranch.id, settings);
180
85
  } catch (error) {
181
86
  logErrorAndExit(`Error uploading files: ${error}`);
182
87
  }
@@ -1 +1 @@
1
- {"version":3,"file":"upload.js","names":[],"sources":["../../../src/cli/commands/upload.ts"],"sourcesContent":["import {\n noSupportedFormatError,\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 { ResolvedFiles, Settings, TransformFiles } from '../../types/index.js';\nimport { FileFormat, DataFormat } from '../../types/data.js';\nimport { SUPPORTED_FILE_EXTENSIONS } from '../../formats/files/supportedFiles.js';\nimport { UploadOptions } from '../base.js';\nimport sanitizeFileContent from '../../utils/sanitizeFileContent.js';\nimport { parseJson } from '../../formats/json/parseJson.js';\nimport { extractJson } from '../../formats/json/extractJson.js';\nimport { validateJsonSchema } from '../../formats/json/utils.js';\nimport {\n resolveMintlifyRefs,\n shouldResolveRefs,\n} from '../../utils/resolveMintlifyRefs.js';\nimport { runUploadFilesWorkflow } from '../../workflows/upload.js';\nimport { existsSync, readFileSync } from 'node:fs';\nimport { createFileMapping } from '../../formats/files/fileMapping.js';\nimport parseYaml from '../../formats/yaml/parseYaml.js';\nimport type { FileToUpload } from 'generaltranslation/types';\nimport { hashStringSync } from '../../utils/hash.js';\nimport { hasValidCredentials } from './utils/validation.js';\nimport { buildPublishMap } from '../../utils/resolvePublish.js';\nimport { runPublishWorkflow } from '../../workflows/publish.js';\nimport { getTransformFormatProperty } from '../../formats/files/transformFormat.js';\n\nconst SUPPORTED_DATA_FORMATS = ['JSX', 'ICU', 'I18NEXT'];\n\n/**\n * Sends multiple files to the API for translation\n * @param filePaths - Resolved file paths for different file types\n * @param placeholderPaths - Placeholder paths for translated files\n * @param transformPaths - Transform paths for file naming\n * @param dataFormat - Format of the data within the files\n * @param settings - Translation options including API settings\n * @returns Promise that resolves when translation is complete\n */\nexport async function upload(\n filePaths: ResolvedFiles,\n placeholderPaths: ResolvedFiles,\n transformPaths: TransformFiles,\n dataFormat: DataFormat = 'JSX',\n settings: Settings & UploadOptions\n): Promise<void> {\n // Collect all files to translate\n const allFiles: FileToUpload[] = [];\n const additionalOptions = settings.options || {};\n const compositeJsonFiles = new Map<\n string,\n { filePath: string; content: string }\n >();\n\n // Process JSON files\n if (filePaths.json) {\n if (!SUPPORTED_DATA_FORMATS.includes(dataFormat)) {\n logErrorAndExit(noSupportedFormatError);\n }\n\n const jsonFiles = filePaths.json.map((filePath) => {\n const content = readFile(filePath);\n\n // Resolve $ref before parsing if configured\n let contentForParsing = content;\n if (shouldResolveRefs(filePath, additionalOptions)) {\n try {\n const json = JSON.parse(content);\n const { resolved } = resolveMintlifyRefs(json, filePath);\n contentForParsing = JSON.stringify(resolved, null, 2);\n } catch {\n // JSON parse errors are handled below by parseJson\n }\n }\n\n const parsedJson = parseJson(\n contentForParsing,\n filePath,\n additionalOptions,\n settings.defaultLocale\n );\n\n const relativePath = getRelative(filePath);\n\n const jsonSchema = validateJsonSchema(additionalOptions, filePath);\n if (jsonSchema?.composite) {\n compositeJsonFiles.set(relativePath, { filePath, content });\n }\n\n return {\n content: parsedJson,\n fileName: relativePath,\n fileFormat: 'JSON' as FileFormat,\n ...getTransformFormatProperty(settings, 'json'),\n dataFormat,\n locale: settings.defaultLocale,\n fileId: hashStringSync(relativePath),\n versionId: hashStringSync(parsedJson),\n } satisfies FileToUpload;\n });\n allFiles.push(...jsonFiles);\n }\n\n // Process YAML files\n if (filePaths.yaml) {\n if (!SUPPORTED_DATA_FORMATS.includes(dataFormat)) {\n logErrorAndExit(noSupportedFormatError);\n }\n\n const yamlFiles = filePaths.yaml.map((filePath) => {\n const content = readFile(filePath);\n const { content: parsedYaml, fileFormat } = parseYaml(\n content,\n filePath,\n additionalOptions\n );\n\n const relativePath = getRelative(filePath);\n return {\n content: parsedYaml,\n fileName: relativePath,\n fileFormat,\n ...getTransformFormatProperty(settings, 'yaml'),\n dataFormat,\n locale: settings.defaultLocale,\n fileId: hashStringSync(relativePath),\n versionId: hashStringSync(parsedYaml),\n } satisfies FileToUpload;\n });\n allFiles.push(...yamlFiles);\n }\n\n // Process Twilio Content JSON files\n if (filePaths.twilioContentJson) {\n const twilioContentJsonFiles = filePaths.twilioContentJson.map(\n (filePath) => {\n const content = readFile(filePath);\n\n const parsedJson = parseJson(\n content,\n filePath,\n additionalOptions,\n settings.defaultLocale\n );\n\n const relativePath = getRelative(filePath);\n\n return {\n content: parsedJson,\n fileName: relativePath,\n fileFormat: 'TWILIO_CONTENT_JSON' as const,\n ...getTransformFormatProperty(settings, 'twilioContentJson'),\n dataFormat: 'STRING' as const,\n locale: settings.defaultLocale,\n fileId: hashStringSync(relativePath),\n versionId: hashStringSync(parsedJson),\n } satisfies FileToUpload;\n }\n );\n allFiles.push(...twilioContentJsonFiles);\n }\n\n for (const fileType of SUPPORTED_FILE_EXTENSIONS) {\n if (\n fileType === 'json' ||\n fileType === 'yaml' ||\n fileType === 'twilioContentJson'\n )\n continue;\n if (filePaths[fileType]) {\n const files = filePaths[fileType].map((filePath) => {\n const content = readFile(filePath);\n const sanitizedContent = sanitizeFileContent(content);\n const relativePath = getRelative(filePath);\n return {\n content: sanitizedContent,\n fileName: relativePath,\n fileFormat: fileType.toUpperCase() as FileFormat,\n ...getTransformFormatProperty(settings, fileType),\n dataFormat,\n locale: settings.defaultLocale,\n fileId: hashStringSync(relativePath),\n versionId: hashStringSync(sanitizedContent),\n } satisfies FileToUpload;\n });\n allFiles.push(...files);\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 settings.files?.transformFormats || {},\n locales,\n settings.defaultLocale\n );\n\n // construct object\n const uploadData = allFiles.map((file) => {\n const sourceFile: FileToUpload = {\n content: file.content,\n fileName: file.fileName,\n fileFormat: file.fileFormat,\n transformFormat: file.transformFormat,\n dataFormat: file.dataFormat,\n locale: file.locale,\n fileId: file.fileId,\n versionId: file.versionId,\n };\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 translatedContent = readFileSync(translatedFileName, 'utf8');\n translations.push({\n content: translatedContent,\n fileName: translatedFileName,\n fileFormat: file.transformFormat ?? file.fileFormat,\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 const publishMap = buildPublishMap(filePaths, settings);\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":"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"}
1
+ {"version":3,"file":"upload.js","names":[],"sources":["../../../src/cli/commands/upload.ts"],"sourcesContent":["import { noDefaultLocaleError } 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 { 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, readFileSync } 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';\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 translatedContent = readFileSync(translatedFileName, 'utf8');\n translations.push({\n content: translatedContent,\n fileName: translatedFileName,\n fileFormat: file.transformFormat ?? file.fileFormat,\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":";;;;;;;;;;;;;;;;;;AAqBA,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,aAAa,oBAAoB,OAAO;AAClE,iBAAa,KAAK;KAChB,SAAS;KACT,UAAU;KACV,YAAY,KAAK,mBAAmB,KAAK;KACzC,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,13 +5,13 @@ import { SUPPORTED_FILE_EXTENSIONS } from "./supportedFiles.js";
5
5
  import { getTransformFormatProperty } from "./transformFormat.js";
6
6
  import { determineLibrary } from "../../fs/determineFramework/index.js";
7
7
  import { flattenJson } from "../json/flattenJson.js";
8
+ import { recordWarning } from "../../state/translateWarnings.js";
9
+ import { buildPublishMap } from "../../utils/resolvePublish.js";
8
10
  import { parseJson } from "../json/parseJson.js";
9
11
  import { resolveMintlifyRefs, shouldResolveRefs } from "../../utils/resolveMintlifyRefs.js";
10
- import { recordWarning } from "../../state/translateWarnings.js";
12
+ import { storeRefMap } from "../../state/mintlifyRefMap.js";
11
13
  import { validateYamlSchema } from "../yaml/utils.js";
12
14
  import parseYaml from "../yaml/parseYaml.js";
13
- import { buildPublishMap } from "../../utils/resolvePublish.js";
14
- import { storeRefMap } from "../../state/mintlifyRefMap.js";
15
15
  import { preprocessContent } from "./preprocessContent.js";
16
16
  import { parseKeyedMetadata } from "../parseKeyedMetadata.js";
17
17
  import YAML from "yaml";
@@ -213,7 +213,6 @@ async function aggregateFiles(settings) {
213
213
  files.push(...parsed.filter((file) => file !== null));
214
214
  }
215
215
  }
216
- if (files.length === 0 && !settings.publish) logger.error("No files to translate were found. Check your configuration and try again.");
217
216
  const validFileIds = new Set(files.map((f) => f.fileId));
218
217
  for (const fileId of publishMap.keys()) if (!validFileIds.has(fileId)) publishMap.delete(fileId);
219
218
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"aggregateFiles.js","names":[],"sources":["../../../src/formats/files/aggregateFiles.ts"],"sourcesContent":["import { logger } from '../../console/logger.js';\nimport { recordWarning } from '../../state/translateWarnings.js';\nimport { getRelative, readFile } from '../../fs/findFilepath.js';\nimport { Settings } from '../../types/index.js';\nimport type { FileFormat, DataFormat, FileToUpload } from '../../types/data.js';\nimport { SUPPORTED_FILE_EXTENSIONS } from './supportedFiles.js';\nimport { parseJson } from '../json/parseJson.js';\nimport {\n resolveMintlifyRefs,\n shouldResolveRefs,\n} from '../../utils/resolveMintlifyRefs.js';\nimport { storeRefMap } from '../../state/mintlifyRefMap.js';\nimport parseYaml from '../yaml/parseYaml.js';\nimport { validateYamlSchema } from '../yaml/utils.js';\nimport { flattenJson } from '../json/flattenJson.js';\nimport type { JSONObject } from '../../types/data/json.js';\nimport YAML from 'yaml';\nimport { determineLibrary } from '../../fs/determineFramework/index.js';\nimport { hashStringSync } from '../../utils/hash.js';\nimport { preprocessContent } from './preprocessContent.js';\nimport {\n parseKeyedMetadata,\n type KeyedMetadata,\n} from '../parseKeyedMetadata.js';\nimport { buildPublishMap } from '../../utils/resolvePublish.js';\nimport { getTransformFormatProperty } from './transformFormat.js';\n\n/**\n * Checks if a file path is a metadata companion file (e.g. foo.metadata.json)\n * AND its corresponding source file (e.g. foo.json) exists in the file list.\n * If both conditions are true, the metadata file should be skipped as a translation source.\n */\nfunction isCompanionMetadataFile(\n filePath: string,\n allFilePaths: string[]\n): boolean {\n const metadataPattern = /\\.metadata\\.(json|yaml|yml)$/;\n if (!metadataPattern.test(filePath)) return false;\n\n // Derive the source file path: foo.metadata.json -> foo.json\n const sourceFilePath = filePath.replace(\n /\\.metadata\\.(json|yaml|yml)$/,\n '.$1'\n );\n return allFilePaths.includes(sourceFilePath);\n}\nexport const SUPPORTED_DATA_FORMATS = ['JSX', 'ICU', 'I18NEXT'];\n\nexport async function aggregateFiles(\n settings: Settings\n): Promise<{ files: FileToUpload[]; publishMap: Map<string, boolean> }> {\n // Aggregate all files to translate\n const files: FileToUpload[] = [];\n if (\n !settings.files ||\n (Object.keys(settings.files.placeholderPaths).length === 1 &&\n settings.files.placeholderPaths.gt)\n ) {\n return { files, publishMap: new Map<string, boolean>() };\n }\n\n const { resolvedPaths: filePaths } = settings.files;\n const skipValidation = settings.options?.skipFileValidation;\n\n // Build publish map upfront from resolved paths.\n const publishMap = buildPublishMap(filePaths, settings);\n\n // Process JSON files\n if (filePaths.json) {\n const { library, additionalModules } = determineLibrary();\n\n // Determine dataFormat for JSONs\n let dataFormat: DataFormat;\n if (library === 'next-intl') {\n dataFormat = 'ICU';\n } else if (library === 'i18next') {\n if (additionalModules.includes('i18next-icu')) {\n dataFormat = 'ICU';\n } else {\n dataFormat = 'I18NEXT';\n }\n } else {\n dataFormat = 'STRING';\n }\n\n const jsonFiles = filePaths.json\n .filter((filePath) => !isCompanionMetadataFile(filePath, filePaths.json!))\n .map((filePath) => {\n const content = readFile(filePath);\n const relativePath = getRelative(filePath);\n\n // Pre-validate JSON parseability\n if (!skipValidation?.json) {\n try {\n JSON.parse(content);\n } catch {\n logger.warn(`Skipping ${relativePath}: JSON file is not parsable`);\n recordWarning(\n 'skipped_file',\n relativePath,\n 'JSON file is not parsable'\n );\n return null;\n }\n }\n\n // Resolve $ref before parsing if configured\n let contentForParsing = content;\n if (shouldResolveRefs(filePath, settings.options)) {\n try {\n const json = JSON.parse(content);\n const { resolved, refMap } = resolveMintlifyRefs(json, filePath);\n storeRefMap(refMap);\n contentForParsing = JSON.stringify(resolved, null, 2);\n } catch {\n // JSON parse errors are handled below by parseJson\n }\n }\n\n const parsedJson = parseJson(\n contentForParsing,\n filePath,\n settings.options || {},\n settings.defaultLocale\n );\n\n // Detect companion metadata file\n let keyedMetadata: KeyedMetadata | undefined;\n let parsedContent: JSONObject | undefined;\n try {\n parsedContent = JSON.parse(content) as JSONObject;\n } catch {\n // Content not parsable — skip metadata detection\n }\n if (parsedContent) {\n const rawMetadata = parseKeyedMetadata(filePath, parsedContent);\n if (rawMetadata) {\n // Run metadata through the same include/composite schema as the source\n // so key paths align at translation time\n const transformed = parseJson(\n JSON.stringify(rawMetadata),\n filePath,\n settings.options || {},\n settings.defaultLocale,\n false\n );\n const transformedMetadata = JSON.parse(transformed);\n\n // Filter metadata to only keep keys that exist in the transformed source\n // This prevents misaligned entries from wide JSONPath patterns\n const sourceKeys = new Set(Object.keys(JSON.parse(parsedJson)));\n const filtered = Object.fromEntries(\n Object.entries(transformedMetadata).filter(([k]) =>\n sourceKeys.has(k)\n )\n ) as KeyedMetadata;\n\n if (Object.keys(filtered).length > 0) {\n keyedMetadata = filtered;\n } else {\n logger.warn(\n `Companion metadata found for ${relativePath} but no keys aligned with the JSON schema — metadata was not attached`\n );\n }\n }\n }\n\n return {\n fileId: hashStringSync(relativePath),\n versionId: hashStringSync(parsedJson),\n content: parsedJson,\n fileName: relativePath,\n fileFormat: 'JSON' as const,\n ...getTransformFormatProperty(settings, 'json'),\n dataFormat,\n locale: settings.defaultLocale,\n ...(keyedMetadata && {\n formatMetadata: { keyedMetadata },\n }),\n } satisfies FileToUpload;\n })\n .filter((file) => {\n if (!file) return false;\n if (typeof file.content !== 'string' || !file.content.trim()) {\n logger.warn(`Skipping ${file.fileName}: JSON file is empty`);\n recordWarning('skipped_file', file.fileName, 'JSON file is empty');\n return false;\n }\n return true;\n });\n files.push(...jsonFiles.filter((file) => file !== null));\n }\n\n // Process YAML files\n if (filePaths.yaml) {\n const yamlFiles = filePaths.yaml\n .filter((filePath) => !isCompanionMetadataFile(filePath, filePaths.yaml!))\n .map((filePath) => {\n const content = readFile(filePath);\n const relativePath = getRelative(filePath);\n\n // Pre-validate YAML parseability\n if (!skipValidation?.yaml) {\n try {\n YAML.parse(content);\n } catch {\n logger.warn(`Skipping ${relativePath}: YAML file is not parsable`);\n recordWarning(\n 'skipped_file',\n relativePath,\n 'YAML file is not parsable'\n );\n return null;\n }\n }\n\n const { content: parsedYaml, fileFormat } = parseYaml(\n content,\n filePath,\n settings.options || {}\n );\n\n // Detect companion metadata file\n let keyedMetadata: KeyedMetadata | undefined;\n try {\n const parsedYamlContent = YAML.parse(content);\n const rawMetadata = parseKeyedMetadata(filePath, parsedYamlContent);\n if (rawMetadata) {\n const yamlSchema = validateYamlSchema(\n settings.options || {},\n filePath\n );\n if (yamlSchema?.include) {\n // Flatten metadata through the same include schema as the source\n const flattened = flattenJson(rawMetadata, yamlSchema.include);\n // Filter to only keep keys that exist in the transformed source\n const sourceKeys = new Set(Object.keys(JSON.parse(parsedYaml)));\n const filtered = Object.fromEntries(\n Object.entries(flattened).filter(([k]) => sourceKeys.has(k))\n ) as KeyedMetadata;\n if (Object.keys(filtered).length > 0) {\n keyedMetadata = filtered;\n } else {\n logger.warn(\n `Companion metadata found for ${relativePath} but no keys aligned with the YAML schema — metadata was not attached`\n );\n }\n } else {\n keyedMetadata = rawMetadata;\n }\n }\n } catch {\n // Content not parsable as YAML — skip metadata detection\n }\n\n return {\n content: parsedYaml,\n fileName: relativePath,\n fileFormat,\n ...getTransformFormatProperty(settings, 'yaml'),\n fileId: hashStringSync(relativePath),\n versionId: hashStringSync(parsedYaml),\n locale: settings.defaultLocale,\n ...(keyedMetadata && {\n formatMetadata: { keyedMetadata },\n }),\n } satisfies FileToUpload;\n })\n .filter((file) => {\n if (!file || typeof file.content !== 'string' || !file.content.trim()) {\n logger.warn(\n `Skipping ${file?.fileName ?? 'unknown'}: YAML file is empty`\n );\n recordWarning(\n 'skipped_file',\n file?.fileName ?? 'unknown',\n 'YAML file is empty'\n );\n return false;\n }\n return true;\n });\n files.push(...yamlFiles.filter((file) => file !== null));\n }\n\n // Process Twilio Content JSON files\n if (filePaths.twilioContentJson) {\n const twilioContentJsonFiles = filePaths.twilioContentJson\n .map((filePath) => {\n const content = readFile(filePath);\n const relativePath = getRelative(filePath);\n\n // Pre-validate JSON parseability\n if (!skipValidation?.json) {\n try {\n JSON.parse(content);\n } catch {\n logger.warn(`Skipping ${relativePath}: JSON file is not parsable`);\n recordWarning(\n 'skipped_file',\n relativePath,\n 'JSON file is not parsable'\n );\n return null;\n }\n }\n\n const parsedJson = parseJson(\n content,\n filePath,\n settings.options || {},\n settings.defaultLocale\n );\n\n return {\n fileId: hashStringSync(relativePath),\n versionId: hashStringSync(parsedJson),\n content: parsedJson,\n fileName: relativePath,\n fileFormat: 'TWILIO_CONTENT_JSON' as const,\n ...getTransformFormatProperty(settings, 'twilioContentJson'),\n dataFormat: 'STRING' as const,\n locale: settings.defaultLocale,\n } satisfies FileToUpload;\n })\n .filter((file) => {\n if (!file) return false;\n if (typeof file.content !== 'string' || !file.content.trim()) {\n logger.warn(`Skipping ${file.fileName}: JSON file is empty`);\n recordWarning('skipped_file', file.fileName, 'JSON file is empty');\n return false;\n }\n return true;\n });\n files.push(...twilioContentJsonFiles.filter((file) => file !== null));\n }\n\n for (const fileType of SUPPORTED_FILE_EXTENSIONS) {\n if (\n fileType === 'json' ||\n fileType === 'yaml' ||\n fileType === 'twilioContentJson'\n )\n continue;\n if (filePaths[fileType]) {\n const parsed = filePaths[fileType]\n .map((filePath) => {\n const content = readFile(filePath);\n const relativePath = getRelative(filePath);\n\n const processed = preprocessContent(\n content,\n relativePath,\n fileType,\n settings\n );\n\n if (typeof processed !== 'string') {\n logger.warn(`Skipping ${relativePath}: ${processed.skip}`);\n recordWarning('skipped_file', relativePath, processed.skip);\n return null;\n }\n\n return {\n content: processed,\n fileName: relativePath,\n fileFormat: fileType.toUpperCase() as FileFormat,\n ...getTransformFormatProperty(settings, fileType),\n fileId: hashStringSync(relativePath),\n versionId: hashStringSync(processed),\n locale: settings.defaultLocale,\n } satisfies FileToUpload;\n })\n .filter((file) => {\n if (\n !file ||\n typeof file.content !== 'string' ||\n !file.content.trim()\n ) {\n logger.warn(\n `Skipping ${file?.fileName ?? 'unknown'}: File is empty after sanitization`\n );\n recordWarning(\n 'skipped_file',\n file?.fileName ?? 'unknown',\n 'File is empty after sanitization'\n );\n return false;\n }\n return true;\n });\n files.push(...parsed.filter((file) => file !== null));\n }\n }\n\n if (files.length === 0 && !settings.publish) {\n logger.error(\n 'No files to translate were found. Check your configuration and try again.'\n );\n }\n\n // Remove stale entries for files that were skipped during validation\n const validFileIds = new Set(files.map((f) => f.fileId));\n for (const fileId of publishMap.keys()) {\n if (!validFileIds.has(fileId)) {\n publishMap.delete(fileId);\n }\n }\n\n return { files, publishMap };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"aggregateFiles.js","names":[],"sources":["../../../src/formats/files/aggregateFiles.ts"],"sourcesContent":["import { logger } from '../../console/logger.js';\nimport { recordWarning } from '../../state/translateWarnings.js';\nimport { getRelative, readFile } from '../../fs/findFilepath.js';\nimport { Settings } from '../../types/index.js';\nimport type { FileFormat, DataFormat, FileToUpload } from '../../types/data.js';\nimport { SUPPORTED_FILE_EXTENSIONS } from './supportedFiles.js';\nimport { parseJson } from '../json/parseJson.js';\nimport {\n resolveMintlifyRefs,\n shouldResolveRefs,\n} from '../../utils/resolveMintlifyRefs.js';\nimport { storeRefMap } from '../../state/mintlifyRefMap.js';\nimport parseYaml from '../yaml/parseYaml.js';\nimport { validateYamlSchema } from '../yaml/utils.js';\nimport { flattenJson } from '../json/flattenJson.js';\nimport type { JSONObject } from '../../types/data/json.js';\nimport YAML from 'yaml';\nimport { determineLibrary } from '../../fs/determineFramework/index.js';\nimport { hashStringSync } from '../../utils/hash.js';\nimport { preprocessContent } from './preprocessContent.js';\nimport {\n parseKeyedMetadata,\n type KeyedMetadata,\n} from '../parseKeyedMetadata.js';\nimport { buildPublishMap } from '../../utils/resolvePublish.js';\nimport { getTransformFormatProperty } from './transformFormat.js';\n\n/**\n * Checks if a file path is a metadata companion file (e.g. foo.metadata.json)\n * AND its corresponding source file (e.g. foo.json) exists in the file list.\n * If both conditions are true, the metadata file should be skipped as a translation source.\n */\nfunction isCompanionMetadataFile(\n filePath: string,\n allFilePaths: string[]\n): boolean {\n const metadataPattern = /\\.metadata\\.(json|yaml|yml)$/;\n if (!metadataPattern.test(filePath)) return false;\n\n // Derive the source file path: foo.metadata.json -> foo.json\n const sourceFilePath = filePath.replace(\n /\\.metadata\\.(json|yaml|yml)$/,\n '.$1'\n );\n return allFilePaths.includes(sourceFilePath);\n}\nexport const SUPPORTED_DATA_FORMATS = ['JSX', 'ICU', 'I18NEXT'];\n\nexport async function aggregateFiles(\n settings: Settings\n): Promise<{ files: FileToUpload[]; publishMap: Map<string, boolean> }> {\n // Aggregate all files to translate\n const files: FileToUpload[] = [];\n if (\n !settings.files ||\n (Object.keys(settings.files.placeholderPaths).length === 1 &&\n settings.files.placeholderPaths.gt)\n ) {\n return { files, publishMap: new Map<string, boolean>() };\n }\n\n const { resolvedPaths: filePaths } = settings.files;\n const skipValidation = settings.options?.skipFileValidation;\n\n // Build publish map upfront from resolved paths.\n const publishMap = buildPublishMap(filePaths, settings);\n\n // Process JSON files\n if (filePaths.json) {\n const { library, additionalModules } = determineLibrary();\n\n // Determine dataFormat for JSONs\n let dataFormat: DataFormat;\n if (library === 'next-intl') {\n dataFormat = 'ICU';\n } else if (library === 'i18next') {\n if (additionalModules.includes('i18next-icu')) {\n dataFormat = 'ICU';\n } else {\n dataFormat = 'I18NEXT';\n }\n } else {\n dataFormat = 'STRING';\n }\n\n const jsonFiles = filePaths.json\n .filter((filePath) => !isCompanionMetadataFile(filePath, filePaths.json!))\n .map((filePath) => {\n const content = readFile(filePath);\n const relativePath = getRelative(filePath);\n\n // Pre-validate JSON parseability\n if (!skipValidation?.json) {\n try {\n JSON.parse(content);\n } catch {\n logger.warn(`Skipping ${relativePath}: JSON file is not parsable`);\n recordWarning(\n 'skipped_file',\n relativePath,\n 'JSON file is not parsable'\n );\n return null;\n }\n }\n\n // Resolve $ref before parsing if configured\n let contentForParsing = content;\n if (shouldResolveRefs(filePath, settings.options)) {\n try {\n const json = JSON.parse(content);\n const { resolved, refMap } = resolveMintlifyRefs(json, filePath);\n storeRefMap(refMap);\n contentForParsing = JSON.stringify(resolved, null, 2);\n } catch {\n // JSON parse errors are handled below by parseJson\n }\n }\n\n const parsedJson = parseJson(\n contentForParsing,\n filePath,\n settings.options || {},\n settings.defaultLocale\n );\n\n // Detect companion metadata file\n let keyedMetadata: KeyedMetadata | undefined;\n let parsedContent: JSONObject | undefined;\n try {\n parsedContent = JSON.parse(content) as JSONObject;\n } catch {\n // Content not parsable — skip metadata detection\n }\n if (parsedContent) {\n const rawMetadata = parseKeyedMetadata(filePath, parsedContent);\n if (rawMetadata) {\n // Run metadata through the same include/composite schema as the source\n // so key paths align at translation time\n const transformed = parseJson(\n JSON.stringify(rawMetadata),\n filePath,\n settings.options || {},\n settings.defaultLocale,\n false\n );\n const transformedMetadata = JSON.parse(transformed);\n\n // Filter metadata to only keep keys that exist in the transformed source\n // This prevents misaligned entries from wide JSONPath patterns\n const sourceKeys = new Set(Object.keys(JSON.parse(parsedJson)));\n const filtered = Object.fromEntries(\n Object.entries(transformedMetadata).filter(([k]) =>\n sourceKeys.has(k)\n )\n ) as KeyedMetadata;\n\n if (Object.keys(filtered).length > 0) {\n keyedMetadata = filtered;\n } else {\n logger.warn(\n `Companion metadata found for ${relativePath} but no keys aligned with the JSON schema — metadata was not attached`\n );\n }\n }\n }\n\n return {\n fileId: hashStringSync(relativePath),\n versionId: hashStringSync(parsedJson),\n content: parsedJson,\n fileName: relativePath,\n fileFormat: 'JSON' as const,\n ...getTransformFormatProperty(settings, 'json'),\n dataFormat,\n locale: settings.defaultLocale,\n ...(keyedMetadata && {\n formatMetadata: { keyedMetadata },\n }),\n } satisfies FileToUpload;\n })\n .filter((file) => {\n if (!file) return false;\n if (typeof file.content !== 'string' || !file.content.trim()) {\n logger.warn(`Skipping ${file.fileName}: JSON file is empty`);\n recordWarning('skipped_file', file.fileName, 'JSON file is empty');\n return false;\n }\n return true;\n });\n files.push(...jsonFiles.filter((file) => file !== null));\n }\n\n // Process YAML files\n if (filePaths.yaml) {\n const yamlFiles = filePaths.yaml\n .filter((filePath) => !isCompanionMetadataFile(filePath, filePaths.yaml!))\n .map((filePath) => {\n const content = readFile(filePath);\n const relativePath = getRelative(filePath);\n\n // Pre-validate YAML parseability\n if (!skipValidation?.yaml) {\n try {\n YAML.parse(content);\n } catch {\n logger.warn(`Skipping ${relativePath}: YAML file is not parsable`);\n recordWarning(\n 'skipped_file',\n relativePath,\n 'YAML file is not parsable'\n );\n return null;\n }\n }\n\n const { content: parsedYaml, fileFormat } = parseYaml(\n content,\n filePath,\n settings.options || {}\n );\n\n // Detect companion metadata file\n let keyedMetadata: KeyedMetadata | undefined;\n try {\n const parsedYamlContent = YAML.parse(content);\n const rawMetadata = parseKeyedMetadata(filePath, parsedYamlContent);\n if (rawMetadata) {\n const yamlSchema = validateYamlSchema(\n settings.options || {},\n filePath\n );\n if (yamlSchema?.include) {\n // Flatten metadata through the same include schema as the source\n const flattened = flattenJson(rawMetadata, yamlSchema.include);\n // Filter to only keep keys that exist in the transformed source\n const sourceKeys = new Set(Object.keys(JSON.parse(parsedYaml)));\n const filtered = Object.fromEntries(\n Object.entries(flattened).filter(([k]) => sourceKeys.has(k))\n ) as KeyedMetadata;\n if (Object.keys(filtered).length > 0) {\n keyedMetadata = filtered;\n } else {\n logger.warn(\n `Companion metadata found for ${relativePath} but no keys aligned with the YAML schema — metadata was not attached`\n );\n }\n } else {\n keyedMetadata = rawMetadata;\n }\n }\n } catch {\n // Content not parsable as YAML — skip metadata detection\n }\n\n return {\n content: parsedYaml,\n fileName: relativePath,\n fileFormat,\n ...getTransformFormatProperty(settings, 'yaml'),\n fileId: hashStringSync(relativePath),\n versionId: hashStringSync(parsedYaml),\n locale: settings.defaultLocale,\n ...(keyedMetadata && {\n formatMetadata: { keyedMetadata },\n }),\n } satisfies FileToUpload;\n })\n .filter((file) => {\n if (!file || typeof file.content !== 'string' || !file.content.trim()) {\n logger.warn(\n `Skipping ${file?.fileName ?? 'unknown'}: YAML file is empty`\n );\n recordWarning(\n 'skipped_file',\n file?.fileName ?? 'unknown',\n 'YAML file is empty'\n );\n return false;\n }\n return true;\n });\n files.push(...yamlFiles.filter((file) => file !== null));\n }\n\n // Process Twilio Content JSON files\n if (filePaths.twilioContentJson) {\n const twilioContentJsonFiles = filePaths.twilioContentJson\n .map((filePath) => {\n const content = readFile(filePath);\n const relativePath = getRelative(filePath);\n\n // Pre-validate JSON parseability\n if (!skipValidation?.json) {\n try {\n JSON.parse(content);\n } catch {\n logger.warn(`Skipping ${relativePath}: JSON file is not parsable`);\n recordWarning(\n 'skipped_file',\n relativePath,\n 'JSON file is not parsable'\n );\n return null;\n }\n }\n\n const parsedJson = parseJson(\n content,\n filePath,\n settings.options || {},\n settings.defaultLocale\n );\n\n return {\n fileId: hashStringSync(relativePath),\n versionId: hashStringSync(parsedJson),\n content: parsedJson,\n fileName: relativePath,\n fileFormat: 'TWILIO_CONTENT_JSON' as const,\n ...getTransformFormatProperty(settings, 'twilioContentJson'),\n dataFormat: 'STRING' as const,\n locale: settings.defaultLocale,\n } satisfies FileToUpload;\n })\n .filter((file) => {\n if (!file) return false;\n if (typeof file.content !== 'string' || !file.content.trim()) {\n logger.warn(`Skipping ${file.fileName}: JSON file is empty`);\n recordWarning('skipped_file', file.fileName, 'JSON file is empty');\n return false;\n }\n return true;\n });\n files.push(...twilioContentJsonFiles.filter((file) => file !== null));\n }\n\n for (const fileType of SUPPORTED_FILE_EXTENSIONS) {\n if (\n fileType === 'json' ||\n fileType === 'yaml' ||\n fileType === 'twilioContentJson'\n )\n continue;\n if (filePaths[fileType]) {\n const parsed = filePaths[fileType]\n .map((filePath) => {\n const content = readFile(filePath);\n const relativePath = getRelative(filePath);\n\n const processed = preprocessContent(\n content,\n relativePath,\n fileType,\n settings\n );\n\n if (typeof processed !== 'string') {\n logger.warn(`Skipping ${relativePath}: ${processed.skip}`);\n recordWarning('skipped_file', relativePath, processed.skip);\n return null;\n }\n\n return {\n content: processed,\n fileName: relativePath,\n fileFormat: fileType.toUpperCase() as FileFormat,\n ...getTransformFormatProperty(settings, fileType),\n fileId: hashStringSync(relativePath),\n versionId: hashStringSync(processed),\n locale: settings.defaultLocale,\n } satisfies FileToUpload;\n })\n .filter((file) => {\n if (\n !file ||\n typeof file.content !== 'string' ||\n !file.content.trim()\n ) {\n logger.warn(\n `Skipping ${file?.fileName ?? 'unknown'}: File is empty after sanitization`\n );\n recordWarning(\n 'skipped_file',\n file?.fileName ?? 'unknown',\n 'File is empty after sanitization'\n );\n return false;\n }\n return true;\n });\n files.push(...parsed.filter((file) => file !== null));\n }\n }\n\n // Remove stale entries for files that were skipped during validation\n const validFileIds = new Set(files.map((f) => f.fileId));\n for (const fileId of publishMap.keys()) {\n if (!validFileIds.has(fileId)) {\n publishMap.delete(fileId);\n }\n }\n\n return { files, publishMap };\n}\n"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
- import sanitizeFileContent from "../../utils/sanitizeFileContent.js";
2
1
  import { preprocessMdx } from "./preprocess/mdx.js";
3
2
  import { preprocessMintlify } from "./preprocess/mintlify.js";
3
+ import sanitizeFileContent from "../../utils/sanitizeFileContent.js";
4
4
  //#region src/formats/files/preprocessContent.ts
5
5
  /**
6
6
  * Preprocesses file content before upload. Returns the processed content,
@@ -1 +1 @@
1
- export declare const PACKAGE_VERSION = "2.14.50";
1
+ export declare const PACKAGE_VERSION = "2.14.51";
@@ -1,5 +1,5 @@
1
1
  //#region src/generated/version.ts
2
- const PACKAGE_VERSION = "2.14.50";
2
+ const PACKAGE_VERSION = "2.14.51";
3
3
  //#endregion
4
4
  export { PACKAGE_VERSION };
5
5
 
@@ -1 +1 @@
1
- {"version":3,"file":"version.js","names":[],"sources":["../../src/generated/version.ts"],"sourcesContent":["// This file is auto-generated. Do not edit manually.\nexport const PACKAGE_VERSION = '2.14.50';\n"],"mappings":";AACA,MAAa,kBAAkB"}
1
+ {"version":3,"file":"version.js","names":[],"sources":["../../src/generated/version.ts"],"sourcesContent":["// This file is auto-generated. Do not edit manually.\nexport const PACKAGE_VERSION = '2.14.51';\n"],"mappings":";AACA,MAAa,kBAAkB"}
@@ -1,7 +1,7 @@
1
1
  import { logger } from "../console/logger.js";
2
2
  import { gt } from "../utils/gt.js";
3
- import { hasPublishConfig } from "../utils/resolvePublish.js";
4
3
  import { PublishStep } from "./steps/PublishStep.js";
4
+ import { hasPublishConfig } from "../utils/resolvePublish.js";
5
5
  //#region src/workflows/publish.ts
6
6
  /**
7
7
  * Publishes files to the CDN if publish config exists and the publishMap is non-empty.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gt",
3
- "version": "2.14.50",
3
+ "version": "2.14.51",
4
4
  "main": "dist/index.js",
5
5
  "bin": "bin/main.js",
6
6
  "files": [