gt 2.14.65 → 2.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/dist/api/saveLocalEdits.js +1 -3
  3. package/dist/api/saveLocalEdits.js.map +1 -1
  4. package/dist/cli/base.js +4 -0
  5. package/dist/cli/base.js.map +1 -1
  6. package/dist/cli/inline.js +1 -3
  7. package/dist/cli/inline.js.map +1 -1
  8. package/dist/console/logger.d.ts +13 -0
  9. package/dist/console/logger.js +35 -8
  10. package/dist/console/logger.js.map +1 -1
  11. package/dist/console/logging.js +4 -2
  12. package/dist/console/logging.js.map +1 -1
  13. package/dist/generated/version.d.ts +1 -1
  14. package/dist/generated/version.js +1 -1
  15. package/dist/generated/version.js.map +1 -1
  16. package/dist/react/jsx/evaluateJsx.js +1 -1
  17. package/dist/react/jsx/evaluateJsx.js.map +1 -1
  18. package/dist/workflows/download.js +3 -9
  19. package/dist/workflows/download.js.map +1 -1
  20. package/dist/workflows/enqueue.js +0 -2
  21. package/dist/workflows/enqueue.js.map +1 -1
  22. package/dist/workflows/publish.js +1 -3
  23. package/dist/workflows/publish.js.map +1 -1
  24. package/dist/workflows/setupProject.js +0 -3
  25. package/dist/workflows/setupProject.js.map +1 -1
  26. package/dist/workflows/stage.js +3 -13
  27. package/dist/workflows/stage.js.map +1 -1
  28. package/dist/workflows/steps/BranchStep.d.ts +1 -3
  29. package/dist/workflows/steps/BranchStep.js +1 -4
  30. package/dist/workflows/steps/BranchStep.js.map +1 -1
  31. package/dist/workflows/steps/DownloadStep.d.ts +1 -3
  32. package/dist/workflows/steps/DownloadStep.js +1 -4
  33. package/dist/workflows/steps/DownloadStep.js.map +1 -1
  34. package/dist/workflows/steps/EnqueueStep.d.ts +1 -5
  35. package/dist/workflows/steps/EnqueueStep.js +9 -19
  36. package/dist/workflows/steps/EnqueueStep.js.map +1 -1
  37. package/dist/workflows/steps/PollJobsStep.d.ts +1 -3
  38. package/dist/workflows/steps/PollJobsStep.js +1 -4
  39. package/dist/workflows/steps/PollJobsStep.js.map +1 -1
  40. package/dist/workflows/steps/PublishStep.d.ts +1 -3
  41. package/dist/workflows/steps/PublishStep.js +1 -4
  42. package/dist/workflows/steps/PublishStep.js.map +1 -1
  43. package/dist/workflows/steps/SetupStep.d.ts +1 -6
  44. package/dist/workflows/steps/SetupStep.js +14 -41
  45. package/dist/workflows/steps/SetupStep.js.map +1 -1
  46. package/dist/workflows/steps/TagStep.d.ts +1 -4
  47. package/dist/workflows/steps/TagStep.js +4 -9
  48. package/dist/workflows/steps/TagStep.js.map +1 -1
  49. package/dist/workflows/steps/UploadSourcesStep.d.ts +1 -7
  50. package/dist/workflows/steps/UploadSourcesStep.js +4 -8
  51. package/dist/workflows/steps/UploadSourcesStep.js.map +1 -1
  52. package/dist/workflows/steps/UploadTranslationsStep.d.ts +1 -4
  53. package/dist/workflows/steps/UploadTranslationsStep.js +6 -11
  54. package/dist/workflows/steps/UploadTranslationsStep.js.map +1 -1
  55. package/dist/workflows/steps/UserEditDiffsStep.d.ts +1 -5
  56. package/dist/workflows/steps/UserEditDiffsStep.js +3 -11
  57. package/dist/workflows/steps/UserEditDiffsStep.js.map +1 -1
  58. package/dist/workflows/upload.js +1 -6
  59. package/dist/workflows/upload.js.map +1 -1
  60. package/package.json +6 -6
  61. package/dist/workflows/steps/WorkflowStep.d.ts +0 -4
  62. package/dist/workflows/steps/WorkflowStep.js +0 -6
  63. package/dist/workflows/steps/WorkflowStep.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"logging.js","names":[],"sources":["../../src/console/logging.ts"],"sourcesContent":["import {\n text,\n select,\n confirm,\n isCancel,\n cancel,\n multiselect,\n} from '@clack/prompts';\nimport type { Option } from '@clack/prompts';\nimport chalk from 'chalk';\nimport { getCLIVersion } from '../utils/packageJson.js';\nimport { logger } from './logger.js';\nimport { TEMPLATE_FILE_NAME } from '../utils/constants.js';\nimport { FileToUpload } from 'generaltranslation/types';\nimport { endTerminalSession, shouldUseInkPrompts } from './terminalSession.js';\nimport {\n parseLocaleList,\n validateLocale,\n validateLocaleList,\n} from './promptParsing.js';\n\nfunction cancelPromptAndExit(message: string): never {\n endTerminalSession();\n cancel(message);\n return exitSync(0);\n}\n\nasync function loadInkPrompts() {\n return import('./inkPrompts.js');\n}\n\nasync function runInkPrompt<T>(\n prompt: (prompts: Awaited<ReturnType<typeof loadInkPrompts>>) => Promise<{\n value?: T;\n cancelled: boolean;\n }>,\n cancelMessage = 'Operation cancelled'\n) {\n const result = await prompt(await loadInkPrompts());\n if (result.cancelled) {\n return cancelPromptAndExit(cancelMessage);\n }\n return result.value;\n}\n\n/**\n * Strip ANSI escape codes from a string (e.g., chalk color codes)\n */\nexport function stripAnsi(str: string): string {\n // eslint-disable-next-line no-control-regex, no-useless-escape\n return str.replace(/\\x1B\\[[0-9;]*m/g, '');\n}\n\nexport function logErrorAndExit(message: string): never {\n logger.error(message);\n return exitSync(1);\n}\n\nexport function exitSync(code: number): never {\n // Flush logs before exit\n logger.flush();\n process.exit(code);\n}\n\n// GT specific logging\nexport function displayHeader(introString?: string) {\n displayAsciiTitle();\n displayInitializingText();\n\n if (introString) {\n logger.startCommand(introString);\n }\n}\n\nfunction displayAsciiTitle() {\n // eslint-disable-next-line no-console\n console.log(\n chalk.cyan(\n `\\n @@@@@@@@@@@@@@@@@@@@@@\n @@ @@@@@@@@@@@@ @@@@@@@\n @@ @@@ @ @\n@@ @@ @ @\n@@ @ @@@@@ @ @\n@@ @@ @@@ @ @ @\n @@ @@ @ @ @ @\n @@ @@@@@@@ @ @ @\n @@@@@@@@@ @ @`\n )\n );\n}\n\nfunction displayInitializingText() {\n const version = getCLIVersion();\n // eslint-disable-next-line no-console\n console.log(\n `\\n${chalk.bold.blue('General Translation, Inc.')}\n${chalk.dim('https://generaltranslation.com/docs')}\n${chalk.dim(`CLI Version: ${version}\\n`)}`\n );\n}\n\nexport function displayProjectId(projectId: string) {\n logger.message(\n chalk.dim(`Project ID: ${chalk.bold(projectId)}`),\n chalk.cyan('~')\n );\n}\n\nexport function displayResolvedPaths(resolvedPaths: [string, string][]) {\n const paths = resolvedPaths.map(([key, resolvedPath]) => {\n return chalk.dim(`'${chalk.white(key)}' → '${chalk.green(resolvedPath)}'`);\n });\n logger.step(`Resolved path aliases:\\n${paths.join('\\n')}`);\n}\n\nexport function displayCreatedConfigFile(configFilepath: string) {\n logger.step(`Created config file ${chalk.cyan(configFilepath)}`);\n}\n\nexport function displayUpdatedConfigFile(configFilepath: string) {\n logger.success(`Updated config file ${chalk.cyan(configFilepath)}`);\n}\n\nexport function displayUpdatedVersionsFile(versionFilepath: string) {\n logger.success(`Updated versions file ${chalk.cyan(versionFilepath)}`);\n}\n\n// Input prompts\nexport async function promptText({\n message,\n defaultValue,\n validate,\n}: {\n message: string;\n defaultValue?: string;\n validate?: (value: string) => boolean | string;\n}) {\n if (shouldUseInkPrompts()) {\n return (\n (await runInkPrompt<string>((prompts) =>\n prompts.inkPromptText({ message, defaultValue, validate })\n )) ?? ''\n );\n }\n\n const result = await text({\n message,\n placeholder: defaultValue,\n validate: validate\n ? (value) => {\n const validation = validate(value || '');\n return validation === true ? undefined : validation.toString();\n }\n : undefined,\n });\n\n if (isCancel(result)) {\n cancel('Operation cancelled');\n return exitSync(0);\n }\n\n return result;\n}\n\nexport async function promptLocale({\n message,\n defaultValue,\n}: {\n message: string;\n defaultValue?: string;\n}) {\n if (shouldUseInkPrompts()) {\n return (\n (await runInkPrompt<string>((prompts) =>\n prompts.inkPromptLocale({ message, defaultValue })\n )) ?? ''\n );\n }\n\n return promptText({\n message,\n defaultValue,\n validate: validateLocale,\n });\n}\n\nexport async function promptLocaleList({\n message,\n defaultValue,\n required = true,\n}: {\n message: string;\n defaultValue?: string[];\n required?: boolean;\n}) {\n if (shouldUseInkPrompts()) {\n return (\n (await runInkPrompt<string[]>((prompts) =>\n prompts.inkPromptLocaleMulti({\n message,\n defaultValue,\n required,\n })\n )) ?? []\n );\n }\n\n return promptText({\n message,\n defaultValue: defaultValue?.join(' '),\n validate: validateLocaleList,\n }).then(parseLocaleList);\n}\n\nexport async function promptGlobPatterns({\n label,\n message,\n defaultValue,\n}: {\n label: string;\n message: string;\n defaultValue?: string;\n}) {\n if (shouldUseInkPrompts()) {\n return (\n (await runInkPrompt<string>((prompts) =>\n prompts.inkPromptGlob({ label, message, defaultValue })\n )) ?? ''\n );\n }\n\n return promptText({\n message,\n defaultValue,\n });\n}\n\nexport async function promptSelect<T>({\n message,\n options,\n defaultValue,\n}: {\n message: string;\n options: Array<{ value: T; label: string; hint?: string }>;\n defaultValue?: T;\n}) {\n if (shouldUseInkPrompts()) {\n return (await runInkPrompt<T>((prompts) =>\n prompts.inkPromptSelect({ message, options, defaultValue })\n )) as T;\n }\n\n // Convert options to the format expected by clack\n const clackOptions = options.map((opt) => ({\n value: opt.value,\n label: opt.label,\n hint: opt.hint,\n })) as Option<T>[];\n\n const result = await select({\n message,\n options: clackOptions,\n initialValue: defaultValue,\n });\n\n if (isCancel(result)) {\n cancel('Operation cancelled');\n return exitSync(0);\n }\n\n return result as T;\n}\n\nexport async function promptMultiSelect<T extends string>({\n message,\n options,\n required = true,\n}: {\n message: string;\n options: Array<{ value: T; label: string; hint?: string }>;\n required?: boolean;\n}) {\n if (shouldUseInkPrompts()) {\n return (\n (await runInkPrompt<Array<T>>((prompts) =>\n prompts.inkPromptMultiSelect({\n message,\n options,\n required,\n })\n )) ?? []\n );\n }\n\n // Convert options to the format expected by clack\n const clackOptions = options.map((opt) => ({\n value: opt.value,\n label: opt.label,\n hint: opt.hint,\n })) as Option<T>[];\n\n const result = await multiselect({\n message,\n options: clackOptions,\n required,\n });\n\n if (isCancel(result)) {\n cancel('Operation cancelled');\n return exitSync(0);\n }\n\n return result as Array<T>;\n}\n\nexport async function promptConfirm({\n message,\n defaultValue = true,\n cancelMessage = 'Operation cancelled',\n}: {\n message: string;\n defaultValue?: boolean;\n cancelMessage?: string;\n}) {\n if (shouldUseInkPrompts()) {\n return (\n (await runInkPrompt<boolean>(\n (prompts) => prompts.inkPromptConfirm({ message, defaultValue }),\n cancelMessage\n )) ?? defaultValue\n );\n }\n\n const result = await confirm({\n message,\n initialValue: defaultValue,\n });\n\n if (isCancel(result)) {\n cancel(cancelMessage);\n return exitSync(0);\n }\n\n return result;\n}\n\n// Warning display functions\nexport function warnApiKeyInConfig(optionsFilepath: string) {\n logger.warn(\n `Found ${chalk.cyan('apiKey')} in \"${chalk.green(optionsFilepath)}\". ` +\n chalk.white(\n 'Your API key is exposed! Remove it from the file and include it as an environment variable.'\n )\n );\n}\n\nexport function warnVariableProp(\n file: string,\n attrName: string,\n value: string\n) {\n logger.warn(\n `Found ${chalk.green('<T>')} component in ${chalk.cyan(file)} with variable ${attrName}: \"${chalk.white(value)}\". ` +\n `Change \"${attrName}\" to ensure this content is translated.`\n );\n}\n\nexport function warnNoId(file: string) {\n logger.warn(\n `Found ${chalk.green('<T>')} component in ${chalk.cyan(file)} with no id. ` +\n chalk.white('Add an id to ensure the content is translated.')\n );\n}\n\nexport function warnHasUnwrappedExpression(\n file: string,\n id: string,\n unwrappedExpressions: string[]\n) {\n logger.warn(\n `${chalk.green('<T>')} with id \"${id}\" in ${chalk.cyan(file)} has children: ${unwrappedExpressions.join(', ')} that could change at runtime. ` +\n chalk.white('Use a variable component like ') +\n chalk.green('<Var>') +\n chalk.white(' (') +\n chalk.blue('https://generaltranslation.com/docs') +\n chalk.white(') to translate this properly.')\n );\n}\n\nexport function warnTemplateLiteral(file: string, value: string) {\n logger.warn(\n `Found template literal with quasis (${value}) in ${chalk.cyan(file)}. ` +\n chalk.white(\n 'Change the template literal to a string to ensure this content is translated.'\n )\n );\n}\n\nexport function warnTernary(file: string) {\n logger.warn(\n `Found ternary expression in ${chalk.cyan(file)}. ` +\n chalk.white('A Branch component may be more appropriate here.')\n );\n}\n\nexport function warnDeprecatedField(\n deprecatedField: string,\n replacement: string\n) {\n logger.warn(\n `${chalk.green(deprecatedField)} is deprecated. ` +\n chalk.white(`Use ${chalk.green(replacement)} instead.`)\n );\n}\n\n/**\n * Helper: Log all collected files\n */\nexport function logCollectedFiles(\n files: Pick<FileToUpload, 'fileName'>[],\n reactComponents?: number\n): void {\n logger.message(\n chalk.cyan('Files found in project:') +\n '\\n' +\n files\n .map((file) => {\n if (file.fileName === TEMPLATE_FILE_NAME) {\n return `- <React Elements>${reactComponents ? ` (${reactComponents})` : ''}`;\n }\n return `- ${file.fileName}`;\n })\n .join('\\n')\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"logging.js","names":[],"sources":["../../src/console/logging.ts"],"sourcesContent":["import {\n text,\n select,\n confirm,\n isCancel,\n cancel,\n multiselect,\n} from '@clack/prompts';\nimport type { Option } from '@clack/prompts';\nimport chalk from 'chalk';\nimport { getCLIVersion } from '../utils/packageJson.js';\nimport { logger } from './logger.js';\nimport { TEMPLATE_FILE_NAME } from '../utils/constants.js';\nimport { FileToUpload } from 'generaltranslation/types';\nimport { endTerminalSession, shouldUseInkPrompts } from './terminalSession.js';\nimport {\n parseLocaleList,\n validateLocale,\n validateLocaleList,\n} from './promptParsing.js';\n\nfunction cancelPromptAndExit(message: string): never {\n endTerminalSession();\n cancel(message);\n return exitSync(0);\n}\n\nasync function loadInkPrompts() {\n return import('./inkPrompts.js');\n}\n\nasync function runInkPrompt<T>(\n prompt: (prompts: Awaited<ReturnType<typeof loadInkPrompts>>) => Promise<{\n value?: T;\n cancelled: boolean;\n }>,\n cancelMessage = 'Operation cancelled'\n) {\n const result = await prompt(await loadInkPrompts());\n if (result.cancelled) {\n return cancelPromptAndExit(cancelMessage);\n }\n return result.value;\n}\n\n/**\n * Strip ANSI escape codes from a string (e.g., chalk color codes)\n */\nexport function stripAnsi(str: string): string {\n // eslint-disable-next-line no-control-regex, no-useless-escape\n return str.replace(/\\x1B\\[[0-9;]*m/g, '');\n}\n\nexport function logErrorAndExit(message: string): never {\n logger.error(message);\n return exitSync(1);\n}\n\nexport function exitSync(code: number): never {\n // Flush logs before exit\n logger.flush();\n process.exit(code);\n}\n\n// GT specific logging\nexport function displayHeader(introString?: string) {\n // The ASCII banner is pure chatter and writes to console directly, bypassing\n // the logger, so gate it here to honor --quiet. startCommand stays outside\n // the gate: it is quiet-aware itself and must still run so the file log\n // gets its [START] marker.\n if (!logger.isQuiet()) {\n displayAsciiTitle();\n displayInitializingText();\n }\n\n if (introString) {\n logger.startCommand(introString);\n }\n}\n\nfunction displayAsciiTitle() {\n // eslint-disable-next-line no-console\n console.log(\n chalk.cyan(\n `\\n @@@@@@@@@@@@@@@@@@@@@@\n @@ @@@@@@@@@@@@ @@@@@@@\n @@ @@@ @ @\n@@ @@ @ @\n@@ @ @@@@@ @ @\n@@ @@ @@@ @ @ @\n @@ @@ @ @ @ @\n @@ @@@@@@@ @ @ @\n @@@@@@@@@ @ @`\n )\n );\n}\n\nfunction displayInitializingText() {\n const version = getCLIVersion();\n // eslint-disable-next-line no-console\n console.log(\n `\\n${chalk.bold.blue('General Translation, Inc.')}\n${chalk.dim('https://generaltranslation.com/docs')}\n${chalk.dim(`CLI Version: ${version}\\n`)}`\n );\n}\n\nexport function displayProjectId(projectId: string) {\n logger.message(\n chalk.dim(`Project ID: ${chalk.bold(projectId)}`),\n chalk.cyan('~')\n );\n}\n\nexport function displayResolvedPaths(resolvedPaths: [string, string][]) {\n const paths = resolvedPaths.map(([key, resolvedPath]) => {\n return chalk.dim(`'${chalk.white(key)}' → '${chalk.green(resolvedPath)}'`);\n });\n logger.step(`Resolved path aliases:\\n${paths.join('\\n')}`);\n}\n\nexport function displayCreatedConfigFile(configFilepath: string) {\n logger.step(`Created config file ${chalk.cyan(configFilepath)}`);\n}\n\nexport function displayUpdatedConfigFile(configFilepath: string) {\n logger.success(`Updated config file ${chalk.cyan(configFilepath)}`);\n}\n\nexport function displayUpdatedVersionsFile(versionFilepath: string) {\n logger.success(`Updated versions file ${chalk.cyan(versionFilepath)}`);\n}\n\n// Input prompts\nexport async function promptText({\n message,\n defaultValue,\n validate,\n}: {\n message: string;\n defaultValue?: string;\n validate?: (value: string) => boolean | string;\n}) {\n if (shouldUseInkPrompts()) {\n return (\n (await runInkPrompt<string>((prompts) =>\n prompts.inkPromptText({ message, defaultValue, validate })\n )) ?? ''\n );\n }\n\n const result = await text({\n message,\n placeholder: defaultValue,\n validate: validate\n ? (value) => {\n const validation = validate(value || '');\n return validation === true ? undefined : validation.toString();\n }\n : undefined,\n });\n\n if (isCancel(result)) {\n cancel('Operation cancelled');\n return exitSync(0);\n }\n\n return result;\n}\n\nexport async function promptLocale({\n message,\n defaultValue,\n}: {\n message: string;\n defaultValue?: string;\n}) {\n if (shouldUseInkPrompts()) {\n return (\n (await runInkPrompt<string>((prompts) =>\n prompts.inkPromptLocale({ message, defaultValue })\n )) ?? ''\n );\n }\n\n return promptText({\n message,\n defaultValue,\n validate: validateLocale,\n });\n}\n\nexport async function promptLocaleList({\n message,\n defaultValue,\n required = true,\n}: {\n message: string;\n defaultValue?: string[];\n required?: boolean;\n}) {\n if (shouldUseInkPrompts()) {\n return (\n (await runInkPrompt<string[]>((prompts) =>\n prompts.inkPromptLocaleMulti({\n message,\n defaultValue,\n required,\n })\n )) ?? []\n );\n }\n\n return promptText({\n message,\n defaultValue: defaultValue?.join(' '),\n validate: validateLocaleList,\n }).then(parseLocaleList);\n}\n\nexport async function promptGlobPatterns({\n label,\n message,\n defaultValue,\n}: {\n label: string;\n message: string;\n defaultValue?: string;\n}) {\n if (shouldUseInkPrompts()) {\n return (\n (await runInkPrompt<string>((prompts) =>\n prompts.inkPromptGlob({ label, message, defaultValue })\n )) ?? ''\n );\n }\n\n return promptText({\n message,\n defaultValue,\n });\n}\n\nexport async function promptSelect<T>({\n message,\n options,\n defaultValue,\n}: {\n message: string;\n options: Array<{ value: T; label: string; hint?: string }>;\n defaultValue?: T;\n}) {\n if (shouldUseInkPrompts()) {\n return (await runInkPrompt<T>((prompts) =>\n prompts.inkPromptSelect({ message, options, defaultValue })\n )) as T;\n }\n\n // Convert options to the format expected by clack\n const clackOptions = options.map((opt) => ({\n value: opt.value,\n label: opt.label,\n hint: opt.hint,\n })) as Option<T>[];\n\n const result = await select({\n message,\n options: clackOptions,\n initialValue: defaultValue,\n });\n\n if (isCancel(result)) {\n cancel('Operation cancelled');\n return exitSync(0);\n }\n\n return result as T;\n}\n\nexport async function promptMultiSelect<T extends string>({\n message,\n options,\n required = true,\n}: {\n message: string;\n options: Array<{ value: T; label: string; hint?: string }>;\n required?: boolean;\n}) {\n if (shouldUseInkPrompts()) {\n return (\n (await runInkPrompt<Array<T>>((prompts) =>\n prompts.inkPromptMultiSelect({\n message,\n options,\n required,\n })\n )) ?? []\n );\n }\n\n // Convert options to the format expected by clack\n const clackOptions = options.map((opt) => ({\n value: opt.value,\n label: opt.label,\n hint: opt.hint,\n })) as Option<T>[];\n\n const result = await multiselect({\n message,\n options: clackOptions,\n required,\n });\n\n if (isCancel(result)) {\n cancel('Operation cancelled');\n return exitSync(0);\n }\n\n return result as Array<T>;\n}\n\nexport async function promptConfirm({\n message,\n defaultValue = true,\n cancelMessage = 'Operation cancelled',\n}: {\n message: string;\n defaultValue?: boolean;\n cancelMessage?: string;\n}) {\n if (shouldUseInkPrompts()) {\n return (\n (await runInkPrompt<boolean>(\n (prompts) => prompts.inkPromptConfirm({ message, defaultValue }),\n cancelMessage\n )) ?? defaultValue\n );\n }\n\n const result = await confirm({\n message,\n initialValue: defaultValue,\n });\n\n if (isCancel(result)) {\n cancel(cancelMessage);\n return exitSync(0);\n }\n\n return result;\n}\n\n// Warning display functions\nexport function warnApiKeyInConfig(optionsFilepath: string) {\n logger.warn(\n `Found ${chalk.cyan('apiKey')} in \"${chalk.green(optionsFilepath)}\". ` +\n chalk.white(\n 'Your API key is exposed! Remove it from the file and include it as an environment variable.'\n )\n );\n}\n\nexport function warnVariableProp(\n file: string,\n attrName: string,\n value: string\n) {\n logger.warn(\n `Found ${chalk.green('<T>')} component in ${chalk.cyan(file)} with variable ${attrName}: \"${chalk.white(value)}\". ` +\n `Change \"${attrName}\" to ensure this content is translated.`\n );\n}\n\nexport function warnNoId(file: string) {\n logger.warn(\n `Found ${chalk.green('<T>')} component in ${chalk.cyan(file)} with no id. ` +\n chalk.white('Add an id to ensure the content is translated.')\n );\n}\n\nexport function warnHasUnwrappedExpression(\n file: string,\n id: string,\n unwrappedExpressions: string[]\n) {\n logger.warn(\n `${chalk.green('<T>')} with id \"${id}\" in ${chalk.cyan(file)} has children: ${unwrappedExpressions.join(', ')} that could change at runtime. ` +\n chalk.white('Use a variable component like ') +\n chalk.green('<Var>') +\n chalk.white(' (') +\n chalk.blue('https://generaltranslation.com/docs') +\n chalk.white(') to translate this properly.')\n );\n}\n\nexport function warnTemplateLiteral(file: string, value: string) {\n logger.warn(\n `Found template literal with quasis (${value}) in ${chalk.cyan(file)}. ` +\n chalk.white(\n 'Change the template literal to a string to ensure this content is translated.'\n )\n );\n}\n\nexport function warnTernary(file: string) {\n logger.warn(\n `Found ternary expression in ${chalk.cyan(file)}. ` +\n chalk.white('A Branch component may be more appropriate here.')\n );\n}\n\nexport function warnDeprecatedField(\n deprecatedField: string,\n replacement: string\n) {\n logger.warn(\n `${chalk.green(deprecatedField)} is deprecated. ` +\n chalk.white(`Use ${chalk.green(replacement)} instead.`)\n );\n}\n\n/**\n * Helper: Log all collected files\n */\nexport function logCollectedFiles(\n files: Pick<FileToUpload, 'fileName'>[],\n reactComponents?: number\n): void {\n logger.message(\n chalk.cyan('Files found in project:') +\n '\\n' +\n files\n .map((file) => {\n if (file.fileName === TEMPLATE_FILE_NAME) {\n return `- <React Elements>${reactComponents ? ` (${reactComponents})` : ''}`;\n }\n return `- ${file.fileName}`;\n })\n .join('\\n')\n );\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- export declare const PACKAGE_VERSION = "2.14.65";
1
+ export declare const PACKAGE_VERSION = "2.15.0";
@@ -1,5 +1,5 @@
1
1
  //#region src/generated/version.ts
2
- const PACKAGE_VERSION = "2.14.65";
2
+ const PACKAGE_VERSION = "2.15.0";
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.65';\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.15.0';\n"],"mappings":";AACA,MAAa,kBAAkB"}
@@ -1,5 +1,5 @@
1
1
  import * as t from "@babel/types";
2
- import { parse } from "@formatjs/icu-messageformat-parser";
2
+ import { parse } from "@generaltranslation/icu";
3
3
  //#region src/react/jsx/evaluateJsx.ts
4
4
  const MEANINGFUL_REGEX = /[\p{L}\p{N}]/u;
5
5
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"evaluateJsx.js","names":[],"sources":["../../../src/react/jsx/evaluateJsx.ts"],"sourcesContent":["import * as t from '@babel/types';\nimport { parse } from '@formatjs/icu-messageformat-parser';\n\nconst MEANINGFUL_REGEX = /[\\p{L}\\p{N}]/u;\n\n/**\n * Checks if a node is meaningful. Does not recurse into children.\n * @param node - The node to check\n * @returns Whether the node is meaningful\n */\nexport function isMeaningful(node: t.Node): boolean {\n if (t.isStringLiteral(node) || t.isJSXText(node)) {\n return MEANINGFUL_REGEX.test(node.value);\n }\n // Handle template literals without expressions\n if (t.isTemplateLiteral(node) && node.expressions.length === 0) {\n return MEANINGFUL_REGEX.test(node.quasis[0].value.raw);\n }\n if (t.isJSXExpressionContainer(node)) {\n const value = isStaticExpression(node.expression);\n if (value.isStatic && value.value) {\n return MEANINGFUL_REGEX.test(value.value);\n }\n }\n if (t.isBinaryExpression(node)) {\n if (node.operator === '+') {\n return isMeaningful(node.left) || isMeaningful(node.right);\n }\n }\n return false;\n}\n\nexport function isStaticExpression(\n expr: t.Expression | t.JSXEmptyExpression,\n jsxStatic?: false\n): {\n isStatic: boolean;\n value?: string;\n};\nexport function isStaticExpression(\n expr: t.Expression | t.JSXEmptyExpression,\n jsxStatic?: true\n): {\n isStatic: boolean;\n value?: string | boolean | null;\n};\nexport function isStaticExpression(\n expr: t.Expression | t.JSXEmptyExpression,\n jsxStatic?: boolean\n): {\n isStatic: boolean;\n value?: string | boolean | null;\n};\n/**\n * Checks if an expression is a static expression (does not contain any variables which could change at runtime).\n * @param expr - The expression to check\n * @param jsxStatic - Whether to return JSX-compatible values (boolean, null) in addition to strings\n * @returns An object containing the result of the static check\n */\nexport function isStaticExpression(\n expr: t.Expression | t.JSXEmptyExpression,\n jsxStatic = false\n): {\n isStatic: boolean;\n value?: string | boolean | null;\n} {\n // Handle empty expressions\n if (t.isJSXEmptyExpression(expr)) {\n return { isStatic: true, value: '' };\n }\n\n // Handle direct string literals\n if (t.isStringLiteral(expr)) {\n return { isStatic: true, value: expr.value };\n }\n\n // Handle template literals without expressions\n if (t.isTemplateLiteral(expr) && expr.expressions.length === 0) {\n return {\n isStatic: true,\n value: jsxStatic ? expr.quasis[0].value.cooked : expr.quasis[0].value.raw,\n };\n }\n\n // Binary expressions are not derivable\n if (t.isBinaryExpression(expr)) {\n // Not a derivable expression\n return { isStatic: false };\n }\n\n // Handle parenthesized expressions\n if (t.isParenthesizedExpression(expr)) {\n return isStaticExpression(expr.expression, jsxStatic);\n }\n\n // Handle numeric literals by converting them to strings\n if (t.isNumericLiteral(expr)) {\n return { isStatic: true, value: String(expr.value) };\n }\n\n // Handle unary expressions by converting them to strings\n if (t.isUnaryExpression(expr)) {\n let value: string;\n let operator = '';\n if (expr.operator === '-') {\n operator = expr.operator;\n }\n if (t.isNumericLiteral(expr.argument)) {\n if (expr.argument.value === 0) {\n value = '0';\n } else {\n value = operator + expr.argument.value.toString();\n }\n } else {\n // invalid\n return { isStatic: false };\n }\n\n return { isStatic: true, value };\n }\n\n // Handle boolean literals by converting them to strings\n if (t.isBooleanLiteral(expr)) {\n return {\n isStatic: true,\n value: jsxStatic ? expr.value : String(expr.value),\n };\n }\n\n // Handle null literal\n if (t.isNullLiteral(expr)) {\n return { isStatic: true, value: jsxStatic ? null : 'null' };\n }\n\n // Not a derivable expression\n return { isStatic: false };\n}\n\n/**\n * Checks if an expression is a static value (a string, number, or template literal).\n * @param expr - The expression to check\n * @returns Whether the expression is a static value\n */\nexport function isStaticValue(\n expr: t.Expression | t.JSXEmptyExpression\n): boolean {\n if (t.isStringLiteral(expr)) {\n return true;\n }\n if (t.isNumericLiteral(expr)) {\n return true;\n }\n if (t.isTemplateLiteral(expr)) {\n return true;\n }\n return false;\n}\n\n/**\n * Checks if a string is a valid ICU message format.\n * @param string - The string to check\n * @returns Whether the string is a valid ICU message format\n */\nexport function isValidIcu(string: string): {\n isValid: boolean;\n error?: string;\n} {\n try {\n parse(string);\n } catch (error) {\n return {\n isValid: false,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n return { isValid: true };\n}\n"],"mappings":";;;AAGA,MAAM,mBAAmB;;;;;;AAOzB,SAAgB,aAAa,MAAuB;AAClD,KAAI,EAAE,gBAAgB,KAAK,IAAI,EAAE,UAAU,KAAK,CAC9C,QAAO,iBAAiB,KAAK,KAAK,MAAM;AAG1C,KAAI,EAAE,kBAAkB,KAAK,IAAI,KAAK,YAAY,WAAW,EAC3D,QAAO,iBAAiB,KAAK,KAAK,OAAO,GAAG,MAAM,IAAI;AAExD,KAAI,EAAE,yBAAyB,KAAK,EAAE;EACpC,MAAM,QAAQ,mBAAmB,KAAK,WAAW;AACjD,MAAI,MAAM,YAAY,MAAM,MAC1B,QAAO,iBAAiB,KAAK,MAAM,MAAM;;AAG7C,KAAI,EAAE,mBAAmB,KAAK;MACxB,KAAK,aAAa,IACpB,QAAO,aAAa,KAAK,KAAK,IAAI,aAAa,KAAK,MAAM;;AAG9D,QAAO;;;;;;;;AA8BT,SAAgB,mBACd,MACA,YAAY,OAIZ;AAEA,KAAI,EAAE,qBAAqB,KAAK,CAC9B,QAAO;EAAE,UAAU;EAAM,OAAO;EAAI;AAItC,KAAI,EAAE,gBAAgB,KAAK,CACzB,QAAO;EAAE,UAAU;EAAM,OAAO,KAAK;EAAO;AAI9C,KAAI,EAAE,kBAAkB,KAAK,IAAI,KAAK,YAAY,WAAW,EAC3D,QAAO;EACL,UAAU;EACV,OAAO,YAAY,KAAK,OAAO,GAAG,MAAM,SAAS,KAAK,OAAO,GAAG,MAAM;EACvE;AAIH,KAAI,EAAE,mBAAmB,KAAK,CAE5B,QAAO,EAAE,UAAU,OAAO;AAI5B,KAAI,EAAE,0BAA0B,KAAK,CACnC,QAAO,mBAAmB,KAAK,YAAY,UAAU;AAIvD,KAAI,EAAE,iBAAiB,KAAK,CAC1B,QAAO;EAAE,UAAU;EAAM,OAAO,OAAO,KAAK,MAAM;EAAE;AAItD,KAAI,EAAE,kBAAkB,KAAK,EAAE;EAC7B,IAAI;EACJ,IAAI,WAAW;AACf,MAAI,KAAK,aAAa,IACpB,YAAW,KAAK;AAElB,MAAI,EAAE,iBAAiB,KAAK,SAAS,CACnC,KAAI,KAAK,SAAS,UAAU,EAC1B,SAAQ;MAER,SAAQ,WAAW,KAAK,SAAS,MAAM,UAAU;MAInD,QAAO,EAAE,UAAU,OAAO;AAG5B,SAAO;GAAE,UAAU;GAAM;GAAO;;AAIlC,KAAI,EAAE,iBAAiB,KAAK,CAC1B,QAAO;EACL,UAAU;EACV,OAAO,YAAY,KAAK,QAAQ,OAAO,KAAK,MAAM;EACnD;AAIH,KAAI,EAAE,cAAc,KAAK,CACvB,QAAO;EAAE,UAAU;EAAM,OAAO,YAAY,OAAO;EAAQ;AAI7D,QAAO,EAAE,UAAU,OAAO;;;;;;;AAQ5B,SAAgB,cACd,MACS;AACT,KAAI,EAAE,gBAAgB,KAAK,CACzB,QAAO;AAET,KAAI,EAAE,iBAAiB,KAAK,CAC1B,QAAO;AAET,KAAI,EAAE,kBAAkB,KAAK,CAC3B,QAAO;AAET,QAAO;;;;;;;AAQT,SAAgB,WAAW,QAGzB;AACA,KAAI;AACF,QAAM,OAAO;UACN,OAAO;AACd,SAAO;GACL,SAAS;GACT,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;GAC9D;;AAEH,QAAO,EAAE,SAAS,MAAM"}
1
+ {"version":3,"file":"evaluateJsx.js","names":[],"sources":["../../../src/react/jsx/evaluateJsx.ts"],"sourcesContent":["import * as t from '@babel/types';\nimport { parse } from '@generaltranslation/icu';\n\nconst MEANINGFUL_REGEX = /[\\p{L}\\p{N}]/u;\n\n/**\n * Checks if a node is meaningful. Does not recurse into children.\n * @param node - The node to check\n * @returns Whether the node is meaningful\n */\nexport function isMeaningful(node: t.Node): boolean {\n if (t.isStringLiteral(node) || t.isJSXText(node)) {\n return MEANINGFUL_REGEX.test(node.value);\n }\n // Handle template literals without expressions\n if (t.isTemplateLiteral(node) && node.expressions.length === 0) {\n return MEANINGFUL_REGEX.test(node.quasis[0].value.raw);\n }\n if (t.isJSXExpressionContainer(node)) {\n const value = isStaticExpression(node.expression);\n if (value.isStatic && value.value) {\n return MEANINGFUL_REGEX.test(value.value);\n }\n }\n if (t.isBinaryExpression(node)) {\n if (node.operator === '+') {\n return isMeaningful(node.left) || isMeaningful(node.right);\n }\n }\n return false;\n}\n\nexport function isStaticExpression(\n expr: t.Expression | t.JSXEmptyExpression,\n jsxStatic?: false\n): {\n isStatic: boolean;\n value?: string;\n};\nexport function isStaticExpression(\n expr: t.Expression | t.JSXEmptyExpression,\n jsxStatic?: true\n): {\n isStatic: boolean;\n value?: string | boolean | null;\n};\nexport function isStaticExpression(\n expr: t.Expression | t.JSXEmptyExpression,\n jsxStatic?: boolean\n): {\n isStatic: boolean;\n value?: string | boolean | null;\n};\n/**\n * Checks if an expression is a static expression (does not contain any variables which could change at runtime).\n * @param expr - The expression to check\n * @param jsxStatic - Whether to return JSX-compatible values (boolean, null) in addition to strings\n * @returns An object containing the result of the static check\n */\nexport function isStaticExpression(\n expr: t.Expression | t.JSXEmptyExpression,\n jsxStatic = false\n): {\n isStatic: boolean;\n value?: string | boolean | null;\n} {\n // Handle empty expressions\n if (t.isJSXEmptyExpression(expr)) {\n return { isStatic: true, value: '' };\n }\n\n // Handle direct string literals\n if (t.isStringLiteral(expr)) {\n return { isStatic: true, value: expr.value };\n }\n\n // Handle template literals without expressions\n if (t.isTemplateLiteral(expr) && expr.expressions.length === 0) {\n return {\n isStatic: true,\n value: jsxStatic ? expr.quasis[0].value.cooked : expr.quasis[0].value.raw,\n };\n }\n\n // Binary expressions are not derivable\n if (t.isBinaryExpression(expr)) {\n // Not a derivable expression\n return { isStatic: false };\n }\n\n // Handle parenthesized expressions\n if (t.isParenthesizedExpression(expr)) {\n return isStaticExpression(expr.expression, jsxStatic);\n }\n\n // Handle numeric literals by converting them to strings\n if (t.isNumericLiteral(expr)) {\n return { isStatic: true, value: String(expr.value) };\n }\n\n // Handle unary expressions by converting them to strings\n if (t.isUnaryExpression(expr)) {\n let value: string;\n let operator = '';\n if (expr.operator === '-') {\n operator = expr.operator;\n }\n if (t.isNumericLiteral(expr.argument)) {\n if (expr.argument.value === 0) {\n value = '0';\n } else {\n value = operator + expr.argument.value.toString();\n }\n } else {\n // invalid\n return { isStatic: false };\n }\n\n return { isStatic: true, value };\n }\n\n // Handle boolean literals by converting them to strings\n if (t.isBooleanLiteral(expr)) {\n return {\n isStatic: true,\n value: jsxStatic ? expr.value : String(expr.value),\n };\n }\n\n // Handle null literal\n if (t.isNullLiteral(expr)) {\n return { isStatic: true, value: jsxStatic ? null : 'null' };\n }\n\n // Not a derivable expression\n return { isStatic: false };\n}\n\n/**\n * Checks if an expression is a static value (a string, number, or template literal).\n * @param expr - The expression to check\n * @returns Whether the expression is a static value\n */\nexport function isStaticValue(\n expr: t.Expression | t.JSXEmptyExpression\n): boolean {\n if (t.isStringLiteral(expr)) {\n return true;\n }\n if (t.isNumericLiteral(expr)) {\n return true;\n }\n if (t.isTemplateLiteral(expr)) {\n return true;\n }\n return false;\n}\n\n/**\n * Checks if a string is a valid ICU message format.\n * @param string - The string to check\n * @returns Whether the string is a valid ICU message format\n */\nexport function isValidIcu(string: string): {\n isValid: boolean;\n error?: string;\n} {\n try {\n parse(string);\n } catch (error) {\n return {\n isValid: false,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n return { isValid: true };\n}\n"],"mappings":";;;AAGA,MAAM,mBAAmB;;;;;;AAOzB,SAAgB,aAAa,MAAuB;AAClD,KAAI,EAAE,gBAAgB,KAAK,IAAI,EAAE,UAAU,KAAK,CAC9C,QAAO,iBAAiB,KAAK,KAAK,MAAM;AAG1C,KAAI,EAAE,kBAAkB,KAAK,IAAI,KAAK,YAAY,WAAW,EAC3D,QAAO,iBAAiB,KAAK,KAAK,OAAO,GAAG,MAAM,IAAI;AAExD,KAAI,EAAE,yBAAyB,KAAK,EAAE;EACpC,MAAM,QAAQ,mBAAmB,KAAK,WAAW;AACjD,MAAI,MAAM,YAAY,MAAM,MAC1B,QAAO,iBAAiB,KAAK,MAAM,MAAM;;AAG7C,KAAI,EAAE,mBAAmB,KAAK;MACxB,KAAK,aAAa,IACpB,QAAO,aAAa,KAAK,KAAK,IAAI,aAAa,KAAK,MAAM;;AAG9D,QAAO;;;;;;;;AA8BT,SAAgB,mBACd,MACA,YAAY,OAIZ;AAEA,KAAI,EAAE,qBAAqB,KAAK,CAC9B,QAAO;EAAE,UAAU;EAAM,OAAO;EAAI;AAItC,KAAI,EAAE,gBAAgB,KAAK,CACzB,QAAO;EAAE,UAAU;EAAM,OAAO,KAAK;EAAO;AAI9C,KAAI,EAAE,kBAAkB,KAAK,IAAI,KAAK,YAAY,WAAW,EAC3D,QAAO;EACL,UAAU;EACV,OAAO,YAAY,KAAK,OAAO,GAAG,MAAM,SAAS,KAAK,OAAO,GAAG,MAAM;EACvE;AAIH,KAAI,EAAE,mBAAmB,KAAK,CAE5B,QAAO,EAAE,UAAU,OAAO;AAI5B,KAAI,EAAE,0BAA0B,KAAK,CACnC,QAAO,mBAAmB,KAAK,YAAY,UAAU;AAIvD,KAAI,EAAE,iBAAiB,KAAK,CAC1B,QAAO;EAAE,UAAU;EAAM,OAAO,OAAO,KAAK,MAAM;EAAE;AAItD,KAAI,EAAE,kBAAkB,KAAK,EAAE;EAC7B,IAAI;EACJ,IAAI,WAAW;AACf,MAAI,KAAK,aAAa,IACpB,YAAW,KAAK;AAElB,MAAI,EAAE,iBAAiB,KAAK,SAAS,CACnC,KAAI,KAAK,SAAS,UAAU,EAC1B,SAAQ;MAER,SAAQ,WAAW,KAAK,SAAS,MAAM,UAAU;MAInD,QAAO,EAAE,UAAU,OAAO;AAG5B,SAAO;GAAE,UAAU;GAAM;GAAO;;AAIlC,KAAI,EAAE,iBAAiB,KAAK,CAC1B,QAAO;EACL,UAAU;EACV,OAAO,YAAY,KAAK,QAAQ,OAAO,KAAK,MAAM;EACnD;AAIH,KAAI,EAAE,cAAc,KAAK,CACvB,QAAO;EAAE,UAAU;EAAM,OAAO,YAAY,OAAO;EAAQ;AAI7D,QAAO,EAAE,UAAU,OAAO;;;;;;;AAQ5B,SAAgB,cACd,MACS;AACT,KAAI,EAAE,gBAAgB,KAAK,CACzB,QAAO;AAET,KAAI,EAAE,iBAAiB,KAAK,CAC1B,QAAO;AAET,KAAI,EAAE,kBAAkB,KAAK,CAC3B,QAAO;AAET,QAAO;;;;;;;AAQT,SAAgB,WAAW,QAGzB;AACA,KAAI;AACF,QAAM,OAAO;UACN,OAAO;AACd,SAAO;GACL,SAAS;GACT,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;GAC9D;;AAEH,QAAO,EAAE,SAAS,MAAM"}
@@ -24,9 +24,7 @@ import path from "node:path";
24
24
  */
25
25
  async function runDownloadWorkflow({ fileVersionData, jobData, branchData, locales, timeoutDuration, resolveOutputPath, options, forceRetranslation, forceDownload }) {
26
26
  if (!branchData) {
27
- const branchStep = new BranchStep(gt, options);
28
- const branchResult = await branchStep.run();
29
- await branchStep.wait();
27
+ const branchResult = await new BranchStep(gt, options).run();
30
28
  if (!branchResult) return logErrorAndExit(branchResolutionError);
31
29
  branchData = branchResult;
32
30
  }
@@ -43,15 +41,13 @@ async function runDownloadWorkflow({ fileVersionData, jobData, branchData, local
43
41
  };
44
42
  let pollTimedOut = false;
45
43
  if (jobData) {
46
- const pollStep = new PollTranslationJobsStep(gt);
47
- const pollResult = await pollStep.run({
44
+ const pollResult = await new PollTranslationJobsStep(gt).run({
48
45
  fileTracker,
49
46
  fileQueryData,
50
47
  jobData,
51
48
  timeoutDuration,
52
49
  forceRetranslation
53
50
  });
54
- await pollStep.wait();
55
51
  if (pollResult.fileTracker.failed.size > 0) {
56
52
  logger.error(`${chalk.red(`${pollResult.fileTracker.failed.size} file(s) failed to translate:`)}\n${Array.from(pollResult.fileTracker.failed.entries()).map(([, value]) => `- ${value.fileName}`).join("\n")}`);
57
53
  for (const [, value] of pollResult.fileTracker.failed) recordWarning("failed_translation", value.fileName, `Failed to translate for locale ${value.locale}`);
@@ -69,13 +65,11 @@ async function runDownloadWorkflow({ fileVersionData, jobData, branchData, local
69
65
  resolveOutputPath,
70
66
  options
71
67
  });
72
- const downloadStep = new DownloadTranslationsStep(gt, settingsForBranch);
73
- const downloadResult = await downloadStep.run({
68
+ const downloadResult = await new DownloadTranslationsStep(gt, settingsForBranch).run({
74
69
  fileTracker,
75
70
  resolveOutputPath,
76
71
  forceDownload
77
72
  });
78
- await downloadStep.wait();
79
73
  if (pollTimedOut) return false;
80
74
  return downloadResult;
81
75
  }
@@ -1 +1 @@
1
- {"version":3,"file":"download.js","names":[],"sources":["../../src/workflows/download.ts"],"sourcesContent":["import path from 'node:path';\nimport { Settings } from '../types/index.js';\nimport { gt } from '../utils/gt.js';\nimport { EnqueueFilesResult } from 'generaltranslation/types';\nimport { clearLocaleDirs } from '../fs/clearLocaleDirs.js';\nimport {\n FileStatusTracker,\n PollTranslationJobsStep,\n} from './steps/PollJobsStep.js';\nimport { DownloadTranslationsStep } from './steps/DownloadStep.js';\nimport { BranchData } from '../types/branch.js';\nimport { branchResolutionError } from '../console/index.js';\nimport { logErrorAndExit } from '../console/logging.js';\nimport { logger } from '../console/logger.js';\nimport { recordWarning } from '../state/translateWarnings.js';\nimport { BranchStep } from './steps/BranchStep.js';\nimport { FileProperties } from '../types/files.js';\nimport chalk from 'chalk';\n\nexport type FileTranslationData = {\n [fileId: string]: {\n versionId: string;\n fileName: string;\n /** Source component count for GTJSON files */\n componentCount?: number;\n };\n};\n\n/**\n * Checks the status of translations and downloads them using a workflow pattern\n * @param fileVersionData - Mapping of file IDs to their version and name information\n * @param jobData - Optional job data from enqueue operation\n * @param locales - The locales to wait for\n * @param timeoutDuration - The timeout duration for the wait in seconds\n * @param resolveOutputPath - Function to resolve the output path for a given source path and locale\n * @param options - Settings configuration\n * @param forceRetranslation - Whether to force retranslation\n * @param forceDownload - Whether to force download even if file exists\n * @returns True if all translations are downloaded successfully, false otherwise\n */\nexport async function runDownloadWorkflow({\n fileVersionData,\n jobData,\n branchData,\n locales,\n timeoutDuration,\n resolveOutputPath,\n options,\n forceRetranslation,\n forceDownload,\n}: {\n fileVersionData: FileTranslationData;\n jobData: EnqueueFilesResult | undefined;\n branchData: BranchData | undefined;\n locales: string[];\n timeoutDuration: number;\n resolveOutputPath: (sourcePath: string, locale: string) => string | null;\n options: Settings;\n forceRetranslation?: boolean;\n forceDownload?: boolean;\n}): Promise<boolean> {\n if (!branchData) {\n // Run the branch step\n const branchStep = new BranchStep(gt, options);\n const branchResult = await branchStep.run();\n await branchStep.wait();\n if (!branchResult) {\n return logErrorAndExit(branchResolutionError);\n }\n branchData = branchResult;\n }\n // readLockfile uses _branchId to select branch-specific lockfile entries.\n // Keep it on a scoped copy so the caller's settings object is not mutated.\n const settingsForBranch: Settings = {\n ...options,\n _branchId: branchData.currentBranch.id,\n };\n // Prepare the query data\n const fileQueryData = prepareFileQueryData(\n fileVersionData,\n locales,\n branchData\n );\n\n // Initialize download status\n const fileTracker: FileStatusTracker = {\n completed: new Map<string, FileProperties>(),\n inProgress: new Map<string, FileProperties>(),\n failed: new Map<string, FileProperties>(),\n skipped: new Map<string, FileProperties>(),\n };\n\n // Step 1: Poll translation jobs if jobData exists\n let pollTimedOut = false;\n if (jobData) {\n const pollStep = new PollTranslationJobsStep(gt);\n const pollResult = await pollStep.run({\n fileTracker,\n fileQueryData,\n jobData,\n timeoutDuration,\n forceRetranslation,\n });\n await pollStep.wait();\n\n if (pollResult.fileTracker.failed.size > 0) {\n logger.error(\n `${chalk.red(`${pollResult.fileTracker.failed.size} file(s) failed to translate:`)}\\n${Array.from(\n pollResult.fileTracker.failed.entries()\n )\n .map(([, value]) => `- ${value.fileName}`)\n .join('\\n')}`\n );\n for (const [, value] of pollResult.fileTracker.failed) {\n recordWarning(\n 'failed_translation',\n value.fileName,\n `Failed to translate for locale ${value.locale}`\n );\n }\n\n // If all files failed translation, exit early\n if (pollResult.fileTracker.completed.size === 0) {\n return false;\n }\n }\n\n // Even if polling timed out, still download whatever completed successfully\n if (!pollResult.success) {\n pollTimedOut = true;\n if (pollResult.fileTracker.completed.size > 0) {\n logger.warn(\n chalk.yellow(\n `Timed out, but ${pollResult.fileTracker.completed.size} translation(s) completed successfully. Downloading completed files...`\n )\n );\n } else {\n return false;\n }\n }\n } else {\n for (const file of fileQueryData) {\n // Staging - assume all files are completed\n fileTracker.completed.set(\n `${file.branchId}:${file.fileId}:${file.versionId}:${file.locale}`,\n file\n );\n }\n }\n\n await clearCompletedLocaleDirs({\n fileTracker,\n locales,\n resolveOutputPath,\n options,\n });\n\n // Step 2: Download translations\n const downloadStep = new DownloadTranslationsStep(gt, settingsForBranch);\n const downloadResult = await downloadStep.run({\n fileTracker,\n resolveOutputPath,\n forceDownload,\n });\n await downloadStep.wait();\n\n // If polling timed out, report failure even though we downloaded what we could\n if (pollTimedOut) {\n return false;\n }\n\n return downloadResult;\n}\n\nasync function clearCompletedLocaleDirs({\n fileTracker,\n locales,\n resolveOutputPath,\n options,\n}: {\n fileTracker: FileStatusTracker;\n locales: string[];\n resolveOutputPath: (sourcePath: string, locale: string) => string | null;\n options: Settings;\n}): Promise<void> {\n if (\n options.options?.experimentalClearLocaleDirs !== true ||\n fileTracker.completed.size === 0\n ) {\n return;\n }\n\n const translatedFiles = new Set(\n Array.from(fileTracker.completed.values())\n .map((file) => {\n const outputPath = resolveOutputPath(file.fileName, file.locale);\n // Only clear if the output path is different from the source.\n return outputPath !== null && outputPath !== file.fileName\n ? outputPath\n : null;\n })\n .filter((filePath): filePath is string => filePath !== null)\n );\n\n if (translatedFiles.size === 0) return;\n\n const cwd = path.dirname(options.config);\n\n await clearLocaleDirs(\n translatedFiles,\n locales,\n options.options?.clearLocaleDirsExclude,\n cwd\n );\n}\n\n/**\n * Prepares the file query data from input data and locales\n */\nfunction prepareFileQueryData(\n fileVersionData: FileTranslationData,\n locales: string[],\n branchData: BranchData\n): FileProperties[] {\n const fileQueryData: FileProperties[] = [];\n\n for (const fileId in fileVersionData) {\n for (const locale of locales) {\n fileQueryData.push({\n versionId: fileVersionData[fileId].versionId,\n fileName: fileVersionData[fileId].fileName,\n fileId,\n locale,\n branchId: branchData.currentBranch.id,\n componentCount: fileVersionData[fileId].componentCount,\n });\n }\n }\n\n return fileQueryData;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"download.js","names":[],"sources":["../../src/workflows/download.ts"],"sourcesContent":["import path from 'node:path';\nimport { Settings } from '../types/index.js';\nimport { gt } from '../utils/gt.js';\nimport { EnqueueFilesResult } from 'generaltranslation/types';\nimport { clearLocaleDirs } from '../fs/clearLocaleDirs.js';\nimport {\n FileStatusTracker,\n PollTranslationJobsStep,\n} from './steps/PollJobsStep.js';\nimport { DownloadTranslationsStep } from './steps/DownloadStep.js';\nimport { BranchData } from '../types/branch.js';\nimport { branchResolutionError } from '../console/index.js';\nimport { logErrorAndExit } from '../console/logging.js';\nimport { logger } from '../console/logger.js';\nimport { recordWarning } from '../state/translateWarnings.js';\nimport { BranchStep } from './steps/BranchStep.js';\nimport { FileProperties } from '../types/files.js';\nimport chalk from 'chalk';\n\nexport type FileTranslationData = {\n [fileId: string]: {\n versionId: string;\n fileName: string;\n /** Source component count for GTJSON files */\n componentCount?: number;\n };\n};\n\n/**\n * Checks the status of translations and downloads them using a workflow pattern\n * @param fileVersionData - Mapping of file IDs to their version and name information\n * @param jobData - Optional job data from enqueue operation\n * @param locales - The locales to wait for\n * @param timeoutDuration - The timeout duration for the wait in seconds\n * @param resolveOutputPath - Function to resolve the output path for a given source path and locale\n * @param options - Settings configuration\n * @param forceRetranslation - Whether to force retranslation\n * @param forceDownload - Whether to force download even if file exists\n * @returns True if all translations are downloaded successfully, false otherwise\n */\nexport async function runDownloadWorkflow({\n fileVersionData,\n jobData,\n branchData,\n locales,\n timeoutDuration,\n resolveOutputPath,\n options,\n forceRetranslation,\n forceDownload,\n}: {\n fileVersionData: FileTranslationData;\n jobData: EnqueueFilesResult | undefined;\n branchData: BranchData | undefined;\n locales: string[];\n timeoutDuration: number;\n resolveOutputPath: (sourcePath: string, locale: string) => string | null;\n options: Settings;\n forceRetranslation?: boolean;\n forceDownload?: boolean;\n}): Promise<boolean> {\n if (!branchData) {\n // Run the branch step\n const branchStep = new BranchStep(gt, options);\n const branchResult = await branchStep.run();\n if (!branchResult) {\n return logErrorAndExit(branchResolutionError);\n }\n branchData = branchResult;\n }\n // readLockfile uses _branchId to select branch-specific lockfile entries.\n // Keep it on a scoped copy so the caller's settings object is not mutated.\n const settingsForBranch: Settings = {\n ...options,\n _branchId: branchData.currentBranch.id,\n };\n // Prepare the query data\n const fileQueryData = prepareFileQueryData(\n fileVersionData,\n locales,\n branchData\n );\n\n // Initialize download status\n const fileTracker: FileStatusTracker = {\n completed: new Map<string, FileProperties>(),\n inProgress: new Map<string, FileProperties>(),\n failed: new Map<string, FileProperties>(),\n skipped: new Map<string, FileProperties>(),\n };\n\n // Step 1: Poll translation jobs if jobData exists\n let pollTimedOut = false;\n if (jobData) {\n const pollStep = new PollTranslationJobsStep(gt);\n const pollResult = await pollStep.run({\n fileTracker,\n fileQueryData,\n jobData,\n timeoutDuration,\n forceRetranslation,\n });\n\n if (pollResult.fileTracker.failed.size > 0) {\n logger.error(\n `${chalk.red(`${pollResult.fileTracker.failed.size} file(s) failed to translate:`)}\\n${Array.from(\n pollResult.fileTracker.failed.entries()\n )\n .map(([, value]) => `- ${value.fileName}`)\n .join('\\n')}`\n );\n for (const [, value] of pollResult.fileTracker.failed) {\n recordWarning(\n 'failed_translation',\n value.fileName,\n `Failed to translate for locale ${value.locale}`\n );\n }\n\n // If all files failed translation, exit early\n if (pollResult.fileTracker.completed.size === 0) {\n return false;\n }\n }\n\n // Even if polling timed out, still download whatever completed successfully\n if (!pollResult.success) {\n pollTimedOut = true;\n if (pollResult.fileTracker.completed.size > 0) {\n logger.warn(\n chalk.yellow(\n `Timed out, but ${pollResult.fileTracker.completed.size} translation(s) completed successfully. Downloading completed files...`\n )\n );\n } else {\n return false;\n }\n }\n } else {\n for (const file of fileQueryData) {\n // Staging - assume all files are completed\n fileTracker.completed.set(\n `${file.branchId}:${file.fileId}:${file.versionId}:${file.locale}`,\n file\n );\n }\n }\n\n await clearCompletedLocaleDirs({\n fileTracker,\n locales,\n resolveOutputPath,\n options,\n });\n\n // Step 2: Download translations\n const downloadStep = new DownloadTranslationsStep(gt, settingsForBranch);\n const downloadResult = await downloadStep.run({\n fileTracker,\n resolveOutputPath,\n forceDownload,\n });\n\n // If polling timed out, report failure even though we downloaded what we could\n if (pollTimedOut) {\n return false;\n }\n\n return downloadResult;\n}\n\nasync function clearCompletedLocaleDirs({\n fileTracker,\n locales,\n resolveOutputPath,\n options,\n}: {\n fileTracker: FileStatusTracker;\n locales: string[];\n resolveOutputPath: (sourcePath: string, locale: string) => string | null;\n options: Settings;\n}): Promise<void> {\n if (\n options.options?.experimentalClearLocaleDirs !== true ||\n fileTracker.completed.size === 0\n ) {\n return;\n }\n\n const translatedFiles = new Set(\n Array.from(fileTracker.completed.values())\n .map((file) => {\n const outputPath = resolveOutputPath(file.fileName, file.locale);\n // Only clear if the output path is different from the source.\n return outputPath !== null && outputPath !== file.fileName\n ? outputPath\n : null;\n })\n .filter((filePath): filePath is string => filePath !== null)\n );\n\n if (translatedFiles.size === 0) return;\n\n const cwd = path.dirname(options.config);\n\n await clearLocaleDirs(\n translatedFiles,\n locales,\n options.options?.clearLocaleDirsExclude,\n cwd\n );\n}\n\n/**\n * Prepares the file query data from input data and locales\n */\nfunction prepareFileQueryData(\n fileVersionData: FileTranslationData,\n locales: string[],\n branchData: BranchData\n): FileProperties[] {\n const fileQueryData: FileProperties[] = [];\n\n for (const fileId in fileVersionData) {\n for (const locale of locales) {\n fileQueryData.push({\n versionId: fileVersionData[fileId].versionId,\n fileName: fileVersionData[fileId].fileName,\n fileId,\n locale,\n branchId: branchData.currentBranch.id,\n componentCount: fileVersionData[fileId].componentCount,\n });\n }\n }\n\n return fileQueryData;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAwCA,eAAsB,oBAAoB,EACxC,iBACA,SACA,YACA,SACA,iBACA,mBACA,SACA,oBACA,iBAWmB;AACnB,KAAI,CAAC,YAAY;EAGf,MAAM,eAAe,MAAM,IADJ,WAAW,IAAI,QACD,CAAC,KAAK;AAC3C,MAAI,CAAC,aACH,QAAO,gBAAgB,sBAAsB;AAE/C,eAAa;;CAIf,MAAM,oBAA8B;EAClC,GAAG;EACH,WAAW,WAAW,cAAc;EACrC;CAED,MAAM,gBAAgB,qBACpB,iBACA,SACA,WACD;CAGD,MAAM,cAAiC;EACrC,2BAAW,IAAI,KAA6B;EAC5C,4BAAY,IAAI,KAA6B;EAC7C,wBAAQ,IAAI,KAA6B;EACzC,yBAAS,IAAI,KAA6B;EAC3C;CAGD,IAAI,eAAe;AACnB,KAAI,SAAS;EAEX,MAAM,aAAa,MAAM,IADJ,wBAAwB,GACZ,CAAC,IAAI;GACpC;GACA;GACA;GACA;GACA;GACD,CAAC;AAEF,MAAI,WAAW,YAAY,OAAO,OAAO,GAAG;AAC1C,UAAO,MACL,GAAG,MAAM,IAAI,GAAG,WAAW,YAAY,OAAO,KAAK,+BAA+B,CAAC,IAAI,MAAM,KAC3F,WAAW,YAAY,OAAO,SAAS,CACxC,CACE,KAAK,GAAG,WAAW,KAAK,MAAM,WAAW,CACzC,KAAK,KAAK,GACd;AACD,QAAK,MAAM,GAAG,UAAU,WAAW,YAAY,OAC7C,eACE,sBACA,MAAM,UACN,kCAAkC,MAAM,SACzC;AAIH,OAAI,WAAW,YAAY,UAAU,SAAS,EAC5C,QAAO;;AAKX,MAAI,CAAC,WAAW,SAAS;AACvB,kBAAe;AACf,OAAI,WAAW,YAAY,UAAU,OAAO,EAC1C,QAAO,KACL,MAAM,OACJ,kBAAkB,WAAW,YAAY,UAAU,KAAK,wEACzD,CACF;OAED,QAAO;;OAIX,MAAK,MAAM,QAAQ,cAEjB,aAAY,UAAU,IACpB,GAAG,KAAK,SAAS,GAAG,KAAK,OAAO,GAAG,KAAK,UAAU,GAAG,KAAK,UAC1D,KACD;AAIL,OAAM,yBAAyB;EAC7B;EACA;EACA;EACA;EACD,CAAC;CAIF,MAAM,iBAAiB,MAAM,IADJ,yBAAyB,IAAI,kBACb,CAAC,IAAI;EAC5C;EACA;EACA;EACD,CAAC;AAGF,KAAI,aACF,QAAO;AAGT,QAAO;;AAGT,eAAe,yBAAyB,EACtC,aACA,SACA,mBACA,WAMgB;AAChB,KACE,QAAQ,SAAS,gCAAgC,QACjD,YAAY,UAAU,SAAS,EAE/B;CAGF,MAAM,kBAAkB,IAAI,IAC1B,MAAM,KAAK,YAAY,UAAU,QAAQ,CAAC,CACvC,KAAK,SAAS;EACb,MAAM,aAAa,kBAAkB,KAAK,UAAU,KAAK,OAAO;AAEhE,SAAO,eAAe,QAAQ,eAAe,KAAK,WAC9C,aACA;GACJ,CACD,QAAQ,aAAiC,aAAa,KAAK,CAC/D;AAED,KAAI,gBAAgB,SAAS,EAAG;CAEhC,MAAM,MAAM,KAAK,QAAQ,QAAQ,OAAO;AAExC,OAAM,gBACJ,iBACA,SACA,QAAQ,SAAS,wBACjB,IACD;;;;;AAMH,SAAS,qBACP,iBACA,SACA,YACkB;CAClB,MAAM,gBAAkC,EAAE;AAE1C,MAAK,MAAM,UAAU,gBACnB,MAAK,MAAM,UAAU,QACnB,eAAc,KAAK;EACjB,WAAW,gBAAgB,QAAQ;EACnC,UAAU,gBAAgB,QAAQ;EAClC;EACA;EACA,UAAU,WAAW,cAAc;EACnC,gBAAgB,gBAAgB,QAAQ;EACzC,CAAC;AAIN,QAAO"}
@@ -23,7 +23,6 @@ async function runEnqueueWorkflow({ files, options, settings }) {
23
23
  const branchStep = new BranchStep(gt, settings);
24
24
  const enqueueStep = new EnqueueStep(gt, settings, options.force);
25
25
  const branchData = await branchStep.run();
26
- await branchStep.wait();
27
26
  if (!branchData) return logErrorAndExit(branchResolutionError);
28
27
  logger.debug("Branch data: " + JSON.stringify(branchData, null, 2));
29
28
  const { filesToEnqueue, skippedFiles } = await filterFilesForEnqueue({
@@ -37,7 +36,6 @@ async function runEnqueueWorkflow({ files, options, settings }) {
37
36
  });
38
37
  if (skippedFiles.length > 0) logger.info(`Skipped enqueue for ${skippedFiles.length} already translated file${skippedFiles.length === 1 ? "" : "s"}`);
39
38
  const enqueueResult = await enqueueStep.run(filesToEnqueue);
40
- await enqueueStep.wait();
41
39
  logger.debug("Enqueue result: " + JSON.stringify(enqueueResult, null, 2));
42
40
  logEnqueueResult(enqueueResult, filesToEnqueue.length === 0 ? files.length : filesToEnqueue.length);
43
41
  return enqueueResult;
@@ -1 +1 @@
1
- {"version":3,"file":"enqueue.js","names":[],"sources":["../../src/workflows/enqueue.ts"],"sourcesContent":["import { logCollectedFiles, logErrorAndExit } from '../console/logging.js';\nimport { branchResolutionError, withOriginalError } from '../console/index.js';\nimport { Settings, TranslateFlags } from '../types/index.js';\nimport { gt } from '../utils/gt.js';\nimport { EnqueueFilesResult, FileToUpload } from 'generaltranslation/types';\nimport { EnqueueStep } from './steps/EnqueueStep.js';\nimport { BranchStep } from './steps/BranchStep.js';\nimport { logger } from '../console/logger.js';\nimport { filterFilesForEnqueue } from './utils/filterFilesForEnqueue.js';\n\n/**\n * Enqueues translations for a given set of files\n * - Only enqueues uploaded files\n * - Don't have to worry about double enqueuing files because dedupe on API side\n *\n * @param {FileTranslationData} fileVersionData - The file version data\n * @param {TranslateFlags} options - The options for the enqueue operation\n * @param {Settings} settings - The settings for the enqueue operation\n * @returns {Promise<EnqueueFilesResult>} The enqueue result\n */\nexport async function runEnqueueWorkflow({\n files,\n options,\n settings,\n}: {\n files: FileToUpload[];\n options: TranslateFlags;\n settings: Settings;\n}): Promise<EnqueueFilesResult> {\n try {\n // Log files to be enqueued\n logCollectedFiles(files);\n\n logger.debug('Files: ' + JSON.stringify(files, null, 2));\n\n // Create workflow with steps\n const branchStep = new BranchStep(gt, settings);\n // const queryFileDataStep = new QueryFileDataStep(gt);\n const enqueueStep = new EnqueueStep(gt, settings, options.force);\n\n // (1) run the branch step\n const branchData = await branchStep.run();\n await branchStep.wait();\n if (!branchData) {\n return logErrorAndExit(branchResolutionError);\n }\n logger.debug('Branch data: ' + JSON.stringify(branchData, null, 2));\n\n // (2) Enqueue the files\n const filesWithBranch = files.map((files) => ({\n branchId: branchData.currentBranch.id,\n ...files,\n }));\n const { filesToEnqueue, skippedFiles } = await filterFilesForEnqueue({\n gt,\n files: filesWithBranch,\n locales: settings.locales,\n force: options.force,\n });\n if (skippedFiles.length > 0) {\n logger.info(\n `Skipped enqueue for ${skippedFiles.length} already translated file${skippedFiles.length === 1 ? '' : 's'}`\n );\n }\n\n const enqueueResult = await enqueueStep.run(filesToEnqueue);\n await enqueueStep.wait();\n\n logger.debug('Enqueue result: ' + JSON.stringify(enqueueResult, null, 2));\n\n logEnqueueResult(\n enqueueResult,\n filesToEnqueue.length === 0 ? files.length : filesToEnqueue.length\n );\n return enqueueResult;\n } catch (error) {\n return logErrorAndExit(\n withOriginalError(\n 'Translations could not be enqueued. Check the files, branch configuration, and API credentials, then try again.',\n error\n )\n );\n }\n}\n\n// ----- Helper functions ----- //\n\n/**\n * Logs the enqueue result\n * @param enqueueResult - The enqueue result\n * @returns void\n */\nfunction logEnqueueResult(\n enqueueResult: EnqueueFilesResult,\n fileCount: number\n): void {\n if (Object.keys(enqueueResult.jobData).length === 0) {\n logger.success(\n `All ${fileCount} ${fileCount === 1 ? 'file' : 'files'} already translated. 0 files enqueued.`\n );\n } else {\n logger.success(enqueueResult.message);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAoBA,eAAsB,mBAAmB,EACvC,OACA,SACA,YAK8B;AAC9B,KAAI;AAEF,oBAAkB,MAAM;AAExB,SAAO,MAAM,YAAY,KAAK,UAAU,OAAO,MAAM,EAAE,CAAC;EAGxD,MAAM,aAAa,IAAI,WAAW,IAAI,SAAS;EAE/C,MAAM,cAAc,IAAI,YAAY,IAAI,UAAU,QAAQ,MAAM;EAGhE,MAAM,aAAa,MAAM,WAAW,KAAK;AACzC,QAAM,WAAW,MAAM;AACvB,MAAI,CAAC,WACH,QAAO,gBAAgB,sBAAsB;AAE/C,SAAO,MAAM,kBAAkB,KAAK,UAAU,YAAY,MAAM,EAAE,CAAC;EAOnE,MAAM,EAAE,gBAAgB,iBAAiB,MAAM,sBAAsB;GACnE;GACA,OANsB,MAAM,KAAK,WAAW;IAC5C,UAAU,WAAW,cAAc;IACnC,GAAG;IACJ,EAGuB;GACtB,SAAS,SAAS;GAClB,OAAO,QAAQ;GAChB,CAAC;AACF,MAAI,aAAa,SAAS,EACxB,QAAO,KACL,uBAAuB,aAAa,OAAO,0BAA0B,aAAa,WAAW,IAAI,KAAK,MACvG;EAGH,MAAM,gBAAgB,MAAM,YAAY,IAAI,eAAe;AAC3D,QAAM,YAAY,MAAM;AAExB,SAAO,MAAM,qBAAqB,KAAK,UAAU,eAAe,MAAM,EAAE,CAAC;AAEzE,mBACE,eACA,eAAe,WAAW,IAAI,MAAM,SAAS,eAAe,OAC7D;AACD,SAAO;UACA,OAAO;AACd,SAAO,gBACL,kBACE,mHACA,MACD,CACF;;;;;;;;AAWL,SAAS,iBACP,eACA,WACM;AACN,KAAI,OAAO,KAAK,cAAc,QAAQ,CAAC,WAAW,EAChD,QAAO,QACL,OAAO,UAAU,GAAG,cAAc,IAAI,SAAS,QAAQ,wCACxD;KAED,QAAO,QAAQ,cAAc,QAAQ"}
1
+ {"version":3,"file":"enqueue.js","names":[],"sources":["../../src/workflows/enqueue.ts"],"sourcesContent":["import { logCollectedFiles, logErrorAndExit } from '../console/logging.js';\nimport { branchResolutionError, withOriginalError } from '../console/index.js';\nimport { Settings, TranslateFlags } from '../types/index.js';\nimport { gt } from '../utils/gt.js';\nimport { EnqueueFilesResult, FileToUpload } from 'generaltranslation/types';\nimport { EnqueueStep } from './steps/EnqueueStep.js';\nimport { BranchStep } from './steps/BranchStep.js';\nimport { logger } from '../console/logger.js';\nimport { filterFilesForEnqueue } from './utils/filterFilesForEnqueue.js';\n\n/**\n * Enqueues translations for a given set of files\n * - Only enqueues uploaded files\n * - Don't have to worry about double enqueuing files because dedupe on API side\n *\n * @param {FileTranslationData} fileVersionData - The file version data\n * @param {TranslateFlags} options - The options for the enqueue operation\n * @param {Settings} settings - The settings for the enqueue operation\n * @returns {Promise<EnqueueFilesResult>} The enqueue result\n */\nexport async function runEnqueueWorkflow({\n files,\n options,\n settings,\n}: {\n files: FileToUpload[];\n options: TranslateFlags;\n settings: Settings;\n}): Promise<EnqueueFilesResult> {\n try {\n // Log files to be enqueued\n logCollectedFiles(files);\n\n logger.debug('Files: ' + JSON.stringify(files, null, 2));\n\n // Create workflow with steps\n const branchStep = new BranchStep(gt, settings);\n // const queryFileDataStep = new QueryFileDataStep(gt);\n const enqueueStep = new EnqueueStep(gt, settings, options.force);\n\n // (1) run the branch step\n const branchData = await branchStep.run();\n if (!branchData) {\n return logErrorAndExit(branchResolutionError);\n }\n logger.debug('Branch data: ' + JSON.stringify(branchData, null, 2));\n\n // (2) Enqueue the files\n const filesWithBranch = files.map((files) => ({\n branchId: branchData.currentBranch.id,\n ...files,\n }));\n const { filesToEnqueue, skippedFiles } = await filterFilesForEnqueue({\n gt,\n files: filesWithBranch,\n locales: settings.locales,\n force: options.force,\n });\n if (skippedFiles.length > 0) {\n logger.info(\n `Skipped enqueue for ${skippedFiles.length} already translated file${skippedFiles.length === 1 ? '' : 's'}`\n );\n }\n\n const enqueueResult = await enqueueStep.run(filesToEnqueue);\n\n logger.debug('Enqueue result: ' + JSON.stringify(enqueueResult, null, 2));\n\n logEnqueueResult(\n enqueueResult,\n filesToEnqueue.length === 0 ? files.length : filesToEnqueue.length\n );\n return enqueueResult;\n } catch (error) {\n return logErrorAndExit(\n withOriginalError(\n 'Translations could not be enqueued. Check the files, branch configuration, and API credentials, then try again.',\n error\n )\n );\n }\n}\n\n// ----- Helper functions ----- //\n\n/**\n * Logs the enqueue result\n * @param enqueueResult - The enqueue result\n * @returns void\n */\nfunction logEnqueueResult(\n enqueueResult: EnqueueFilesResult,\n fileCount: number\n): void {\n if (Object.keys(enqueueResult.jobData).length === 0) {\n logger.success(\n `All ${fileCount} ${fileCount === 1 ? 'file' : 'files'} already translated. 0 files enqueued.`\n );\n } else {\n logger.success(enqueueResult.message);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAoBA,eAAsB,mBAAmB,EACvC,OACA,SACA,YAK8B;AAC9B,KAAI;AAEF,oBAAkB,MAAM;AAExB,SAAO,MAAM,YAAY,KAAK,UAAU,OAAO,MAAM,EAAE,CAAC;EAGxD,MAAM,aAAa,IAAI,WAAW,IAAI,SAAS;EAE/C,MAAM,cAAc,IAAI,YAAY,IAAI,UAAU,QAAQ,MAAM;EAGhE,MAAM,aAAa,MAAM,WAAW,KAAK;AACzC,MAAI,CAAC,WACH,QAAO,gBAAgB,sBAAsB;AAE/C,SAAO,MAAM,kBAAkB,KAAK,UAAU,YAAY,MAAM,EAAE,CAAC;EAOnE,MAAM,EAAE,gBAAgB,iBAAiB,MAAM,sBAAsB;GACnE;GACA,OANsB,MAAM,KAAK,WAAW;IAC5C,UAAU,WAAW,cAAc;IACnC,GAAG;IACJ,EAGuB;GACtB,SAAS,SAAS;GAClB,OAAO,QAAQ;GAChB,CAAC;AACF,MAAI,aAAa,SAAS,EACxB,QAAO,KACL,uBAAuB,aAAa,OAAO,0BAA0B,aAAa,WAAW,IAAI,KAAK,MACvG;EAGH,MAAM,gBAAgB,MAAM,YAAY,IAAI,eAAe;AAE3D,SAAO,MAAM,qBAAqB,KAAK,UAAU,eAAe,MAAM,EAAE,CAAC;AAEzE,mBACE,eACA,eAAe,WAAW,IAAI,MAAM,SAAS,eAAe,OAC7D;AACD,SAAO;UACA,OAAO;AACd,SAAO,gBACL,kBACE,mHACA,MACD,CACF;;;;;;;;AAWL,SAAS,iBACP,eACA,WACM;AACN,KAAI,OAAO,KAAK,cAAc,QAAQ,CAAC,WAAW,EAChD,QAAO,QACL,OAAO,UAAU,GAAG,cAAc,IAAI,SAAS,QAAQ,wCACxD;KAED,QAAO,QAAQ,cAAc,QAAQ"}
@@ -18,9 +18,7 @@ async function runPublishWorkflow(files, publishMap, branchId, settings) {
18
18
  fileName: file.fileName
19
19
  }));
20
20
  if (allFileRefs.length === 0) return;
21
- const publishStep = new PublishStep(gt);
22
- await publishStep.run(allFileRefs);
23
- await publishStep.wait();
21
+ await new PublishStep(gt).run(allFileRefs);
24
22
  } catch (error) {
25
23
  logger.warn(`Failed to publish files: ${error instanceof Error ? error.message : String(error)}`);
26
24
  }
@@ -1 +1 @@
1
- {"version":3,"file":"publish.js","names":[],"sources":["../../src/workflows/publish.ts"],"sourcesContent":["import { Settings } from '../types/index.js';\nimport { PublishStep } from './steps/PublishStep.js';\nimport { gt } from '../utils/gt.js';\nimport { hasPublishConfig } from '../utils/resolvePublish.js';\nimport { logger } from '../console/logger.js';\n\n/**\n * Publishes files to the CDN if publish config exists and the publishMap is non-empty.\n * Shared by translate, upload, and save-local commands.\n */\nexport async function runPublishWorkflow(\n files: { fileId: string; versionId: string; fileName: string }[],\n publishMap: Map<string, boolean>,\n branchId: string,\n settings: Settings\n): Promise<void> {\n if (publishMap.size === 0 || !hasPublishConfig(settings)) return;\n\n try {\n const allFileRefs = files\n .filter((file) => publishMap.has(file.fileId))\n .map((file) => ({\n fileId: file.fileId,\n versionId: file.versionId,\n branchId,\n publish: publishMap.get(file.fileId)!,\n fileName: file.fileName,\n }));\n if (allFileRefs.length === 0) return;\n const publishStep = new PublishStep(gt);\n await publishStep.run(allFileRefs);\n await publishStep.wait();\n } catch (error) {\n logger.warn(\n `Failed to publish files: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n}\n"],"mappings":";;;;;;;;;AAUA,eAAsB,mBACpB,OACA,YACA,UACA,UACe;AACf,KAAI,WAAW,SAAS,KAAK,CAAC,iBAAiB,SAAS,CAAE;AAE1D,KAAI;EACF,MAAM,cAAc,MACjB,QAAQ,SAAS,WAAW,IAAI,KAAK,OAAO,CAAC,CAC7C,KAAK,UAAU;GACd,QAAQ,KAAK;GACb,WAAW,KAAK;GAChB;GACA,SAAS,WAAW,IAAI,KAAK,OAAO;GACpC,UAAU,KAAK;GAChB,EAAE;AACL,MAAI,YAAY,WAAW,EAAG;EAC9B,MAAM,cAAc,IAAI,YAAY,GAAG;AACvC,QAAM,YAAY,IAAI,YAAY;AAClC,QAAM,YAAY,MAAM;UACjB,OAAO;AACd,SAAO,KACL,4BAA4B,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,GACnF"}
1
+ {"version":3,"file":"publish.js","names":[],"sources":["../../src/workflows/publish.ts"],"sourcesContent":["import { Settings } from '../types/index.js';\nimport { PublishStep } from './steps/PublishStep.js';\nimport { gt } from '../utils/gt.js';\nimport { hasPublishConfig } from '../utils/resolvePublish.js';\nimport { logger } from '../console/logger.js';\n\n/**\n * Publishes files to the CDN if publish config exists and the publishMap is non-empty.\n * Shared by translate, upload, and save-local commands.\n */\nexport async function runPublishWorkflow(\n files: { fileId: string; versionId: string; fileName: string }[],\n publishMap: Map<string, boolean>,\n branchId: string,\n settings: Settings\n): Promise<void> {\n if (publishMap.size === 0 || !hasPublishConfig(settings)) return;\n\n try {\n const allFileRefs = files\n .filter((file) => publishMap.has(file.fileId))\n .map((file) => ({\n fileId: file.fileId,\n versionId: file.versionId,\n branchId,\n publish: publishMap.get(file.fileId)!,\n fileName: file.fileName,\n }));\n if (allFileRefs.length === 0) return;\n const publishStep = new PublishStep(gt);\n await publishStep.run(allFileRefs);\n } catch (error) {\n logger.warn(\n `Failed to publish files: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n}\n"],"mappings":";;;;;;;;;AAUA,eAAsB,mBACpB,OACA,YACA,UACA,UACe;AACf,KAAI,WAAW,SAAS,KAAK,CAAC,iBAAiB,SAAS,CAAE;AAE1D,KAAI;EACF,MAAM,cAAc,MACjB,QAAQ,SAAS,WAAW,IAAI,KAAK,OAAO,CAAC,CAC7C,KAAK,UAAU;GACd,QAAQ,KAAK;GACb,WAAW,KAAK;GAChB;GACA,SAAS,WAAW,IAAI,KAAK,OAAO;GACpC,UAAU,KAAK;GAChB,EAAE;AACL,MAAI,YAAY,WAAW,EAAG;AAE9B,QAAM,IADkB,YAAY,GACnB,CAAC,IAAI,YAAY;UAC3B,OAAO;AACd,SAAO,KACL,4BAA4B,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,GACnF"}
@@ -21,15 +21,12 @@ async function runSetupProjectWorkflow(files, options, settings) {
21
21
  const uploadStep = new UploadSourcesStep(gt, settings);
22
22
  const setupStep = new SetupStep(gt, settings, timeoutMs);
23
23
  const branchData = await branchStep.run();
24
- await branchStep.wait();
25
24
  if (!branchData) return logErrorAndExit(branchResolutionError);
26
25
  const uploadedFiles = await uploadStep.run({
27
26
  files,
28
27
  branchData
29
28
  });
30
- await uploadStep.wait();
31
29
  await setupStep.run(uploadedFiles, options.force ?? false);
32
- await setupStep.wait();
33
30
  return { branchData };
34
31
  } catch (error) {
35
32
  return logErrorAndExit(withOriginalError("Project setup could not be completed. Check the files, branch configuration, and API credentials, then try again.", error));
@@ -1 +1 @@
1
- {"version":3,"file":"setupProject.js","names":[],"sources":["../../src/workflows/setupProject.ts"],"sourcesContent":["import { logErrorAndExit } from '../console/logging.js';\nimport { branchResolutionError, withOriginalError } from '../console/index.js';\nimport { Settings, TranslateFlags } from '../types/index.js';\nimport { gt } from '../utils/gt.js';\nimport { FileToUpload } from 'generaltranslation/types';\nimport { UploadSourcesStep } from './steps/UploadSourcesStep.js';\nimport { SetupStep } from './steps/SetupStep.js';\nimport { BranchStep } from './steps/BranchStep.js';\nimport { BranchData } from '../types/branch.js';\nimport { logCollectedFiles } from '../console/logging.js';\nimport { calculateTimeoutMs } from '../utils/calculateTimeoutMs.js';\n\n/**\n * Sets up a project by uploading files running the setup step\n * @param files - Array of file objects to upload\n * @param options - The options for the API call\n * @param settings - Settings configuration\n * @returns The branch data\n */\nexport async function runSetupProjectWorkflow(\n files: FileToUpload[],\n options: TranslateFlags,\n settings: Settings\n): Promise<{\n branchData: BranchData;\n}> {\n try {\n // Log files to be translated\n logCollectedFiles(files);\n\n // Calculate timeout for setup step\n const timeoutMs = calculateTimeoutMs(options.timeout);\n\n // Create workflow with steps\n const branchStep = new BranchStep(gt, settings);\n const uploadStep = new UploadSourcesStep(gt, settings);\n const setupStep = new SetupStep(gt, settings, timeoutMs);\n\n // first run the branch step\n const branchData = await branchStep.run();\n await branchStep.wait();\n\n if (!branchData) {\n return logErrorAndExit(branchResolutionError);\n }\n\n // then run the upload step\n const uploadedFiles = await uploadStep.run({ files, branchData });\n await uploadStep.wait();\n\n // then run the setup step\n await setupStep.run(uploadedFiles, options.force ?? false);\n await setupStep.wait();\n\n return { branchData };\n } catch (error) {\n return logErrorAndExit(\n withOriginalError(\n 'Project setup could not be completed. Check the files, branch configuration, and API credentials, then try again.',\n error\n )\n );\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;AAmBA,eAAsB,wBACpB,OACA,SACA,UAGC;AACD,KAAI;AAEF,oBAAkB,MAAM;EAGxB,MAAM,YAAY,mBAAmB,QAAQ,QAAQ;EAGrD,MAAM,aAAa,IAAI,WAAW,IAAI,SAAS;EAC/C,MAAM,aAAa,IAAI,kBAAkB,IAAI,SAAS;EACtD,MAAM,YAAY,IAAI,UAAU,IAAI,UAAU,UAAU;EAGxD,MAAM,aAAa,MAAM,WAAW,KAAK;AACzC,QAAM,WAAW,MAAM;AAEvB,MAAI,CAAC,WACH,QAAO,gBAAgB,sBAAsB;EAI/C,MAAM,gBAAgB,MAAM,WAAW,IAAI;GAAE;GAAO;GAAY,CAAC;AACjE,QAAM,WAAW,MAAM;AAGvB,QAAM,UAAU,IAAI,eAAe,QAAQ,SAAS,MAAM;AAC1D,QAAM,UAAU,MAAM;AAEtB,SAAO,EAAE,YAAY;UACd,OAAO;AACd,SAAO,gBACL,kBACE,qHACA,MACD,CACF"}
1
+ {"version":3,"file":"setupProject.js","names":[],"sources":["../../src/workflows/setupProject.ts"],"sourcesContent":["import { logErrorAndExit } from '../console/logging.js';\nimport { branchResolutionError, withOriginalError } from '../console/index.js';\nimport { Settings, TranslateFlags } from '../types/index.js';\nimport { gt } from '../utils/gt.js';\nimport { FileToUpload } from 'generaltranslation/types';\nimport { UploadSourcesStep } from './steps/UploadSourcesStep.js';\nimport { SetupStep } from './steps/SetupStep.js';\nimport { BranchStep } from './steps/BranchStep.js';\nimport { BranchData } from '../types/branch.js';\nimport { logCollectedFiles } from '../console/logging.js';\nimport { calculateTimeoutMs } from '../utils/calculateTimeoutMs.js';\n\n/**\n * Sets up a project by uploading files running the setup step\n * @param files - Array of file objects to upload\n * @param options - The options for the API call\n * @param settings - Settings configuration\n * @returns The branch data\n */\nexport async function runSetupProjectWorkflow(\n files: FileToUpload[],\n options: TranslateFlags,\n settings: Settings\n): Promise<{\n branchData: BranchData;\n}> {\n try {\n // Log files to be translated\n logCollectedFiles(files);\n\n // Calculate timeout for setup step\n const timeoutMs = calculateTimeoutMs(options.timeout);\n\n // Create workflow with steps\n const branchStep = new BranchStep(gt, settings);\n const uploadStep = new UploadSourcesStep(gt, settings);\n const setupStep = new SetupStep(gt, settings, timeoutMs);\n\n // first run the branch step\n const branchData = await branchStep.run();\n\n if (!branchData) {\n return logErrorAndExit(branchResolutionError);\n }\n\n // then run the upload step\n const uploadedFiles = await uploadStep.run({ files, branchData });\n\n // then run the setup step\n await setupStep.run(uploadedFiles, options.force ?? false);\n\n return { branchData };\n } catch (error) {\n return logErrorAndExit(\n withOriginalError(\n 'Project setup could not be completed. Check the files, branch configuration, and API credentials, then try again.',\n error\n )\n );\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;AAmBA,eAAsB,wBACpB,OACA,SACA,UAGC;AACD,KAAI;AAEF,oBAAkB,MAAM;EAGxB,MAAM,YAAY,mBAAmB,QAAQ,QAAQ;EAGrD,MAAM,aAAa,IAAI,WAAW,IAAI,SAAS;EAC/C,MAAM,aAAa,IAAI,kBAAkB,IAAI,SAAS;EACtD,MAAM,YAAY,IAAI,UAAU,IAAI,UAAU,UAAU;EAGxD,MAAM,aAAa,MAAM,WAAW,KAAK;AAEzC,MAAI,CAAC,WACH,QAAO,gBAAgB,sBAAsB;EAI/C,MAAM,gBAAgB,MAAM,WAAW,IAAI;GAAE;GAAO;GAAY,CAAC;AAGjE,QAAM,UAAU,IAAI,eAAe,QAAQ,SAAS,MAAM;AAE1D,SAAO,EAAE,YAAY;UACd,OAAO;AACd,SAAO,gBACL,kBACE,qHACA,MACD,CACF"}
@@ -28,26 +28,18 @@ async function runStageFilesWorkflow({ files, options, settings }) {
28
28
  const setupStep = new SetupStep(gt, settings, timeoutMs);
29
29
  const enqueueStep = new EnqueueStep(gt, settings, options.force);
30
30
  const branchData = await branchStep.run();
31
- await branchStep.wait();
32
31
  if (!branchData) return logErrorAndExit(branchResolutionError);
33
32
  const uploadedFiles = await uploadStep.run({
34
33
  files,
35
34
  branchData
36
35
  });
37
- await uploadStep.wait();
38
- if (options?.saveLocal) {
39
- await userEditDiffsStep.run(uploadedFiles);
40
- await userEditDiffsStep.wait();
41
- }
36
+ if (options?.saveLocal) await userEditDiffsStep.run(uploadedFiles);
42
37
  if (settings.tag) try {
43
- const tagStep = new TagStep(gt, settings, !!options.tag);
44
- await tagStep.run(uploadedFiles);
45
- await tagStep.wait();
38
+ await new TagStep(gt, settings, !!options.tag).run(uploadedFiles);
46
39
  } catch {
47
40
  logger.warn("Failed to create translation tag. Continuing...");
48
41
  }
49
42
  await setupStep.run(uploadedFiles);
50
- await setupStep.wait();
51
43
  const { filesToEnqueue, skippedFiles } = await filterFilesForEnqueue({
52
44
  gt,
53
45
  files: uploadedFiles,
@@ -55,11 +47,9 @@ async function runStageFilesWorkflow({ files, options, settings }) {
55
47
  force: options.force
56
48
  });
57
49
  if (skippedFiles.length > 0) logger.info(`Skipped enqueue for ${skippedFiles.length} already translated file${skippedFiles.length === 1 ? "" : "s"}`);
58
- const enqueueResult = await enqueueStep.run(filesToEnqueue);
59
- await enqueueStep.wait();
60
50
  return {
61
51
  branchData,
62
- enqueueResult
52
+ enqueueResult: await enqueueStep.run(filesToEnqueue)
63
53
  };
64
54
  } catch (error) {
65
55
  return logErrorAndExit(withOriginalError("Files could not be sent for translation. Check the files, branch configuration, and API credentials, then try again.", error));
@@ -1 +1 @@
1
- {"version":3,"file":"stage.js","names":[],"sources":["../../src/workflows/stage.ts"],"sourcesContent":["import { logCollectedFiles, logErrorAndExit } from '../console/logging.js';\nimport { branchResolutionError, withOriginalError } from '../console/index.js';\nimport { logger } from '../console/logger.js';\nimport { Settings, TranslateFlags } from '../types/index.js';\nimport { gt } from '../utils/gt.js';\nimport { EnqueueFilesResult, FileToUpload } from 'generaltranslation/types';\nimport { UploadSourcesStep } from './steps/UploadSourcesStep.js';\nimport { SetupStep } from './steps/SetupStep.js';\nimport { EnqueueStep } from './steps/EnqueueStep.js';\nimport { BranchStep } from './steps/BranchStep.js';\nimport { TagStep } from './steps/TagStep.js';\nimport { UserEditDiffsStep } from './steps/UserEditDiffsStep.js';\nimport { BranchData } from '../types/branch.js';\nimport { calculateTimeoutMs } from '../utils/calculateTimeoutMs.js';\nimport { filterFilesForEnqueue } from './utils/filterFilesForEnqueue.js';\n\n/**\n * Sends multiple files for translation to the API using a workflow pattern\n * @param files - Array of file objects to translate\n * @param options - The options for the API call\n * @param settings - Settings configuration\n * @returns The translated content or version ID\n */\nexport async function runStageFilesWorkflow({\n files,\n options,\n settings,\n}: {\n files: FileToUpload[];\n options: TranslateFlags;\n settings: Settings;\n}): Promise<{\n branchData: BranchData;\n enqueueResult: EnqueueFilesResult;\n}> {\n try {\n // Log files to be translated\n logCollectedFiles(files);\n\n // Calculate timeout for setup step\n const timeoutMs = calculateTimeoutMs(options.timeout);\n\n // Create workflow with steps\n const branchStep = new BranchStep(gt, settings);\n const uploadStep = new UploadSourcesStep(gt, settings);\n const userEditDiffsStep = new UserEditDiffsStep(settings);\n const setupStep = new SetupStep(gt, settings, timeoutMs);\n const enqueueStep = new EnqueueStep(gt, settings, options.force);\n\n // first run the branch step\n const branchData = await branchStep.run();\n await branchStep.wait();\n if (!branchData) {\n return logErrorAndExit(branchResolutionError);\n }\n\n // then run the upload step\n const uploadedFiles = await uploadStep.run({ files, branchData });\n await uploadStep.wait();\n\n // optionally run the user edit diffs step\n if (options?.saveLocal) {\n await userEditDiffsStep.run(uploadedFiles);\n await userEditDiffsStep.wait();\n }\n\n // then run the tag step (non-fatal — tagging failure should not block translations)\n if (settings.tag) {\n try {\n const userProvidedTag = !!options.tag;\n const tagStep = new TagStep(gt, settings, userProvidedTag);\n await tagStep.run(uploadedFiles);\n await tagStep.wait();\n } catch {\n logger.warn('Failed to create translation tag. Continuing...');\n }\n }\n\n // then run the setup step\n await setupStep.run(uploadedFiles);\n await setupStep.wait();\n\n // then run the enqueue step\n const { filesToEnqueue, skippedFiles } = await filterFilesForEnqueue({\n gt,\n files: uploadedFiles,\n locales: settings.locales,\n force: options.force,\n });\n if (skippedFiles.length > 0) {\n logger.info(\n `Skipped enqueue for ${skippedFiles.length} already translated file${skippedFiles.length === 1 ? '' : 's'}`\n );\n }\n\n const enqueueResult = await enqueueStep.run(filesToEnqueue);\n await enqueueStep.wait();\n\n return { branchData, enqueueResult };\n } catch (error) {\n return logErrorAndExit(\n withOriginalError(\n 'Files could not be sent for translation. Check the files, branch configuration, and API credentials, then try again.',\n error\n )\n );\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAuBA,eAAsB,sBAAsB,EAC1C,OACA,SACA,YAQC;AACD,KAAI;AAEF,oBAAkB,MAAM;EAGxB,MAAM,YAAY,mBAAmB,QAAQ,QAAQ;EAGrD,MAAM,aAAa,IAAI,WAAW,IAAI,SAAS;EAC/C,MAAM,aAAa,IAAI,kBAAkB,IAAI,SAAS;EACtD,MAAM,oBAAoB,IAAI,kBAAkB,SAAS;EACzD,MAAM,YAAY,IAAI,UAAU,IAAI,UAAU,UAAU;EACxD,MAAM,cAAc,IAAI,YAAY,IAAI,UAAU,QAAQ,MAAM;EAGhE,MAAM,aAAa,MAAM,WAAW,KAAK;AACzC,QAAM,WAAW,MAAM;AACvB,MAAI,CAAC,WACH,QAAO,gBAAgB,sBAAsB;EAI/C,MAAM,gBAAgB,MAAM,WAAW,IAAI;GAAE;GAAO;GAAY,CAAC;AACjE,QAAM,WAAW,MAAM;AAGvB,MAAI,SAAS,WAAW;AACtB,SAAM,kBAAkB,IAAI,cAAc;AAC1C,SAAM,kBAAkB,MAAM;;AAIhC,MAAI,SAAS,IACX,KAAI;GAEF,MAAM,UAAU,IAAI,QAAQ,IAAI,UAAU,CADjB,CAAC,QAAQ,IACwB;AAC1D,SAAM,QAAQ,IAAI,cAAc;AAChC,SAAM,QAAQ,MAAM;UACd;AACN,UAAO,KAAK,kDAAkD;;AAKlE,QAAM,UAAU,IAAI,cAAc;AAClC,QAAM,UAAU,MAAM;EAGtB,MAAM,EAAE,gBAAgB,iBAAiB,MAAM,sBAAsB;GACnE;GACA,OAAO;GACP,SAAS,SAAS;GAClB,OAAO,QAAQ;GAChB,CAAC;AACF,MAAI,aAAa,SAAS,EACxB,QAAO,KACL,uBAAuB,aAAa,OAAO,0BAA0B,aAAa,WAAW,IAAI,KAAK,MACvG;EAGH,MAAM,gBAAgB,MAAM,YAAY,IAAI,eAAe;AAC3D,QAAM,YAAY,MAAM;AAExB,SAAO;GAAE;GAAY;GAAe;UAC7B,OAAO;AACd,SAAO,gBACL,kBACE,wHACA,MACD,CACF"}
1
+ {"version":3,"file":"stage.js","names":[],"sources":["../../src/workflows/stage.ts"],"sourcesContent":["import { logCollectedFiles, logErrorAndExit } from '../console/logging.js';\nimport { branchResolutionError, withOriginalError } from '../console/index.js';\nimport { logger } from '../console/logger.js';\nimport { Settings, TranslateFlags } from '../types/index.js';\nimport { gt } from '../utils/gt.js';\nimport { EnqueueFilesResult, FileToUpload } from 'generaltranslation/types';\nimport { UploadSourcesStep } from './steps/UploadSourcesStep.js';\nimport { SetupStep } from './steps/SetupStep.js';\nimport { EnqueueStep } from './steps/EnqueueStep.js';\nimport { BranchStep } from './steps/BranchStep.js';\nimport { TagStep } from './steps/TagStep.js';\nimport { UserEditDiffsStep } from './steps/UserEditDiffsStep.js';\nimport { BranchData } from '../types/branch.js';\nimport { calculateTimeoutMs } from '../utils/calculateTimeoutMs.js';\nimport { filterFilesForEnqueue } from './utils/filterFilesForEnqueue.js';\n\n/**\n * Sends multiple files for translation to the API using a workflow pattern\n * @param files - Array of file objects to translate\n * @param options - The options for the API call\n * @param settings - Settings configuration\n * @returns The translated content or version ID\n */\nexport async function runStageFilesWorkflow({\n files,\n options,\n settings,\n}: {\n files: FileToUpload[];\n options: TranslateFlags;\n settings: Settings;\n}): Promise<{\n branchData: BranchData;\n enqueueResult: EnqueueFilesResult;\n}> {\n try {\n // Log files to be translated\n logCollectedFiles(files);\n\n // Calculate timeout for setup step\n const timeoutMs = calculateTimeoutMs(options.timeout);\n\n // Create workflow with steps\n const branchStep = new BranchStep(gt, settings);\n const uploadStep = new UploadSourcesStep(gt, settings);\n const userEditDiffsStep = new UserEditDiffsStep(settings);\n const setupStep = new SetupStep(gt, settings, timeoutMs);\n const enqueueStep = new EnqueueStep(gt, settings, options.force);\n\n // first run the branch step\n const branchData = await branchStep.run();\n if (!branchData) {\n return logErrorAndExit(branchResolutionError);\n }\n\n // then run the upload step\n const uploadedFiles = await uploadStep.run({ files, branchData });\n\n // optionally run the user edit diffs step\n if (options?.saveLocal) {\n await userEditDiffsStep.run(uploadedFiles);\n }\n\n // then run the tag step (non-fatal — tagging failure should not block translations)\n if (settings.tag) {\n try {\n const userProvidedTag = !!options.tag;\n const tagStep = new TagStep(gt, settings, userProvidedTag);\n await tagStep.run(uploadedFiles);\n } catch {\n logger.warn('Failed to create translation tag. Continuing...');\n }\n }\n\n // then run the setup step\n await setupStep.run(uploadedFiles);\n\n // then run the enqueue step\n const { filesToEnqueue, skippedFiles } = await filterFilesForEnqueue({\n gt,\n files: uploadedFiles,\n locales: settings.locales,\n force: options.force,\n });\n if (skippedFiles.length > 0) {\n logger.info(\n `Skipped enqueue for ${skippedFiles.length} already translated file${skippedFiles.length === 1 ? '' : 's'}`\n );\n }\n\n const enqueueResult = await enqueueStep.run(filesToEnqueue);\n\n return { branchData, enqueueResult };\n } catch (error) {\n return logErrorAndExit(\n withOriginalError(\n 'Files could not be sent for translation. Check the files, branch configuration, and API credentials, then try again.',\n error\n )\n );\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAuBA,eAAsB,sBAAsB,EAC1C,OACA,SACA,YAQC;AACD,KAAI;AAEF,oBAAkB,MAAM;EAGxB,MAAM,YAAY,mBAAmB,QAAQ,QAAQ;EAGrD,MAAM,aAAa,IAAI,WAAW,IAAI,SAAS;EAC/C,MAAM,aAAa,IAAI,kBAAkB,IAAI,SAAS;EACtD,MAAM,oBAAoB,IAAI,kBAAkB,SAAS;EACzD,MAAM,YAAY,IAAI,UAAU,IAAI,UAAU,UAAU;EACxD,MAAM,cAAc,IAAI,YAAY,IAAI,UAAU,QAAQ,MAAM;EAGhE,MAAM,aAAa,MAAM,WAAW,KAAK;AACzC,MAAI,CAAC,WACH,QAAO,gBAAgB,sBAAsB;EAI/C,MAAM,gBAAgB,MAAM,WAAW,IAAI;GAAE;GAAO;GAAY,CAAC;AAGjE,MAAI,SAAS,UACX,OAAM,kBAAkB,IAAI,cAAc;AAI5C,MAAI,SAAS,IACX,KAAI;AAGF,SAAM,IADc,QAAQ,IAAI,UAAU,CADjB,CAAC,QAAQ,IAErB,CAAC,IAAI,cAAc;UAC1B;AACN,UAAO,KAAK,kDAAkD;;AAKlE,QAAM,UAAU,IAAI,cAAc;EAGlC,MAAM,EAAE,gBAAgB,iBAAiB,MAAM,sBAAsB;GACnE;GACA,OAAO;GACP,SAAS,SAAS;GAClB,OAAO,QAAQ;GAChB,CAAC;AACF,MAAI,aAAa,SAAS,EACxB,QAAO,KACL,uBAAuB,aAAa,OAAO,0BAA0B,aAAa,WAAW,IAAI,KAAK,MACvG;AAKH,SAAO;GAAE;GAAY,eAAA,MAFO,YAAY,IAAI,eAAe;GAEvB;UAC7B,OAAO;AACd,SAAO,gBACL,kBACE,wHACA,MACD,CACF"}
@@ -1,16 +1,14 @@
1
- import { WorkflowStep } from './WorkflowStep.js';
2
1
  import type { GT } from 'generaltranslation';
3
2
  import type { Settings } from '../../types/index.js';
4
3
  import { BranchData } from '../../types/branch.js';
5
4
  type BranchStepClient = Pick<GT, 'queryBranchData' | 'createBranch'>;
6
5
  type BranchStepSettings = Pick<Settings, 'branchOptions'>;
7
- export declare class BranchStep extends WorkflowStep<null, BranchData | null> {
6
+ export declare class BranchStep {
8
7
  private spinner;
9
8
  private branchData;
10
9
  private settings;
11
10
  private gt;
12
11
  constructor(gt: BranchStepClient, settings: BranchStepSettings);
13
12
  run(): Promise<BranchData | null>;
14
- wait(): Promise<void>;
15
13
  }
16
14
  export {};
@@ -1,17 +1,15 @@
1
1
  import { logger } from "../../console/logger.js";
2
2
  import { logErrorAndExit } from "../../console/logging.js";
3
- import { WorkflowStep } from "./WorkflowStep.js";
4
3
  import { getCheckedOutBranches, getCurrentBranch, getIncomingBranches } from "../../git/branches.js";
5
4
  import chalk from "chalk";
6
5
  import { ApiError } from "generaltranslation/errors";
7
6
  //#region src/workflows/steps/BranchStep.ts
8
- var BranchStep = class extends WorkflowStep {
7
+ var BranchStep = class {
9
8
  spinner = logger.createSpinner("dots");
10
9
  branchData;
11
10
  settings;
12
11
  gt;
13
12
  constructor(gt, settings) {
14
- super();
15
13
  this.gt = gt;
16
14
  this.settings = settings;
17
15
  this.branchData = {
@@ -110,7 +108,6 @@ var BranchStep = class extends WorkflowStep {
110
108
  this.spinner.stop(chalk.green("Branch information resolved successfully"));
111
109
  return this.branchData;
112
110
  }
113
- async wait() {}
114
111
  };
115
112
  //#endregion
116
113
  export { BranchStep };
@@ -1 +1 @@
1
- {"version":3,"file":"BranchStep.js","names":[],"sources":["../../../src/workflows/steps/BranchStep.ts"],"sourcesContent":["import { WorkflowStep } from './WorkflowStep.js';\nimport { logErrorAndExit } from '../../console/logging.js';\nimport { logger } from '../../console/logger.js';\nimport type { GT } from 'generaltranslation';\nimport type { Settings } from '../../types/index.js';\nimport chalk from 'chalk';\nimport {\n getCurrentBranch,\n getIncomingBranches,\n getCheckedOutBranches,\n} from '../../git/branches.js';\nimport { BranchData } from '../../types/branch.js';\nimport { ApiError } from 'generaltranslation/errors';\n\ntype BranchStepClient = Pick<GT, 'queryBranchData' | 'createBranch'>;\ntype BranchStepSettings = Pick<Settings, 'branchOptions'>;\n\n// Step 1: Resolve the current branch id & update API with branch information\nexport class BranchStep extends WorkflowStep<null, BranchData | null> {\n private spinner = logger.createSpinner('dots');\n private branchData: BranchData;\n private settings: BranchStepSettings;\n private gt: BranchStepClient;\n\n constructor(gt: BranchStepClient, settings: BranchStepSettings) {\n super();\n this.gt = gt;\n this.settings = settings;\n this.branchData = {\n currentBranch: {\n id: '',\n name: '',\n },\n incomingBranch: null,\n checkedOutBranch: null,\n };\n }\n\n async run(): Promise<BranchData | null> {\n this.spinner.start(`Resolving branch information...`);\n\n // First get some info about the branches we're working with\n let current: {\n currentBranchName: string;\n defaultBranch: boolean;\n } | null = null;\n let incoming: string[] = [];\n let checkedOut: string[] = [];\n let useDefaultBranch: boolean = true;\n let detectedDefaultBranchName: string = 'main';\n let autoDetectFailed = !this.settings.branchOptions.autoDetectBranches;\n\n if (\n this.settings.branchOptions.enabled &&\n this.settings.branchOptions.autoDetectBranches\n ) {\n const [currentResult, incomingResult, checkedOutResult] =\n await Promise.all([\n getCurrentBranch(this.settings.branchOptions.remoteName),\n getIncomingBranches(this.settings.branchOptions.remoteName),\n getCheckedOutBranches(this.settings.branchOptions.remoteName),\n ]);\n current = currentResult;\n incoming = incomingResult;\n checkedOut = checkedOutResult;\n\n if (currentResult) {\n detectedDefaultBranchName = currentResult.defaultBranchName;\n }\n\n // Try env var detection if git commands failed (e.g. Vercel)\n if (!currentResult) {\n autoDetectFailed = true;\n const vercelBranch = process.env.VERCEL_GIT_COMMIT_REF;\n if (vercelBranch) {\n current = { currentBranchName: vercelBranch, defaultBranch: false };\n }\n }\n\n // If detection succeeded, use the detected branch; otherwise fall back to default\n if (current) {\n useDefaultBranch = false;\n }\n }\n if (\n this.settings.branchOptions.enabled &&\n this.settings.branchOptions.currentBranch\n ) {\n current = {\n currentBranchName: this.settings.branchOptions.currentBranch,\n defaultBranch: current?.defaultBranch ?? false, // we have no way of knowing if this is the default branch without using the auto-detection logic\n };\n useDefaultBranch = false;\n }\n\n const branchData = await this.gt.queryBranchData({\n branchNames: [\n ...(current ? [current.currentBranchName] : []),\n ...incoming,\n ...checkedOut,\n ],\n });\n\n if (useDefaultBranch) {\n if (autoDetectFailed) {\n logger.warn(\n 'Branch auto-detection failed. Falling back to the default branch. Use --branch to specify a branch manually.'\n );\n }\n if (!branchData.defaultBranch) {\n const createBranchResult = await this.gt.createBranch({\n branchName: detectedDefaultBranchName,\n defaultBranch: true,\n });\n this.branchData.currentBranch = createBranchResult.branch;\n } else {\n this.branchData.currentBranch = branchData.defaultBranch;\n }\n } else {\n if (!current) {\n return logErrorAndExit(\n 'The current git branch could not be determined. Specify a custom branch or enable automatic branch detection.'\n );\n }\n const currentBranch = branchData.branches.find(\n (b) => b.name === current.currentBranchName\n );\n if (!currentBranch) {\n try {\n const createBranchResult = await this.gt.createBranch({\n branchName: current.currentBranchName,\n defaultBranch: current.defaultBranch,\n });\n this.branchData.currentBranch = createBranchResult.branch;\n } catch (error) {\n if (error instanceof ApiError && error.code === 403) {\n logger.warn(\n 'To enable translation branching, upgrade your plan. Falling back to default branch.'\n );\n // retry with default branch\n try {\n const createBranchResult = await this.gt.createBranch({\n branchName: detectedDefaultBranchName,\n defaultBranch: true,\n });\n this.branchData.currentBranch = createBranchResult.branch;\n } catch {\n // The fallback branch may already exist.\n }\n }\n }\n } else {\n this.branchData.currentBranch = currentBranch;\n }\n }\n\n if (this.branchData.currentBranch.id === '') {\n return logErrorAndExit(\n 'Something went wrong while resolving branch information. Try again.'\n );\n }\n\n // Now set the incoming and checked out branches (first one that exists)\n this.branchData.incomingBranch =\n incoming\n .map((b) => {\n const branch = branchData.branches.find((bb) => bb.name === b);\n if (branch) {\n return branch;\n } else {\n return null;\n }\n })\n .filter((b) => b !== null)[0] ?? null;\n this.branchData.checkedOutBranch =\n checkedOut\n .map((b) => {\n const branch = branchData.branches.find((bb) => bb.name === b);\n if (branch) {\n return branch;\n } else {\n return null;\n }\n })\n .filter((b) => b !== null)[0] ?? null;\n\n // ALWAYS fallback to default branch for checked out branch (to avoid retranslation)\n if (!this.branchData.checkedOutBranch && branchData.defaultBranch) {\n this.branchData.checkedOutBranch = branchData.defaultBranch;\n }\n\n this.spinner.stop(chalk.green('Branch information resolved successfully'));\n\n return this.branchData;\n }\n\n async wait(): Promise<void> {\n return;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"BranchStep.js","names":[],"sources":["../../../src/workflows/steps/BranchStep.ts"],"sourcesContent":["import { logErrorAndExit } from '../../console/logging.js';\nimport { logger } from '../../console/logger.js';\nimport type { GT } from 'generaltranslation';\nimport type { Settings } from '../../types/index.js';\nimport chalk from 'chalk';\nimport {\n getCurrentBranch,\n getIncomingBranches,\n getCheckedOutBranches,\n} from '../../git/branches.js';\nimport { BranchData } from '../../types/branch.js';\nimport { ApiError } from 'generaltranslation/errors';\n\ntype BranchStepClient = Pick<GT, 'queryBranchData' | 'createBranch'>;\ntype BranchStepSettings = Pick<Settings, 'branchOptions'>;\n\n// Step 1: Resolve the current branch id & update API with branch information\nexport class BranchStep {\n private spinner = logger.createSpinner('dots');\n private branchData: BranchData;\n private settings: BranchStepSettings;\n private gt: BranchStepClient;\n\n constructor(gt: BranchStepClient, settings: BranchStepSettings) {\n this.gt = gt;\n this.settings = settings;\n this.branchData = {\n currentBranch: {\n id: '',\n name: '',\n },\n incomingBranch: null,\n checkedOutBranch: null,\n };\n }\n\n async run(): Promise<BranchData | null> {\n this.spinner.start(`Resolving branch information...`);\n\n // First get some info about the branches we're working with\n let current: {\n currentBranchName: string;\n defaultBranch: boolean;\n } | null = null;\n let incoming: string[] = [];\n let checkedOut: string[] = [];\n let useDefaultBranch: boolean = true;\n let detectedDefaultBranchName: string = 'main';\n let autoDetectFailed = !this.settings.branchOptions.autoDetectBranches;\n\n if (\n this.settings.branchOptions.enabled &&\n this.settings.branchOptions.autoDetectBranches\n ) {\n const [currentResult, incomingResult, checkedOutResult] =\n await Promise.all([\n getCurrentBranch(this.settings.branchOptions.remoteName),\n getIncomingBranches(this.settings.branchOptions.remoteName),\n getCheckedOutBranches(this.settings.branchOptions.remoteName),\n ]);\n current = currentResult;\n incoming = incomingResult;\n checkedOut = checkedOutResult;\n\n if (currentResult) {\n detectedDefaultBranchName = currentResult.defaultBranchName;\n }\n\n // Try env var detection if git commands failed (e.g. Vercel)\n if (!currentResult) {\n autoDetectFailed = true;\n const vercelBranch = process.env.VERCEL_GIT_COMMIT_REF;\n if (vercelBranch) {\n current = { currentBranchName: vercelBranch, defaultBranch: false };\n }\n }\n\n // If detection succeeded, use the detected branch; otherwise fall back to default\n if (current) {\n useDefaultBranch = false;\n }\n }\n if (\n this.settings.branchOptions.enabled &&\n this.settings.branchOptions.currentBranch\n ) {\n current = {\n currentBranchName: this.settings.branchOptions.currentBranch,\n defaultBranch: current?.defaultBranch ?? false, // we have no way of knowing if this is the default branch without using the auto-detection logic\n };\n useDefaultBranch = false;\n }\n\n const branchData = await this.gt.queryBranchData({\n branchNames: [\n ...(current ? [current.currentBranchName] : []),\n ...incoming,\n ...checkedOut,\n ],\n });\n\n if (useDefaultBranch) {\n if (autoDetectFailed) {\n logger.warn(\n 'Branch auto-detection failed. Falling back to the default branch. Use --branch to specify a branch manually.'\n );\n }\n if (!branchData.defaultBranch) {\n const createBranchResult = await this.gt.createBranch({\n branchName: detectedDefaultBranchName,\n defaultBranch: true,\n });\n this.branchData.currentBranch = createBranchResult.branch;\n } else {\n this.branchData.currentBranch = branchData.defaultBranch;\n }\n } else {\n if (!current) {\n return logErrorAndExit(\n 'The current git branch could not be determined. Specify a custom branch or enable automatic branch detection.'\n );\n }\n const currentBranch = branchData.branches.find(\n (b) => b.name === current.currentBranchName\n );\n if (!currentBranch) {\n try {\n const createBranchResult = await this.gt.createBranch({\n branchName: current.currentBranchName,\n defaultBranch: current.defaultBranch,\n });\n this.branchData.currentBranch = createBranchResult.branch;\n } catch (error) {\n if (error instanceof ApiError && error.code === 403) {\n logger.warn(\n 'To enable translation branching, upgrade your plan. Falling back to default branch.'\n );\n // retry with default branch\n try {\n const createBranchResult = await this.gt.createBranch({\n branchName: detectedDefaultBranchName,\n defaultBranch: true,\n });\n this.branchData.currentBranch = createBranchResult.branch;\n } catch {\n // The fallback branch may already exist.\n }\n }\n }\n } else {\n this.branchData.currentBranch = currentBranch;\n }\n }\n\n if (this.branchData.currentBranch.id === '') {\n return logErrorAndExit(\n 'Something went wrong while resolving branch information. Try again.'\n );\n }\n\n // Now set the incoming and checked out branches (first one that exists)\n this.branchData.incomingBranch =\n incoming\n .map((b) => {\n const branch = branchData.branches.find((bb) => bb.name === b);\n if (branch) {\n return branch;\n } else {\n return null;\n }\n })\n .filter((b) => b !== null)[0] ?? null;\n this.branchData.checkedOutBranch =\n checkedOut\n .map((b) => {\n const branch = branchData.branches.find((bb) => bb.name === b);\n if (branch) {\n return branch;\n } else {\n return null;\n }\n })\n .filter((b) => b !== null)[0] ?? null;\n\n // ALWAYS fallback to default branch for checked out branch (to avoid retranslation)\n if (!this.branchData.checkedOutBranch && branchData.defaultBranch) {\n this.branchData.checkedOutBranch = branchData.defaultBranch;\n }\n\n this.spinner.stop(chalk.green('Branch information resolved successfully'));\n\n return this.branchData;\n }\n}\n"],"mappings":"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"}
@@ -1,4 +1,3 @@
1
- import { WorkflowStep } from './WorkflowStep.js';
2
1
  import { GT } from 'generaltranslation';
3
2
  import { Settings } from '../../types/index.js';
4
3
  import { FileStatusTracker } from './PollJobsStep.js';
@@ -7,7 +6,7 @@ export type DownloadTranslationsInput = {
7
6
  resolveOutputPath: (sourcePath: string, locale: string) => string | null;
8
7
  forceDownload?: boolean;
9
8
  };
10
- export declare class DownloadTranslationsStep extends WorkflowStep<DownloadTranslationsInput, boolean> {
9
+ export declare class DownloadTranslationsStep {
11
10
  private gt;
12
11
  private settings;
13
12
  private spinner;
@@ -15,5 +14,4 @@ export declare class DownloadTranslationsStep extends WorkflowStep<DownloadTrans
15
14
  run({ fileTracker, resolveOutputPath, forceDownload, }: DownloadTranslationsInput): Promise<boolean>;
16
15
  private downloadFiles;
17
16
  private downloadFilesWithRetry;
18
- wait(): Promise<void>;
19
17
  }
@@ -1,15 +1,13 @@
1
1
  import { logger } from "../../console/logger.js";
2
2
  import "../../utils/constants.js";
3
- import { WorkflowStep } from "./WorkflowStep.js";
4
3
  import { recordWarning } from "../../state/translateWarnings.js";
5
4
  import { downloadFileBatch } from "../../api/downloadFileBatch.js";
6
5
  import chalk from "chalk";
7
6
  import path from "node:path";
8
7
  //#region src/workflows/steps/DownloadStep.ts
9
- var DownloadTranslationsStep = class extends WorkflowStep {
8
+ var DownloadTranslationsStep = class {
10
9
  spinner = null;
11
10
  constructor(gt, settings) {
12
- super();
13
11
  this.gt = gt;
14
12
  this.settings = settings;
15
13
  }
@@ -119,7 +117,6 @@ var DownloadTranslationsStep = class extends WorkflowStep {
119
117
  skipped: allSkipped
120
118
  };
121
119
  }
122
- async wait() {}
123
120
  };
124
121
  //#endregion
125
122
  export { DownloadTranslationsStep };