gt 2.21.4 → 2.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +46 -0
- package/dist/api/collectUserEditDiffs.js +1 -1
- package/dist/auth/callbackPage.d.ts +1 -0
- package/dist/auth/callbackPage.js +77 -0
- package/dist/auth/callbackPage.js.map +1 -0
- package/dist/auth/credentialStore.d.ts +15 -0
- package/dist/auth/credentialStore.js +107 -0
- package/dist/auth/credentialStore.js.map +1 -0
- package/dist/auth/errors.d.ts +7 -0
- package/dist/auth/errors.js +23 -0
- package/dist/auth/errors.js.map +1 -0
- package/dist/auth/loopback.d.ts +9 -0
- package/dist/auth/loopback.js +73 -0
- package/dist/auth/loopback.js.map +1 -0
- package/dist/auth/loopback.test.d.ts +1 -0
- package/dist/auth/oauth.d.ts +39 -0
- package/dist/auth/oauth.js +260 -0
- package/dist/auth/oauth.js.map +1 -0
- package/dist/bin/bin-entry.js +2 -10
- package/dist/bin/bin-entry.js.map +1 -1
- package/dist/cli/base.d.ts +4 -8
- package/dist/cli/base.js +119 -60
- package/dist/cli/base.js.map +1 -1
- package/dist/cli/commands/api.js +6 -2
- package/dist/cli/commands/api.js.map +1 -1
- package/dist/cli/commands/upload.js +2 -2
- package/dist/cli/commands/upload.js.map +1 -1
- package/dist/cli/commands/utils/validation.d.ts +7 -7
- package/dist/cli/commands/utils/validation.js +7 -20
- package/dist/cli/commands/utils/validation.js.map +1 -1
- package/dist/config/generateSettings.js +4 -9
- package/dist/config/generateSettings.js.map +1 -1
- package/dist/config/optionPresets.js +16 -6
- package/dist/config/optionPresets.js.map +1 -1
- package/dist/config/validateSettings.d.ts +4 -2
- package/dist/config/validateSettings.js +9 -0
- package/dist/config/validateSettings.js.map +1 -1
- package/dist/console/index.d.ts +0 -2
- package/dist/console/index.js +2 -4
- package/dist/console/index.js.map +1 -1
- package/dist/console/inkPrompts.js +8 -6
- package/dist/console/inkPrompts.js.map +1 -1
- package/dist/console/inkTypes.d.ts +3 -0
- package/dist/console/logger.d.ts +13 -0
- package/dist/console/logger.js +60 -20
- package/dist/console/logger.js.map +1 -1
- package/dist/console/logging.d.ts +5 -3
- package/dist/console/logging.js +8 -6
- package/dist/console/logging.js.map +1 -1
- package/dist/console/promptParsing.d.ts +4 -3
- package/dist/console/promptParsing.js +7 -7
- package/dist/console/promptParsing.js.map +1 -1
- package/dist/formats/files/aggregateFiles.js +4 -4
- package/dist/formats/files/aggregateFiles.js.map +1 -1
- package/dist/formats/files/localeContent.js +2 -2
- package/dist/formats/files/localeContent.js.map +1 -1
- package/dist/formats/files/transformFormat.d.ts +2 -0
- package/dist/formats/files/transformFormat.js +8 -2
- package/dist/formats/files/transformFormat.js.map +1 -1
- package/dist/formats/json/extractJson.js +3 -3
- package/dist/formats/json/extractJson.js.map +1 -1
- package/dist/formats/json/mergeJson.js +6 -6
- package/dist/formats/json/mergeJson.js.map +1 -1
- package/dist/formats/xcstrings/mergeXcstrings.js +2 -2
- package/dist/formats/xcstrings/mergeXcstrings.js.map +1 -1
- package/dist/generated/version.d.ts +1 -1
- package/dist/generated/version.js +1 -1
- package/dist/generated/version.js.map +1 -1
- package/dist/git/setupMergeDrivers.js +1 -1
- package/dist/git/setupMergeDrivers.js.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/main.js +2 -10
- package/dist/main.js.map +1 -1
- package/dist/react/jsx/utils/jsxParsing/addGTIdentifierToSyntaxTree.js +1 -1
- package/dist/react/jsx/utils/jsxParsing/parseJsx.js +1 -1
- package/dist/react/jsx/utils/parseString.js +1 -1
- package/dist/react/jsx/utils/stringParsing/derivation/index.js +1 -1
- package/dist/setup/developmentCredentials.d.ts +8 -0
- package/dist/setup/developmentCredentials.js +82 -0
- package/dist/setup/developmentCredentials.js.map +1 -0
- package/dist/setup/setupViteSPA.js +1 -1
- package/dist/setup/setupViteSPA.js.map +1 -1
- package/dist/setup/userInput.d.ts +1 -0
- package/dist/setup/userInput.js +7 -2
- package/dist/setup/userInput.js.map +1 -1
- package/dist/translation/extractInline.js +1 -1
- package/dist/translation/extractInline.js.map +1 -1
- package/dist/types/index.d.ts +7 -2
- package/dist/utils/api.d.ts +146 -67
- package/dist/utils/api.js +5 -94
- package/dist/utils/api.js.map +1 -1
- package/dist/utils/credentials.d.ts +37 -10
- package/dist/utils/credentials.js +267 -58
- package/dist/utils/credentials.js.map +1 -1
- package/dist/utils/loadEnv.d.ts +2 -0
- package/dist/utils/loadEnv.js +24 -0
- package/dist/utils/loadEnv.js.map +1 -0
- package/dist/utils/localizeStaticUrls.js +34 -6
- package/dist/utils/localizeStaticUrls.js.map +1 -1
- package/dist/utils/processOpenApi.js +2 -2
- package/dist/utils/processOpenApi.js.map +1 -1
- package/dist/utils/reactPackageCompatibility.js +1 -1
- package/dist/utils/reactPackageCompatibility.js.map +1 -1
- package/dist/workflows/steps/PollJobsStep.js +40 -53
- package/dist/workflows/steps/PollJobsStep.js.map +1 -1
- package/dist/workflows/utils/syncFonts.js +2 -2
- package/dist/workflows/utils/syncFonts.js.map +1 -1
- package/package.json +8 -7
- package/dist/next/config/parseNextConfig.d.ts +0 -10
- package/dist/next/config/parseNextConfig.js +0 -34
- package/dist/next/config/parseNextConfig.js.map +0 -1
- package/dist/utils/fetch.d.ts +0 -11
- package/dist/utils/fetch.js +0 -24
- package/dist/utils/fetch.js.map +0 -1
- package/dist/utils/gt.d.ts +0 -2
- package/dist/utils/gt.js +0 -7
- package/dist/utils/gt.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../src/console/index.ts"],"sourcesContent":["import { createDiagnosticMessage } from 'generaltranslation/internal';\nimport { BRANCH_COMPONENT } from '../react/jsx/utils/constants.js';\nimport {\n colorizeFilepath,\n colorizeComponent,\n colorizeIdString,\n colorizeContent,\n colorizeLine,\n colorizeFunctionName,\n} from './colors.js';\nimport { formatCodeClamp } from './formatting.js';\n\nconst withWillErrorInNextVersion = (message: string): string =>\n `${message} (This will become an error in the next major version of the CLI.)`;\n\n// Derive function related errors\nconst withDeriveComponentError = (message: string): string =>\n `<Derive> rules violation: ${message}`;\n\nconst withDeriveFunctionError = (message: string): string =>\n `derive() rules violation: ${message}`;\n// Synchronous wrappers for backward compatibility\nexport const warnApiKeyInConfigSync = (optionsFilepath: string): string =>\n `${colorizeFilepath(\n optionsFilepath\n )}: Your API key is exposed! Remove it from the file and include it as an environment variable.`;\n\nexport const warnVariablePropSync = (\n file: string,\n attrName: string,\n value: string,\n location?: string\n): string =>\n withLocation(\n file,\n `${colorizeComponent('<T>')} component has dynamic attribute ${colorizeIdString(attrName)} with value: ${colorizeContent(\n value\n )}. Change ${colorizeIdString(attrName)} to ensure this content is translated.`,\n location\n );\n\nexport const warnInvalidReturnSync = (\n file: string,\n functionName: string,\n expression: string,\n location?: string\n): string =>\n withLocation(\n file,\n withDeriveComponentError(\n `Function ${colorizeFunctionName(functionName)} does not return a derivable (statically analyzable) expression. ${colorizeFunctionName(functionName)} must return either (1) a derivable string literal, (2) another derivable function invocation, (3) derivable JSX content, or (4) a ternary expression. Instead got:\\n${colorizeContent(expression)}`\n ),\n location\n );\n\n// TODO: this is temporary until we handle implicit returns\nexport const warnMissingReturnSync = (\n file: string,\n functionName: string,\n location?: string\n): string =>\n withLocation(\n file,\n `Function ${colorizeFunctionName(functionName)} is wrapped in ${colorizeComponent('<Derive>')} tags but does not have an explicit return statement. Derivable functions must have an explicit return statement.`,\n location\n );\n\nexport const warnHasUnwrappedExpressionSync = (\n file: string,\n unwrappedExpressions: string[],\n id?: string,\n location?: string\n): string =>\n withLocation(\n file,\n `${colorizeComponent('<T>')} component${\n id ? ` with id ${colorizeIdString(id)}` : ''\n } has children that could change at runtime. Use a variable component like ${colorizeComponent(\n '<Var>'\n )} to ensure this content is translated.\\n${colorizeContent(\n unwrappedExpressions.join('\\n')\n )}`,\n location\n );\n\nexport const warnFailedToConstructJsxTreeSync = (\n file: string,\n code: string,\n location?: string\n): string =>\n withLocation(\n file,\n `Failed to construct JsxTree! Call expression is not a valid createElement call: ${colorizeContent(code)}`,\n location\n );\n\nexport const warnNestedTComponent = (file: string, location?: string): string =>\n withLocation(\n file,\n `Found nested <T> component. <T> components cannot be directly nested.`,\n location\n );\n\nexport const warnNestedInternalTComponent = (\n file: string,\n location?: string\n): string =>\n withLocation(\n file,\n `DEBUG: Found nested <GtInternalTranslateJsx> component. <GtInternalTranslateJsx> components cannot be directly nested.`,\n location\n );\n\nexport const warnNonStaticExpressionSync = (\n file: string,\n attrName: string,\n value: string,\n location?: string\n): string =>\n withLocation(\n file,\n `Found non-static expression for attribute ${colorizeIdString(\n attrName\n )}: ${colorizeContent(value)}. Change \"${colorizeIdString(attrName)}\" to ensure this content is translated.`,\n location\n );\n\nexport const warnInvalidMaxCharsSync = (\n file: string,\n value: string,\n location?: string\n): string =>\n withLocation(\n file,\n `Found invalid maxChars value: ${colorizeContent(value)}. maxChars must be a numeric literal, e.g. maxChars={10}, to ensure this content is translated.`,\n location\n );\n\nexport const warnDeprecatedTSugarPropsSync = (locations: string[]): string =>\n createDiagnosticMessage({\n whatHappened: `Found ${locations.length} deprecated ${colorizeIdString(\n '$'\n )}-prefixed prop${locations.length === 1 ? '' : 's'} on ${colorizeComponent(\n '<T>'\n )} components`,\n fix: `Use the unprefixed forms instead (${colorizeIdString(\n 'context'\n )}, ${colorizeIdString('id')}, ${colorizeIdString('maxChars')}, ${colorizeIdString(\n 'requiresReview'\n )}); support for the ${colorizeIdString('$')}-prefixed forms will be removed in the next major version`,\n }) +\n '\\n' +\n locations.map((location) => ` ${colorizeLine(location)}`).join('\\n');\n\nexport const warnInvalidFormatSync = (\n file: string,\n value: string,\n location?: string\n): string =>\n withLocation(\n file,\n `Found invalid $format value: ${colorizeContent(value)}. Must be one of: 'ICU', 'STRING', 'I18NEXT'.`,\n location\n );\n\nexport const warnInvalidRequiresReviewSync = (\n file: string,\n value: string,\n location?: string\n): string =>\n withLocation(\n file,\n `Found invalid requiresReview value: ${colorizeContent(value)}. Must be a boolean literal (true or false) — strings and dynamic expressions are not allowed.`,\n location\n );\n\nexport const warnInvalidIcuSync = (\n file: string,\n value: string,\n error: string,\n location?: string\n): string =>\n withWillErrorInNextVersion(\n withLocation(\n file,\n `Found invalid ICU string: ${colorizeContent(value)}. Change the value to a valid ICU to ensure this content is translated. Error message: ${error}.`,\n location\n )\n );\n\nexport const warnTemplateLiteralSync = (\n file: string,\n value: string,\n location?: string\n): string =>\n withLocation(\n file,\n `Found template literal with quasis (${colorizeContent(value)}). Change the template literal to a string to ensure this content is translated.`,\n location\n );\n\nexport const warnNonStringSync = (\n file: string,\n value: string,\n location?: string\n): string =>\n withLocation(\n file,\n `Found non-string literal (${colorizeContent(value)}). Change the value to a string literal to ensure this content is translated.`,\n location\n );\n\nexport const warnAsyncUseGT = (file: string, location?: string): string =>\n withLocation(\n file,\n `Found useGT() in an async function. Use getGT() instead, or make the function synchronous.`,\n location\n );\n\nexport const warnSyncGetGT = (file: string, location?: string): string =>\n withLocation(\n file,\n `Found getGT() in a synchronous function. Use useGT() instead, or make the function async.`,\n location\n );\n\nexport const warnTernarySync = (file: string, location?: string): string =>\n withLocation(\n file,\n 'Found ternary expression. A Branch component may be more appropriate here.',\n location\n );\n\nexport const withLocation = (\n file: string,\n message: string,\n location?: string\n): string =>\n `${colorizeFilepath(file)}${location ? ` (${colorizeLine(location)})` : ''}: ${message}`;\n\nexport const warnFunctionNotFoundSync = (\n file: string,\n functionName: string,\n location?: string\n): string =>\n withLocation(\n file,\n `Function ${colorizeFunctionName(functionName)} definition could not be resolved. This might affect translation resolution for this ${colorizeComponent('<T>')} component.`,\n location\n );\n\nexport const warnInvalidDeclareVarNameSync = (\n file: string,\n value: string,\n location?: string\n): string =>\n withLocation(\n file,\n `Found invalid declareVar() $name tag. Must be a derivable (statically analyzable) expression. Received: ${colorizeContent(value)}.`,\n location\n );\n\nexport const warnDuplicateFunctionDefinitionSync = (\n file: string,\n functionName: string,\n location?: string\n): string =>\n withLocation(\n file,\n `Function ${colorizeFunctionName(functionName)} is defined multiple times. Only the first definition will be used.`,\n location\n );\n\nexport const warnInvalidDeriveInitSync = (\n file: string,\n functionName: string,\n location?: string\n): string =>\n withLocation(\n file,\n withDeriveComponentError(\n `The definition for ${colorizeFunctionName(functionName)} could not be resolved. When using arrow syntax to define a derivable (statically analyzable) function, the right hand side or the assignment MUST only contain the arrow function itself and no other expressions.\nExample: ${colorizeContent(`const ${colorizeFunctionName(functionName)} = () => { ... }`)}\nInvalid: ${colorizeContent(`const ${colorizeFunctionName(functionName)} = [() => { ... }][0]`)}`\n ),\n location\n );\n\nexport const warnDataAttrOnBranch = (\n file: string,\n attrName: string,\n location?: string\n): string =>\n withLocation(\n file,\n `${colorizeComponent(`<${BRANCH_COMPONENT}>`)} component ignores attributes prefixed with ${colorizeIdString('\"data-\"')}. Found ${colorizeIdString(attrName)}. Remove it or use a different attribute name.`,\n location\n );\n\nexport const warnRecursiveFunctionCallSync = (\n file: string,\n functionName: string,\n location?: string\n): string =>\n withLocation(\n file,\n withDeriveComponentError(\n `Recursive function call detected: ${colorizeFunctionName(functionName)}. A derivable (statically analyzable) function cannot use recursive calls to construct its result.`\n ),\n location\n );\n\nexport const warnDeriveFunctionNotWrappedSync = (\n file: string,\n functionName: string,\n location?: string\n): string =>\n withLocation(\n file,\n withDeriveFunctionError(\n `Could not resolve ${colorizeFunctionName(formatCodeClamp(functionName))}. This call is not wrapped in derive(). Ensure the function is properly wrapped with derive() and does not have circular import dependencies.`\n ),\n location\n );\n\nexport const warnDeriveNonConstVariableSync = (\n file: string,\n varName: string,\n kind: string,\n location?: string\n): string =>\n withLocation(\n file,\n withDeriveFunctionError(\n `Variable ${colorizeFunctionName(varName)} is declared with '${kind}' but only 'const' declarations can be resolved statically. Change it to 'const'.`\n ),\n location\n );\n\nexport const warnDeriveFunctionNoResultsSync = (\n file: string,\n functionName: string,\n location?: string\n): string =>\n withLocation(\n file,\n withDeriveFunctionError(\n `Could not resolve ${colorizeFunctionName(formatCodeClamp(functionName))}. derive() can only receive function invocations and cannot use undefined values or looped calls to construct its result.`\n ),\n location\n );\n\nexport const warnAutoderiveNoResultsSync = (\n file: string,\n expression: string,\n location?: string\n): string =>\n withLocation(\n file,\n `Autoderive could not resolve ${colorizeFunctionName(formatCodeClamp(expression))}. Only function calls with statically determinable return values can be used directly in t(). Consider wrapping with derive() for explicit derivation, or use an interpolation variable instead.`,\n location\n );\n\nexport const warnDeriveUnresolvableValueSync = (\n file: string,\n key: string,\n location?: string\n): string =>\n withLocation(\n file,\n withDeriveFunctionError(\n `Object property ${colorizeFunctionName(formatCodeClamp(key))} could not be resolved to a static string value. Only string literals, template literals, conditionals, and function calls returning strings are supported.`\n ),\n location\n );\n\nexport const warnDeriveCircularSpreadSync = (\n file: string,\n varName: string,\n location?: string\n): string =>\n withLocation(\n file,\n withDeriveFunctionError(\n `Circular spread detected involving ${colorizeFunctionName(varName)}. Spread references that form a cycle cannot be resolved statically.`\n ),\n location\n );\n\nexport const warnDeriveDestructuringSync = (\n file: string,\n varName: string,\n location?: string\n): string =>\n withLocation(\n file,\n withDeriveFunctionError(\n `Variable ${colorizeFunctionName(varName)} uses destructuring syntax, which is not yet supported in derive(). Assign the value to a const variable directly instead.`\n ),\n location\n );\n\nexport const warnDeriveOptionalChainingSync = (\n file: string,\n code: string,\n location?: string\n): string =>\n withLocation(\n file,\n withDeriveFunctionError(\n `Optional chaining (${colorizeFunctionName(formatCodeClamp(code))}) is not supported in derive(). Optional chaining implies the value could be undefined, which cannot be resolved statically. Use a non-optional access instead.`\n ),\n location\n );\n\nexport const warnUnresolvedImportSync = (\n file: string,\n functionName: string,\n importPath: string,\n location?: string\n): string =>\n withLocation(\n file,\n `Could not resolve import ${colorizeFunctionName(importPath)} for function ${colorizeFunctionName(functionName)}. Translation strings inside this function will not be extracted.`,\n location\n );\n\n// Re-export error messages\nexport const noLocalesError = `No target locales were found. Add locales to gt.config.json or pass them with the --locales flag.`;\nexport const noDefaultLocaleError = `No default locale was found. Add defaultLocale to gt.config.json or pass it with --default-locale.`;\nexport const noFilesError = `The files configuration is missing or invalid. Check the files section in gt.config.json and try again.`;\nexport const noSourceFileError = `No source translation file was found. Check your translations directory and default locale configuration.`;\nexport const noApiKeyError = `No API key was found. Pass --api-key or set the GT_API_KEY environment variable.`;\nexport const devApiKeyError = `Development API keys cannot be used with the General Translation API. Use a production API key instead.\\nGenerate a production API key with: npx gt auth -t production`;\nexport const noProjectIdError = `No project ID was found. Pass --project-id, add projectId to gt.config.json, or set the GT_PROJECT_ID environment variable.`;\nexport const noVersionIdError = `No version ID was found. Pass --version-id or add _versionId to gt.config.json.`;\nexport const invalidConfigurationError = `The files configuration cannot be used for this operation. Provide a valid download configuration or set --publish true to upload translations to the CDN.`;\nexport const lottieTranslateError = `Lottie translations are processed asynchronously, so the translate command cannot complete them in one run. Use the stage and download flow instead:\\n 1. Stage the files for translation: npx gt stage\\n 2. Fetch the finished translations: npx gt download\\nTranslations that are still processing are skipped, so re-run npx gt download until all of them have been downloaded.`;\nexport const branchResolutionError = `The current git branch could not be resolved. Specify a branch explicitly or run the command from a git worktree with branch metadata available.`;\n\nexport const lottieExpressionsError = (files: string[]): string =>\n `The following Lottie file(s) use After Effects expressions, which contain executable code and are not supported yet:\\n${files\n .map((file) => ` - ${file}`)\n .join(\n '\\n'\n )}\\nRe-export the animation with expressions baked into keyframes (or removed), then try again.`;\n\nexport const xcstringsSourceLanguageMismatchError = (\n catalogs: { file: string; sourceLanguage: string }[],\n defaultLocale: string\n): string =>\n `The following .xcstrings catalog(s) declare a sourceLanguage that does not match the configured defaultLocale \"${defaultLocale}\":\\n${catalogs\n .map(\n ({ file, sourceLanguage }) =>\n ` - ${file} (sourceLanguage \"${sourceLanguage}\")`\n )\n .join(\n '\\n'\n )}\\nSet defaultLocale in gt.config.json to the catalog's sourceLanguage, or change the catalog's source language in Xcode, then try again.`;\n\nexport const fileEncodingSkipReason = (error: unknown): string =>\n `File could not be decoded: ${error instanceof Error ? error.message : String(error)}`;\n\nexport const withOriginalError = (message: string, error: unknown): string =>\n error != null ? `${message} Original error: ${String(error)}` : message;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/console/index.ts"],"sourcesContent":["import { createDiagnosticMessage } from 'generaltranslation/diagnostics';\nimport { BRANCH_COMPONENT } from '../react/jsx/utils/constants.js';\nimport {\n colorizeFilepath,\n colorizeComponent,\n colorizeIdString,\n colorizeContent,\n colorizeLine,\n colorizeFunctionName,\n} from './colors.js';\nimport { formatCodeClamp } from './formatting.js';\n\nconst withWillErrorInNextVersion = (message: string): string =>\n `${message} (This will become an error in the next major version of the CLI.)`;\n\n// Derive function related errors\nconst withDeriveComponentError = (message: string): string =>\n `<Derive> rules violation: ${message}`;\n\nconst withDeriveFunctionError = (message: string): string =>\n `derive() rules violation: ${message}`;\n// Synchronous wrappers for backward compatibility\nexport const warnApiKeyInConfigSync = (optionsFilepath: string): string =>\n `${colorizeFilepath(\n optionsFilepath\n )}: Your API key is exposed! Remove it from the file and include it as an environment variable.`;\n\nexport const warnVariablePropSync = (\n file: string,\n attrName: string,\n value: string,\n location?: string\n): string =>\n withLocation(\n file,\n `${colorizeComponent('<T>')} component has dynamic attribute ${colorizeIdString(attrName)} with value: ${colorizeContent(\n value\n )}. Change ${colorizeIdString(attrName)} to ensure this content is translated.`,\n location\n );\n\nexport const warnInvalidReturnSync = (\n file: string,\n functionName: string,\n expression: string,\n location?: string\n): string =>\n withLocation(\n file,\n withDeriveComponentError(\n `Function ${colorizeFunctionName(functionName)} does not return a derivable (statically analyzable) expression. ${colorizeFunctionName(functionName)} must return either (1) a derivable string literal, (2) another derivable function invocation, (3) derivable JSX content, or (4) a ternary expression. Instead got:\\n${colorizeContent(expression)}`\n ),\n location\n );\n\n// TODO: this is temporary until we handle implicit returns\nexport const warnMissingReturnSync = (\n file: string,\n functionName: string,\n location?: string\n): string =>\n withLocation(\n file,\n `Function ${colorizeFunctionName(functionName)} is wrapped in ${colorizeComponent('<Derive>')} tags but does not have an explicit return statement. Derivable functions must have an explicit return statement.`,\n location\n );\n\nexport const warnHasUnwrappedExpressionSync = (\n file: string,\n unwrappedExpressions: string[],\n id?: string,\n location?: string\n): string =>\n withLocation(\n file,\n `${colorizeComponent('<T>')} component${\n id ? ` with id ${colorizeIdString(id)}` : ''\n } has children that could change at runtime. Use a variable component like ${colorizeComponent(\n '<Var>'\n )} to ensure this content is translated.\\n${colorizeContent(\n unwrappedExpressions.join('\\n')\n )}`,\n location\n );\n\nexport const warnFailedToConstructJsxTreeSync = (\n file: string,\n code: string,\n location?: string\n): string =>\n withLocation(\n file,\n `Failed to construct JsxTree! Call expression is not a valid createElement call: ${colorizeContent(code)}`,\n location\n );\n\nexport const warnNestedTComponent = (file: string, location?: string): string =>\n withLocation(\n file,\n `Found nested <T> component. <T> components cannot be directly nested.`,\n location\n );\n\nexport const warnNestedInternalTComponent = (\n file: string,\n location?: string\n): string =>\n withLocation(\n file,\n `DEBUG: Found nested <GtInternalTranslateJsx> component. <GtInternalTranslateJsx> components cannot be directly nested.`,\n location\n );\n\nexport const warnNonStaticExpressionSync = (\n file: string,\n attrName: string,\n value: string,\n location?: string\n): string =>\n withLocation(\n file,\n `Found non-static expression for attribute ${colorizeIdString(\n attrName\n )}: ${colorizeContent(value)}. Change \"${colorizeIdString(attrName)}\" to ensure this content is translated.`,\n location\n );\n\nexport const warnInvalidMaxCharsSync = (\n file: string,\n value: string,\n location?: string\n): string =>\n withLocation(\n file,\n `Found invalid maxChars value: ${colorizeContent(value)}. maxChars must be a numeric literal, e.g. maxChars={10}, to ensure this content is translated.`,\n location\n );\n\nexport const warnDeprecatedTSugarPropsSync = (locations: string[]): string =>\n createDiagnosticMessage({\n whatHappened: `Found ${locations.length} deprecated ${colorizeIdString(\n '$'\n )}-prefixed prop${locations.length === 1 ? '' : 's'} on ${colorizeComponent(\n '<T>'\n )} components`,\n fix: `Use the unprefixed forms instead (${colorizeIdString(\n 'context'\n )}, ${colorizeIdString('id')}, ${colorizeIdString('maxChars')}, ${colorizeIdString(\n 'requiresReview'\n )}); support for the ${colorizeIdString('$')}-prefixed forms will be removed in the next major version`,\n }) +\n '\\n' +\n locations.map((location) => ` ${colorizeLine(location)}`).join('\\n');\n\nexport const warnInvalidFormatSync = (\n file: string,\n value: string,\n location?: string\n): string =>\n withLocation(\n file,\n `Found invalid $format value: ${colorizeContent(value)}. Must be one of: 'ICU', 'STRING', 'I18NEXT'.`,\n location\n );\n\nexport const warnInvalidRequiresReviewSync = (\n file: string,\n value: string,\n location?: string\n): string =>\n withLocation(\n file,\n `Found invalid requiresReview value: ${colorizeContent(value)}. Must be a boolean literal (true or false) — strings and dynamic expressions are not allowed.`,\n location\n );\n\nexport const warnInvalidIcuSync = (\n file: string,\n value: string,\n error: string,\n location?: string\n): string =>\n withWillErrorInNextVersion(\n withLocation(\n file,\n `Found invalid ICU string: ${colorizeContent(value)}. Change the value to a valid ICU to ensure this content is translated. Error message: ${error}.`,\n location\n )\n );\n\nexport const warnTemplateLiteralSync = (\n file: string,\n value: string,\n location?: string\n): string =>\n withLocation(\n file,\n `Found template literal with quasis (${colorizeContent(value)}). Change the template literal to a string to ensure this content is translated.`,\n location\n );\n\nexport const warnNonStringSync = (\n file: string,\n value: string,\n location?: string\n): string =>\n withLocation(\n file,\n `Found non-string literal (${colorizeContent(value)}). Change the value to a string literal to ensure this content is translated.`,\n location\n );\n\nexport const warnAsyncUseGT = (file: string, location?: string): string =>\n withLocation(\n file,\n `Found useGT() in an async function. Use getGT() instead, or make the function synchronous.`,\n location\n );\n\nexport const warnSyncGetGT = (file: string, location?: string): string =>\n withLocation(\n file,\n `Found getGT() in a synchronous function. Use useGT() instead, or make the function async.`,\n location\n );\n\nexport const warnTernarySync = (file: string, location?: string): string =>\n withLocation(\n file,\n 'Found ternary expression. A Branch component may be more appropriate here.',\n location\n );\n\nexport const withLocation = (\n file: string,\n message: string,\n location?: string\n): string =>\n `${colorizeFilepath(file)}${location ? ` (${colorizeLine(location)})` : ''}: ${message}`;\n\nexport const warnFunctionNotFoundSync = (\n file: string,\n functionName: string,\n location?: string\n): string =>\n withLocation(\n file,\n `Function ${colorizeFunctionName(functionName)} definition could not be resolved. This might affect translation resolution for this ${colorizeComponent('<T>')} component.`,\n location\n );\n\nexport const warnInvalidDeclareVarNameSync = (\n file: string,\n value: string,\n location?: string\n): string =>\n withLocation(\n file,\n `Found invalid declareVar() $name tag. Must be a derivable (statically analyzable) expression. Received: ${colorizeContent(value)}.`,\n location\n );\n\nexport const warnDuplicateFunctionDefinitionSync = (\n file: string,\n functionName: string,\n location?: string\n): string =>\n withLocation(\n file,\n `Function ${colorizeFunctionName(functionName)} is defined multiple times. Only the first definition will be used.`,\n location\n );\n\nexport const warnInvalidDeriveInitSync = (\n file: string,\n functionName: string,\n location?: string\n): string =>\n withLocation(\n file,\n withDeriveComponentError(\n `The definition for ${colorizeFunctionName(functionName)} could not be resolved. When using arrow syntax to define a derivable (statically analyzable) function, the right hand side or the assignment MUST only contain the arrow function itself and no other expressions.\nExample: ${colorizeContent(`const ${colorizeFunctionName(functionName)} = () => { ... }`)}\nInvalid: ${colorizeContent(`const ${colorizeFunctionName(functionName)} = [() => { ... }][0]`)}`\n ),\n location\n );\n\nexport const warnDataAttrOnBranch = (\n file: string,\n attrName: string,\n location?: string\n): string =>\n withLocation(\n file,\n `${colorizeComponent(`<${BRANCH_COMPONENT}>`)} component ignores attributes prefixed with ${colorizeIdString('\"data-\"')}. Found ${colorizeIdString(attrName)}. Remove it or use a different attribute name.`,\n location\n );\n\nexport const warnRecursiveFunctionCallSync = (\n file: string,\n functionName: string,\n location?: string\n): string =>\n withLocation(\n file,\n withDeriveComponentError(\n `Recursive function call detected: ${colorizeFunctionName(functionName)}. A derivable (statically analyzable) function cannot use recursive calls to construct its result.`\n ),\n location\n );\n\nexport const warnDeriveFunctionNotWrappedSync = (\n file: string,\n functionName: string,\n location?: string\n): string =>\n withLocation(\n file,\n withDeriveFunctionError(\n `Could not resolve ${colorizeFunctionName(formatCodeClamp(functionName))}. This call is not wrapped in derive(). Ensure the function is properly wrapped with derive() and does not have circular import dependencies.`\n ),\n location\n );\n\nexport const warnDeriveNonConstVariableSync = (\n file: string,\n varName: string,\n kind: string,\n location?: string\n): string =>\n withLocation(\n file,\n withDeriveFunctionError(\n `Variable ${colorizeFunctionName(varName)} is declared with '${kind}' but only 'const' declarations can be resolved statically. Change it to 'const'.`\n ),\n location\n );\n\nexport const warnDeriveFunctionNoResultsSync = (\n file: string,\n functionName: string,\n location?: string\n): string =>\n withLocation(\n file,\n withDeriveFunctionError(\n `Could not resolve ${colorizeFunctionName(formatCodeClamp(functionName))}. derive() can only receive function invocations and cannot use undefined values or looped calls to construct its result.`\n ),\n location\n );\n\nexport const warnAutoderiveNoResultsSync = (\n file: string,\n expression: string,\n location?: string\n): string =>\n withLocation(\n file,\n `Autoderive could not resolve ${colorizeFunctionName(formatCodeClamp(expression))}. Only function calls with statically determinable return values can be used directly in t(). Consider wrapping with derive() for explicit derivation, or use an interpolation variable instead.`,\n location\n );\n\nexport const warnDeriveUnresolvableValueSync = (\n file: string,\n key: string,\n location?: string\n): string =>\n withLocation(\n file,\n withDeriveFunctionError(\n `Object property ${colorizeFunctionName(formatCodeClamp(key))} could not be resolved to a static string value. Only string literals, template literals, conditionals, and function calls returning strings are supported.`\n ),\n location\n );\n\nexport const warnDeriveCircularSpreadSync = (\n file: string,\n varName: string,\n location?: string\n): string =>\n withLocation(\n file,\n withDeriveFunctionError(\n `Circular spread detected involving ${colorizeFunctionName(varName)}. Spread references that form a cycle cannot be resolved statically.`\n ),\n location\n );\n\nexport const warnDeriveDestructuringSync = (\n file: string,\n varName: string,\n location?: string\n): string =>\n withLocation(\n file,\n withDeriveFunctionError(\n `Variable ${colorizeFunctionName(varName)} uses destructuring syntax, which is not yet supported in derive(). Assign the value to a const variable directly instead.`\n ),\n location\n );\n\nexport const warnDeriveOptionalChainingSync = (\n file: string,\n code: string,\n location?: string\n): string =>\n withLocation(\n file,\n withDeriveFunctionError(\n `Optional chaining (${colorizeFunctionName(formatCodeClamp(code))}) is not supported in derive(). Optional chaining implies the value could be undefined, which cannot be resolved statically. Use a non-optional access instead.`\n ),\n location\n );\n\nexport const warnUnresolvedImportSync = (\n file: string,\n functionName: string,\n importPath: string,\n location?: string\n): string =>\n withLocation(\n file,\n `Could not resolve import ${colorizeFunctionName(importPath)} for function ${colorizeFunctionName(functionName)}. Translation strings inside this function will not be extracted.`,\n location\n );\n\n// Re-export error messages\nexport const noLocalesError = `No target locales were found. Add locales to gt.config.json or pass them with the --locales flag.`;\nexport const noDefaultLocaleError = `No default locale was found. Add defaultLocale to gt.config.json or pass it with --default-locale.`;\nexport const noFilesError = `The files configuration is missing or invalid. Check the files section in gt.config.json and try again.`;\nexport const noSourceFileError = `No source translation file was found. Check your translations directory and default locale configuration.`;\nexport const noProjectIdError = `No project ID was found. Pass --project-id, add projectId to gt.config.json, or set the GT_PROJECT_ID environment variable.`;\nexport const noVersionIdError = `No version ID was found. Pass --version-id or add _versionId to gt.config.json.`;\nexport const invalidConfigurationError = `The files configuration cannot be used for this operation. Provide a valid download configuration or set --publish true to upload translations to the CDN.`;\nexport const lottieTranslateError = `Lottie translations are processed asynchronously, so the translate command cannot complete them in one run. Use the stage and download flow instead:\\n 1. Stage the files for translation: npx gt stage\\n 2. Fetch the finished translations: npx gt download\\nTranslations that are still processing are skipped, so re-run npx gt download until all of them have been downloaded.`;\nexport const branchResolutionError = `The current git branch could not be resolved. Specify a branch explicitly or run the command from a git worktree with branch metadata available.`;\n\nexport const lottieExpressionsError = (files: string[]): string =>\n `The following Lottie file(s) use After Effects expressions, which contain executable code and are not supported yet:\\n${files\n .map((file) => ` - ${file}`)\n .join(\n '\\n'\n )}\\nRe-export the animation with expressions baked into keyframes (or removed), then try again.`;\n\nexport const xcstringsSourceLanguageMismatchError = (\n catalogs: { file: string; sourceLanguage: string }[],\n defaultLocale: string\n): string =>\n `The following .xcstrings catalog(s) declare a sourceLanguage that does not match the configured defaultLocale \"${defaultLocale}\":\\n${catalogs\n .map(\n ({ file, sourceLanguage }) =>\n ` - ${file} (sourceLanguage \"${sourceLanguage}\")`\n )\n .join(\n '\\n'\n )}\\nSet defaultLocale in gt.config.json to the catalog's sourceLanguage, or change the catalog's source language in Xcode, then try again.`;\n\nexport const fileEncodingSkipReason = (error: unknown): string =>\n `File could not be decoded: ${error instanceof Error ? error.message : String(error)}`;\n\nexport const withOriginalError = (message: string, error: unknown): string =>\n error != null ? `${message} Original error: ${String(error)}` : message;\n"],"mappings":"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"}
|
|
@@ -10,9 +10,9 @@ import { getSupportedLocale } from "@generaltranslation/supported-locales";
|
|
|
10
10
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
11
11
|
import { useState } from "react";
|
|
12
12
|
//#region src/console/inkPrompts.tsx
|
|
13
|
-
function resolveLocaleChoice({ query, highlightedLocale, preferHighlightedLocale }) {
|
|
13
|
+
function resolveLocaleChoice({ query, highlightedLocale, preferHighlightedLocale, customMapping }) {
|
|
14
14
|
if (preferHighlightedLocale) return highlightedLocale;
|
|
15
|
-
return parseTypedLocale(query) ?? highlightedLocale;
|
|
15
|
+
return parseTypedLocale(query, customMapping) ?? highlightedLocale;
|
|
16
16
|
}
|
|
17
17
|
function TextPrompt({ message, defaultValue, validate, onComplete, footer = "type to edit enter select esc cancel", placeholder }) {
|
|
18
18
|
const { columns } = useTerminalSize();
|
|
@@ -59,7 +59,7 @@ function TextPrompt({ message, defaultValue, validate, onComplete, footer = "typ
|
|
|
59
59
|
}) : null]
|
|
60
60
|
});
|
|
61
61
|
}
|
|
62
|
-
function LocalePrompt({ message, defaultValue, onComplete }) {
|
|
62
|
+
function LocalePrompt({ message, defaultValue, customMapping, onComplete }) {
|
|
63
63
|
const { columns, rows } = useTerminalSize();
|
|
64
64
|
const localeOptions = getLocaleOptions();
|
|
65
65
|
const defaultLocale = defaultValue ? getSupportedLocale(defaultValue) : null;
|
|
@@ -104,7 +104,8 @@ function LocalePrompt({ message, defaultValue, onComplete }) {
|
|
|
104
104
|
const finalLocale = resolveLocaleChoice({
|
|
105
105
|
query,
|
|
106
106
|
highlightedLocale: filteredOptions[activeIndex]?.code,
|
|
107
|
-
preferHighlightedLocale
|
|
107
|
+
preferHighlightedLocale,
|
|
108
|
+
customMapping
|
|
108
109
|
});
|
|
109
110
|
if (!finalLocale) {
|
|
110
111
|
setError("Enter a valid locale (e.g., en)");
|
|
@@ -148,7 +149,7 @@ function LocalePrompt({ message, defaultValue, onComplete }) {
|
|
|
148
149
|
]
|
|
149
150
|
});
|
|
150
151
|
}
|
|
151
|
-
function LocaleMultiPrompt({ message, defaultValue = [], required, onComplete }) {
|
|
152
|
+
function LocaleMultiPrompt({ message, defaultValue = [], required, customMapping, onComplete }) {
|
|
152
153
|
const { columns, rows } = useTerminalSize();
|
|
153
154
|
const [query, setQuery] = useState("");
|
|
154
155
|
const [index, setIndex] = useState(0);
|
|
@@ -184,7 +185,8 @@ function LocaleMultiPrompt({ message, defaultValue = [], required, onComplete })
|
|
|
184
185
|
const selectedLocale = resolveLocaleChoice({
|
|
185
186
|
query,
|
|
186
187
|
highlightedLocale: filteredOptions[activeOptionIndex]?.code,
|
|
187
|
-
preferHighlightedLocale
|
|
188
|
+
preferHighlightedLocale,
|
|
189
|
+
customMapping
|
|
188
190
|
});
|
|
189
191
|
if (!selectedLocale) {
|
|
190
192
|
setError("Enter a valid locale (e.g., es fr de)");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inkPrompts.js","names":[],"sources":["../../src/console/inkPrompts.tsx"],"sourcesContent":["import { useState } from 'react';\nimport { Box, Text, useInput } from 'ink';\nimport { getSupportedLocale } from '@generaltranslation/supported-locales';\nimport {\n OptionRow,\n LocaleOptionsList,\n RemainingMatches,\n SelectedTags,\n} from './inkFields.js';\nimport { getFilteredLocaleOptions, getLocaleOptions } from './inkLocaleData.js';\nimport { InputBox, PromptFrame } from './inkLayout.js';\nimport { runPrompt } from './inkSession.js';\nimport { useTerminalSize } from './inkTerminal.js';\nimport { parseTypedLocale } from './promptParsing.js';\nimport type {\n ConfirmPromptProps,\n EditableTextPromptProps,\n GlobPromptProps,\n LocaleMultiPromptProps,\n LocalePromptProps,\n MultiSelectPromptProps,\n SelectPromptProps,\n TextPromptProps,\n} from './inkTypes.js';\nimport {\n CANCELLED,\n SELECTED_TAG_ROW_INDEX,\n complete,\n getInputWidth,\n getOptionWidth,\n getSafeIndex,\n getScrollWindow,\n getVisibleCount,\n nextIndex,\n previousIndex,\n} from './inkUtils.js';\n\nfunction resolveLocaleChoice({\n query,\n highlightedLocale,\n preferHighlightedLocale,\n}: {\n query: string;\n highlightedLocale?: string;\n preferHighlightedLocale: boolean;\n}) {\n if (preferHighlightedLocale) return highlightedLocale;\n return parseTypedLocale(query) ?? highlightedLocale;\n}\n\nfunction TextPrompt({\n message,\n defaultValue,\n validate,\n onComplete,\n footer = 'type to edit enter select esc cancel',\n placeholder,\n}: EditableTextPromptProps) {\n const { columns } = useTerminalSize();\n const [value, setValue] = useState(defaultValue ?? '');\n const [error, setError] = useState<string | undefined>();\n const inputWidth = getInputWidth(columns);\n\n useInput((input, key) => {\n if (key.escape || (key.ctrl && input === 'c')) {\n complete(CANCELLED, onComplete);\n return;\n }\n if (key.return) {\n const validation = validate?.(value);\n if (validation && validation !== true) {\n setError(validation.toString());\n return;\n }\n complete({ value, cancelled: false }, onComplete);\n return;\n }\n if (key.backspace || key.delete) {\n setValue((current) => current.slice(0, -1));\n setError(undefined);\n return;\n }\n if (input && !key.ctrl && !key.meta && !key.return) {\n setValue((current) => current + input);\n setError(undefined);\n }\n });\n\n return (\n <PromptFrame message={message} footer={footer}>\n <InputBox value={value} width={inputWidth} placeholder={placeholder} />\n {error ? <Text color='red'>{error}</Text> : null}\n </PromptFrame>\n );\n}\n\nfunction LocalePrompt({\n message,\n defaultValue,\n onComplete,\n}: LocalePromptProps) {\n const { columns, rows } = useTerminalSize();\n const localeOptions = getLocaleOptions();\n const defaultLocale = defaultValue ? getSupportedLocale(defaultValue) : null;\n const defaultIndex = defaultLocale\n ? Math.max(\n 0,\n localeOptions.findIndex((option) => option.code === defaultLocale)\n )\n : 0;\n const [query, setQuery] = useState('');\n const [index, setIndex] = useState(defaultIndex);\n const [preferHighlightedLocale, setPreferHighlightedLocale] = useState(false);\n const [error, setError] = useState<string | undefined>();\n const filteredOptions = getFilteredLocaleOptions(query);\n const activeIndex = getSafeIndex(index, filteredOptions.length);\n const visibleCount = getVisibleCount(rows, 14);\n const { start, visibleItems: visibleOptions } = getScrollWindow({\n items: filteredOptions,\n index: activeIndex,\n visibleCount,\n });\n const inputWidth = getInputWidth(columns);\n const optionWidth = getOptionWidth(columns);\n\n useInput((input, key) => {\n if (key.escape || (key.ctrl && input === 'c')) {\n complete(CANCELLED, onComplete);\n return;\n }\n if (key.upArrow) {\n setPreferHighlightedLocale(true);\n setIndex((current) => previousIndex(current, filteredOptions.length));\n return;\n }\n if (key.downArrow) {\n setPreferHighlightedLocale(true);\n setIndex((current) => nextIndex(current, filteredOptions.length));\n return;\n }\n if (key.backspace || key.delete) {\n setQuery((current) => current.slice(0, -1));\n setIndex(0);\n setPreferHighlightedLocale(false);\n setError(undefined);\n return;\n }\n if (key.return) {\n const finalLocale = resolveLocaleChoice({\n query,\n highlightedLocale: filteredOptions[activeIndex]?.code,\n preferHighlightedLocale,\n });\n if (!finalLocale) {\n setError('Enter a valid locale (e.g., en)');\n return;\n }\n complete({ value: finalLocale, cancelled: false }, onComplete);\n return;\n }\n if (input && !key.ctrl && !key.meta) {\n setQuery((current) => current + input);\n setIndex(0);\n setPreferHighlightedLocale(false);\n setError(undefined);\n }\n });\n\n return (\n <PromptFrame\n message={message}\n footer='↑↓ navigate enter select esc cancel'\n >\n <InputBox\n value={query}\n width={inputWidth}\n placeholder='Search locales...'\n />\n <LocaleOptionsList\n options={visibleOptions}\n activeIndex={activeIndex - start}\n width={optionWidth}\n />\n <RemainingMatches total={filteredOptions.length} visible={visibleCount} />\n {error ? <Text color='red'>{error}</Text> : null}\n </PromptFrame>\n );\n}\n\nfunction LocaleMultiPrompt({\n message,\n defaultValue = [],\n required,\n onComplete,\n}: LocaleMultiPromptProps) {\n const { columns, rows } = useTerminalSize();\n const [query, setQuery] = useState('');\n const [index, setIndex] = useState(0);\n const [preferHighlightedLocale, setPreferHighlightedLocale] = useState(false);\n const [selected, setSelected] = useState<Set<string>>(new Set(defaultValue));\n const [error, setError] = useState<string | undefined>();\n const selectedLocales = [...selected];\n const filteredOptions = getFilteredLocaleOptions(query).filter(\n (option) => !selected.has(option.code)\n );\n const activeOptionIndex = getSafeIndex(index, filteredOptions.length);\n const visibleCount = getVisibleCount(rows, 16);\n const { start, visibleItems: visibleOptions } = getScrollWindow({\n items: filteredOptions,\n index: activeOptionIndex,\n visibleCount,\n });\n const inputWidth = getInputWidth(columns);\n const optionWidth = getOptionWidth(columns);\n const [selectedTagIndex, setSelectedTagIndex] = useState(0);\n const moveSelectedTag = (direction: -1 | 1) =>\n setSelectedTagIndex((current) =>\n Math.max(0, Math.min(selectedLocales.length - 1, current + direction))\n );\n const removeSelectedTag = () => {\n const localeToRemove = selectedLocales[selectedTagIndex];\n if (!localeToRemove) return;\n setSelected((current) => {\n const next = new Set(current);\n next.delete(localeToRemove);\n return next;\n });\n setSelectedTagIndex((current) =>\n Math.max(0, Math.min(current, selectedLocales.length - 2))\n );\n if (selectedLocales.length === 1) setIndex(0);\n setError(undefined);\n };\n const toggleVisibleLocale = () => {\n const selectedLocale = resolveLocaleChoice({\n query,\n highlightedLocale: filteredOptions[activeOptionIndex]?.code,\n preferHighlightedLocale,\n });\n if (!selectedLocale) {\n setError('Enter a valid locale (e.g., es fr de)');\n return;\n }\n setSelected((current) => {\n const next = new Set(current);\n if (next.has(selectedLocale)) {\n next.delete(selectedLocale);\n } else {\n next.add(selectedLocale);\n }\n return next;\n });\n setQuery('');\n setError(undefined);\n };\n\n useInput((input, key) => {\n if (key.escape || (key.ctrl && input === 'c')) {\n complete(CANCELLED, onComplete);\n return;\n }\n if (key.upArrow) {\n setPreferHighlightedLocale(true);\n setIndex((current) => {\n if (current === SELECTED_TAG_ROW_INDEX) {\n if (selectedTagIndex > 0) {\n moveSelectedTag(-1);\n return SELECTED_TAG_ROW_INDEX;\n }\n return Math.max(filteredOptions.length - 1, 0);\n }\n if (current === 0 && selectedLocales.length > 0) {\n setSelectedTagIndex(selectedLocales.length - 1);\n return SELECTED_TAG_ROW_INDEX;\n }\n if (current === 0) {\n return Math.max(filteredOptions.length - 1, 0);\n }\n return current - 1;\n });\n return;\n }\n if (key.downArrow) {\n setPreferHighlightedLocale(true);\n setIndex((current) => {\n if (filteredOptions.length === 0) return 0;\n if (current === SELECTED_TAG_ROW_INDEX) {\n if (selectedTagIndex < selectedLocales.length - 1) {\n moveSelectedTag(1);\n return SELECTED_TAG_ROW_INDEX;\n }\n return 0;\n }\n return nextIndex(current, filteredOptions.length);\n });\n return;\n }\n if (index === SELECTED_TAG_ROW_INDEX && key.leftArrow) {\n setSelectedTagIndex((current) => Math.max(0, current - 1));\n return;\n }\n if (index === SELECTED_TAG_ROW_INDEX && key.rightArrow) {\n setSelectedTagIndex((current) =>\n Math.min(selectedLocales.length - 1, current + 1)\n );\n return;\n }\n if (key.backspace || key.delete) {\n setQuery((current) => current.slice(0, -1));\n setIndex(0);\n setPreferHighlightedLocale(false);\n setError(undefined);\n return;\n }\n if (input === ' ' && index === SELECTED_TAG_ROW_INDEX) {\n removeSelectedTag();\n return;\n }\n if (input === ' ') {\n toggleVisibleLocale();\n return;\n }\n if (key.return) {\n if (required && selected.size === 0) {\n setError('Select at least one locale');\n return;\n }\n complete({ value: [...selected], cancelled: false }, onComplete);\n return;\n }\n if (input && !key.ctrl && !key.meta) {\n setQuery((current) => current + input);\n setIndex(0);\n setPreferHighlightedLocale(false);\n setError(undefined);\n }\n });\n\n return (\n <PromptFrame\n message={message}\n footer='↑↓ navigate space toggle enter confirm esc cancel'\n >\n <InputBox\n value={query}\n width={inputWidth}\n placeholder='Search locales...'\n />\n <Box marginTop={1}>\n <SelectedTags\n selectedLocales={selectedLocales}\n active={index === SELECTED_TAG_ROW_INDEX}\n activeIndex={selectedTagIndex}\n width={optionWidth}\n />\n </Box>\n <LocaleOptionsList\n options={visibleOptions}\n activeIndex={\n index === SELECTED_TAG_ROW_INDEX\n ? SELECTED_TAG_ROW_INDEX\n : activeOptionIndex - start\n }\n width={optionWidth}\n />\n <RemainingMatches total={filteredOptions.length} visible={visibleCount} />\n {error ? <Text color='red'>{error}</Text> : null}\n </PromptFrame>\n );\n}\n\nfunction GlobPrompt({\n label,\n message,\n defaultValue,\n onComplete,\n}: GlobPromptProps) {\n return (\n <TextPrompt\n message={\n message ??\n `${label}: Enter space-separated glob patterns for files to translate. Include [locale].`\n }\n defaultValue={defaultValue}\n footer='enter save esc cancel'\n onComplete={onComplete}\n />\n );\n}\n\nfunction SelectPrompt<T>({\n message,\n options,\n defaultValue,\n onComplete,\n}: SelectPromptProps<T>) {\n const defaultIndex = Math.max(\n 0,\n options.findIndex((option) => option.value === defaultValue)\n );\n const [index, setIndex] = useState(defaultIndex);\n\n useInput((input, key) => {\n if (key.escape || (key.ctrl && input === 'c')) {\n complete(CANCELLED, onComplete);\n return;\n }\n if (key.upArrow) {\n setIndex((current) => (current === 0 ? options.length - 1 : current - 1));\n return;\n }\n if (key.downArrow) {\n setIndex((current) => (current + 1) % options.length);\n return;\n }\n if (key.return) {\n complete({ value: options[index]?.value, cancelled: false }, onComplete);\n }\n });\n\n return (\n <PromptFrame\n message={message}\n footer='↑↓ navigate enter select esc cancel'\n >\n {options.map((option, optionIndex) => (\n <OptionRow\n key={optionIndex}\n active={optionIndex === index}\n label={option.label}\n hint={option.hint}\n />\n ))}\n </PromptFrame>\n );\n}\n\nfunction MultiSelectPrompt<T extends string>({\n message,\n options,\n required,\n onComplete,\n}: MultiSelectPromptProps<T>) {\n const [index, setIndex] = useState(0);\n const [selected, setSelected] = useState<Set<number>>(new Set());\n const [error, setError] = useState<string | undefined>();\n\n useInput((input, key) => {\n if (key.escape || (key.ctrl && input === 'c')) {\n complete(CANCELLED, onComplete);\n return;\n }\n if (key.upArrow) {\n setIndex((current) => (current === 0 ? options.length - 1 : current - 1));\n return;\n }\n if (key.downArrow) {\n setIndex((current) => (current + 1) % options.length);\n return;\n }\n if (input === ' ') {\n setSelected((current) => {\n const next = new Set(current);\n if (next.has(index)) {\n next.delete(index);\n } else {\n next.add(index);\n }\n return next;\n });\n setError(undefined);\n return;\n }\n if (key.return) {\n if (required && selected.size === 0) {\n setError('Select at least one option');\n return;\n }\n const values = [...selected]\n .sort((a, b) => a - b)\n .map((selectedIndex) => options[selectedIndex]?.value)\n .filter((value): value is T => value != null);\n complete({ value: values, cancelled: false }, onComplete);\n }\n });\n\n return (\n <PromptFrame\n message={message}\n footer='↑↓ navigate space toggle enter select esc cancel'\n >\n {options.map((option, optionIndex) => (\n <OptionRow\n key={optionIndex}\n active={optionIndex === index}\n selected={selected.has(optionIndex)}\n label={option.label}\n hint={option.hint}\n />\n ))}\n {error ? <Text color='red'>{error}</Text> : null}\n </PromptFrame>\n );\n}\n\nfunction ConfirmPrompt({\n message,\n defaultValue,\n onComplete,\n}: ConfirmPromptProps) {\n const options = [\n { value: true, label: 'Yes' },\n { value: false, label: 'No' },\n ];\n const [index, setIndex] = useState(defaultValue ? 0 : 1);\n\n useInput((input, key) => {\n if (key.escape || (key.ctrl && input === 'c')) {\n complete(CANCELLED, onComplete);\n return;\n }\n if (key.leftArrow || key.upArrow || key.rightArrow || key.downArrow) {\n setIndex((current) => (current === 0 ? 1 : 0));\n return;\n }\n if (input.toLowerCase() === 'y') {\n complete({ value: true, cancelled: false }, onComplete);\n return;\n }\n if (input.toLowerCase() === 'n') {\n complete({ value: false, cancelled: false }, onComplete);\n return;\n }\n if (key.return) {\n complete({ value: options[index]!.value, cancelled: false }, onComplete);\n }\n });\n\n return (\n <PromptFrame\n message={message}\n footer='←→ choose y/n select enter confirm esc cancel'\n >\n {options.map((option, optionIndex) => (\n <OptionRow\n key={option.label}\n active={optionIndex === index}\n label={option.label}\n />\n ))}\n </PromptFrame>\n );\n}\n\nexport async function inkPromptText(\n options: Omit<TextPromptProps, 'onComplete'>\n) {\n return runPrompt<string>((onComplete) => (\n <TextPrompt {...options} onComplete={onComplete} />\n ));\n}\n\nexport async function inkPromptLocale(\n options: Omit<LocalePromptProps, 'onComplete'>\n) {\n return runPrompt<string>((onComplete) => (\n <LocalePrompt {...options} onComplete={onComplete} />\n ));\n}\n\nexport async function inkPromptLocaleMulti(\n options: Omit<LocaleMultiPromptProps, 'onComplete'>\n) {\n return runPrompt<string[]>((onComplete) => (\n <LocaleMultiPrompt {...options} onComplete={onComplete} />\n ));\n}\n\nexport async function inkPromptGlob(\n options: Omit<GlobPromptProps, 'onComplete'>\n) {\n return runPrompt<string>((onComplete) => (\n <GlobPrompt {...options} onComplete={onComplete} />\n ));\n}\n\nexport async function inkPromptSelect<T>(\n options: Omit<SelectPromptProps<T>, 'onComplete'>\n) {\n return runPrompt<T>((onComplete) => (\n <SelectPrompt {...options} onComplete={onComplete} />\n ));\n}\n\nexport async function inkPromptMultiSelect<T extends string>(\n options: Omit<MultiSelectPromptProps<T>, 'onComplete'>\n) {\n return runPrompt<Array<T>>((onComplete) => (\n <MultiSelectPrompt {...options} onComplete={onComplete} />\n ));\n}\n\nexport async function inkPromptConfirm(\n options: Omit<ConfirmPromptProps, 'onComplete'>\n) {\n return runPrompt<boolean>((onComplete) => (\n <ConfirmPrompt {...options} onComplete={onComplete} />\n ));\n}\n"],"mappings":";;;;;;;;;;;;AAqCA,SAAS,oBAAoB,EAC3B,OACA,mBACA,2BAKC;AACD,KAAI,wBAAyB,QAAO;AACpC,QAAO,iBAAiB,MAAM,IAAI;;AAGpC,SAAS,WAAW,EAClB,SACA,cACA,UACA,YACA,SAAS,4CACT,eAC0B;CAC1B,MAAM,EAAE,YAAY,iBAAiB;CACrC,MAAM,CAAC,OAAO,YAAY,SAAS,gBAAgB,GAAG;CACtD,MAAM,CAAC,OAAO,YAAY,UAA8B;CACxD,MAAM,aAAa,cAAc,QAAQ;AAEzC,WAAU,OAAO,QAAQ;AACvB,MAAI,IAAI,UAAW,IAAI,QAAQ,UAAU,KAAM;AAC7C,YAAS,WAAW,WAAW;AAC/B;;AAEF,MAAI,IAAI,QAAQ;GACd,MAAM,aAAa,WAAW,MAAM;AACpC,OAAI,cAAc,eAAe,MAAM;AACrC,aAAS,WAAW,UAAU,CAAC;AAC/B;;AAEF,YAAS;IAAE;IAAO,WAAW;IAAO,EAAE,WAAW;AACjD;;AAEF,MAAI,IAAI,aAAa,IAAI,QAAQ;AAC/B,aAAU,YAAY,QAAQ,MAAM,GAAG,GAAG,CAAC;AAC3C,YAAS,KAAA,EAAU;AACnB;;AAEF,MAAI,SAAS,CAAC,IAAI,QAAQ,CAAC,IAAI,QAAQ,CAAC,IAAI,QAAQ;AAClD,aAAU,YAAY,UAAU,MAAM;AACtC,YAAS,KAAA,EAAU;;GAErB;AAEF,QACE,qBAAC,aAAD;EAAsB;EAAiB;YAAvC,CACE,oBAAC,UAAD;GAAiB;GAAO,OAAO;GAAyB;GAAe,CAAA,EACtE,QAAQ,oBAAC,MAAD;GAAM,OAAM;aAAO;GAAa,CAAA,GAAG,KAChC;;;AAIlB,SAAS,aAAa,EACpB,SACA,cACA,cACoB;CACpB,MAAM,EAAE,SAAS,SAAS,iBAAiB;CAC3C,MAAM,gBAAgB,kBAAkB;CACxC,MAAM,gBAAgB,eAAe,mBAAmB,aAAa,GAAG;CACxE,MAAM,eAAe,gBACjB,KAAK,IACH,GACA,cAAc,WAAW,WAAW,OAAO,SAAS,cAAc,CACnE,GACD;CACJ,MAAM,CAAC,OAAO,YAAY,SAAS,GAAG;CACtC,MAAM,CAAC,OAAO,YAAY,SAAS,aAAa;CAChD,MAAM,CAAC,yBAAyB,8BAA8B,SAAS,MAAM;CAC7E,MAAM,CAAC,OAAO,YAAY,UAA8B;CACxD,MAAM,kBAAkB,yBAAyB,MAAM;CACvD,MAAM,cAAc,aAAa,OAAO,gBAAgB,OAAO;CAC/D,MAAM,eAAe,gBAAgB,MAAM,GAAG;CAC9C,MAAM,EAAE,OAAO,cAAc,mBAAmB,gBAAgB;EAC9D,OAAO;EACP,OAAO;EACP;EACD,CAAC;CACF,MAAM,aAAa,cAAc,QAAQ;CACzC,MAAM,cAAc,eAAe,QAAQ;AAE3C,WAAU,OAAO,QAAQ;AACvB,MAAI,IAAI,UAAW,IAAI,QAAQ,UAAU,KAAM;AAC7C,YAAS,WAAW,WAAW;AAC/B;;AAEF,MAAI,IAAI,SAAS;AACf,8BAA2B,KAAK;AAChC,aAAU,YAAY,cAAc,SAAS,gBAAgB,OAAO,CAAC;AACrE;;AAEF,MAAI,IAAI,WAAW;AACjB,8BAA2B,KAAK;AAChC,aAAU,YAAY,UAAU,SAAS,gBAAgB,OAAO,CAAC;AACjE;;AAEF,MAAI,IAAI,aAAa,IAAI,QAAQ;AAC/B,aAAU,YAAY,QAAQ,MAAM,GAAG,GAAG,CAAC;AAC3C,YAAS,EAAE;AACX,8BAA2B,MAAM;AACjC,YAAS,KAAA,EAAU;AACnB;;AAEF,MAAI,IAAI,QAAQ;GACd,MAAM,cAAc,oBAAoB;IACtC;IACA,mBAAmB,gBAAgB,cAAc;IACjD;IACD,CAAC;AACF,OAAI,CAAC,aAAa;AAChB,aAAS,kCAAkC;AAC3C;;AAEF,YAAS;IAAE,OAAO;IAAa,WAAW;IAAO,EAAE,WAAW;AAC9D;;AAEF,MAAI,SAAS,CAAC,IAAI,QAAQ,CAAC,IAAI,MAAM;AACnC,aAAU,YAAY,UAAU,MAAM;AACtC,YAAS,EAAE;AACX,8BAA2B,MAAM;AACjC,YAAS,KAAA,EAAU;;GAErB;AAEF,QACE,qBAAC,aAAD;EACW;EACT,QAAO;YAFT;GAIE,oBAAC,UAAD;IACE,OAAO;IACP,OAAO;IACP,aAAY;IACZ,CAAA;GACF,oBAAC,mBAAD;IACE,SAAS;IACT,aAAa,cAAc;IAC3B,OAAO;IACP,CAAA;GACF,oBAAC,kBAAD;IAAkB,OAAO,gBAAgB;IAAQ,SAAS;IAAgB,CAAA;GACzE,QAAQ,oBAAC,MAAD;IAAM,OAAM;cAAO;IAAa,CAAA,GAAG;GAChC;;;AAIlB,SAAS,kBAAkB,EACzB,SACA,eAAe,EAAE,EACjB,UACA,cACyB;CACzB,MAAM,EAAE,SAAS,SAAS,iBAAiB;CAC3C,MAAM,CAAC,OAAO,YAAY,SAAS,GAAG;CACtC,MAAM,CAAC,OAAO,YAAY,SAAS,EAAE;CACrC,MAAM,CAAC,yBAAyB,8BAA8B,SAAS,MAAM;CAC7E,MAAM,CAAC,UAAU,eAAe,SAAsB,IAAI,IAAI,aAAa,CAAC;CAC5E,MAAM,CAAC,OAAO,YAAY,UAA8B;CACxD,MAAM,kBAAkB,CAAC,GAAG,SAAS;CACrC,MAAM,kBAAkB,yBAAyB,MAAM,CAAC,QACrD,WAAW,CAAC,SAAS,IAAI,OAAO,KAAK,CACvC;CACD,MAAM,oBAAoB,aAAa,OAAO,gBAAgB,OAAO;CACrE,MAAM,eAAe,gBAAgB,MAAM,GAAG;CAC9C,MAAM,EAAE,OAAO,cAAc,mBAAmB,gBAAgB;EAC9D,OAAO;EACP,OAAO;EACP;EACD,CAAC;CACF,MAAM,aAAa,cAAc,QAAQ;CACzC,MAAM,cAAc,eAAe,QAAQ;CAC3C,MAAM,CAAC,kBAAkB,uBAAuB,SAAS,EAAE;CAC3D,MAAM,mBAAmB,cACvB,qBAAqB,YACnB,KAAK,IAAI,GAAG,KAAK,IAAI,gBAAgB,SAAS,GAAG,UAAU,UAAU,CAAC,CACvE;CACH,MAAM,0BAA0B;EAC9B,MAAM,iBAAiB,gBAAgB;AACvC,MAAI,CAAC,eAAgB;AACrB,eAAa,YAAY;GACvB,MAAM,OAAO,IAAI,IAAI,QAAQ;AAC7B,QAAK,OAAO,eAAe;AAC3B,UAAO;IACP;AACF,uBAAqB,YACnB,KAAK,IAAI,GAAG,KAAK,IAAI,SAAS,gBAAgB,SAAS,EAAE,CAAC,CAC3D;AACD,MAAI,gBAAgB,WAAW,EAAG,UAAS,EAAE;AAC7C,WAAS,KAAA,EAAU;;CAErB,MAAM,4BAA4B;EAChC,MAAM,iBAAiB,oBAAoB;GACzC;GACA,mBAAmB,gBAAgB,oBAAoB;GACvD;GACD,CAAC;AACF,MAAI,CAAC,gBAAgB;AACnB,YAAS,wCAAwC;AACjD;;AAEF,eAAa,YAAY;GACvB,MAAM,OAAO,IAAI,IAAI,QAAQ;AAC7B,OAAI,KAAK,IAAI,eAAe,CAC1B,MAAK,OAAO,eAAe;OAE3B,MAAK,IAAI,eAAe;AAE1B,UAAO;IACP;AACF,WAAS,GAAG;AACZ,WAAS,KAAA,EAAU;;AAGrB,WAAU,OAAO,QAAQ;AACvB,MAAI,IAAI,UAAW,IAAI,QAAQ,UAAU,KAAM;AAC7C,YAAS,WAAW,WAAW;AAC/B;;AAEF,MAAI,IAAI,SAAS;AACf,8BAA2B,KAAK;AAChC,aAAU,YAAY;AACpB,QAAI,YAAA,IAAoC;AACtC,SAAI,mBAAmB,GAAG;AACxB,sBAAgB,GAAG;AACnB,aAAA;;AAEF,YAAO,KAAK,IAAI,gBAAgB,SAAS,GAAG,EAAE;;AAEhD,QAAI,YAAY,KAAK,gBAAgB,SAAS,GAAG;AAC/C,yBAAoB,gBAAgB,SAAS,EAAE;AAC/C,YAAA;;AAEF,QAAI,YAAY,EACd,QAAO,KAAK,IAAI,gBAAgB,SAAS,GAAG,EAAE;AAEhD,WAAO,UAAU;KACjB;AACF;;AAEF,MAAI,IAAI,WAAW;AACjB,8BAA2B,KAAK;AAChC,aAAU,YAAY;AACpB,QAAI,gBAAgB,WAAW,EAAG,QAAO;AACzC,QAAI,YAAA,IAAoC;AACtC,SAAI,mBAAmB,gBAAgB,SAAS,GAAG;AACjD,sBAAgB,EAAE;AAClB,aAAA;;AAEF,YAAO;;AAET,WAAO,UAAU,SAAS,gBAAgB,OAAO;KACjD;AACF;;AAEF,MAAI,UAAA,MAAoC,IAAI,WAAW;AACrD,wBAAqB,YAAY,KAAK,IAAI,GAAG,UAAU,EAAE,CAAC;AAC1D;;AAEF,MAAI,UAAA,MAAoC,IAAI,YAAY;AACtD,wBAAqB,YACnB,KAAK,IAAI,gBAAgB,SAAS,GAAG,UAAU,EAAE,CAClD;AACD;;AAEF,MAAI,IAAI,aAAa,IAAI,QAAQ;AAC/B,aAAU,YAAY,QAAQ,MAAM,GAAG,GAAG,CAAC;AAC3C,YAAS,EAAE;AACX,8BAA2B,MAAM;AACjC,YAAS,KAAA,EAAU;AACnB;;AAEF,MAAI,UAAU,OAAO,UAAA,IAAkC;AACrD,sBAAmB;AACnB;;AAEF,MAAI,UAAU,KAAK;AACjB,wBAAqB;AACrB;;AAEF,MAAI,IAAI,QAAQ;AACd,OAAI,YAAY,SAAS,SAAS,GAAG;AACnC,aAAS,6BAA6B;AACtC;;AAEF,YAAS;IAAE,OAAO,CAAC,GAAG,SAAS;IAAE,WAAW;IAAO,EAAE,WAAW;AAChE;;AAEF,MAAI,SAAS,CAAC,IAAI,QAAQ,CAAC,IAAI,MAAM;AACnC,aAAU,YAAY,UAAU,MAAM;AACtC,YAAS,EAAE;AACX,8BAA2B,MAAM;AACjC,YAAS,KAAA,EAAU;;GAErB;AAEF,QACE,qBAAC,aAAD;EACW;EACT,QAAO;YAFT;GAIE,oBAAC,UAAD;IACE,OAAO;IACP,OAAO;IACP,aAAY;IACZ,CAAA;GACF,oBAAC,KAAD;IAAK,WAAW;cACd,oBAAC,cAAD;KACmB;KACjB,QAAQ,UAAA;KACR,aAAa;KACb,OAAO;KACP,CAAA;IACE,CAAA;GACN,oBAAC,mBAAD;IACE,SAAS;IACT,aACE,UAAA,KAAA,KAEI,oBAAoB;IAE1B,OAAO;IACP,CAAA;GACF,oBAAC,kBAAD;IAAkB,OAAO,gBAAgB;IAAQ,SAAS;IAAgB,CAAA;GACzE,QAAQ,oBAAC,MAAD;IAAM,OAAM;cAAO;IAAa,CAAA,GAAG;GAChC;;;AAIlB,SAAS,WAAW,EAClB,OACA,SACA,cACA,cACkB;AAClB,QACE,oBAAC,YAAD;EACE,SACE,WACA,GAAG,MAAM;EAEG;EACd,QAAO;EACK;EACZ,CAAA;;AAIN,SAAS,aAAgB,EACvB,SACA,SACA,cACA,cACuB;CAKvB,MAAM,CAAC,OAAO,YAAY,SAJL,KAAK,IACxB,GACA,QAAQ,WAAW,WAAW,OAAO,UAAU,aAAa,CAEf,CAAC;AAEhD,WAAU,OAAO,QAAQ;AACvB,MAAI,IAAI,UAAW,IAAI,QAAQ,UAAU,KAAM;AAC7C,YAAS,WAAW,WAAW;AAC/B;;AAEF,MAAI,IAAI,SAAS;AACf,aAAU,YAAa,YAAY,IAAI,QAAQ,SAAS,IAAI,UAAU,EAAG;AACzE;;AAEF,MAAI,IAAI,WAAW;AACjB,aAAU,aAAa,UAAU,KAAK,QAAQ,OAAO;AACrD;;AAEF,MAAI,IAAI,OACN,UAAS;GAAE,OAAO,QAAQ,QAAQ;GAAO,WAAW;GAAO,EAAE,WAAW;GAE1E;AAEF,QACE,oBAAC,aAAD;EACW;EACT,QAAO;YAEN,QAAQ,KAAK,QAAQ,gBACpB,oBAAC,WAAD;GAEE,QAAQ,gBAAgB;GACxB,OAAO,OAAO;GACd,MAAM,OAAO;GACb,EAJK,YAIL,CACF;EACU,CAAA;;AAIlB,SAAS,kBAAoC,EAC3C,SACA,SACA,UACA,cAC4B;CAC5B,MAAM,CAAC,OAAO,YAAY,SAAS,EAAE;CACrC,MAAM,CAAC,UAAU,eAAe,yBAAsB,IAAI,KAAK,CAAC;CAChE,MAAM,CAAC,OAAO,YAAY,UAA8B;AAExD,WAAU,OAAO,QAAQ;AACvB,MAAI,IAAI,UAAW,IAAI,QAAQ,UAAU,KAAM;AAC7C,YAAS,WAAW,WAAW;AAC/B;;AAEF,MAAI,IAAI,SAAS;AACf,aAAU,YAAa,YAAY,IAAI,QAAQ,SAAS,IAAI,UAAU,EAAG;AACzE;;AAEF,MAAI,IAAI,WAAW;AACjB,aAAU,aAAa,UAAU,KAAK,QAAQ,OAAO;AACrD;;AAEF,MAAI,UAAU,KAAK;AACjB,gBAAa,YAAY;IACvB,MAAM,OAAO,IAAI,IAAI,QAAQ;AAC7B,QAAI,KAAK,IAAI,MAAM,CACjB,MAAK,OAAO,MAAM;QAElB,MAAK,IAAI,MAAM;AAEjB,WAAO;KACP;AACF,YAAS,KAAA,EAAU;AACnB;;AAEF,MAAI,IAAI,QAAQ;AACd,OAAI,YAAY,SAAS,SAAS,GAAG;AACnC,aAAS,6BAA6B;AACtC;;AAMF,YAAS;IAAE,OAJI,CAAC,GAAG,SAAS,CACzB,MAAM,GAAG,MAAM,IAAI,EAAE,CACrB,KAAK,kBAAkB,QAAQ,gBAAgB,MAAM,CACrD,QAAQ,UAAsB,SAAS,KAClB;IAAE,WAAW;IAAO,EAAE,WAAW;;GAE3D;AAEF,QACE,qBAAC,aAAD;EACW;EACT,QAAO;YAFT,CAIG,QAAQ,KAAK,QAAQ,gBACpB,oBAAC,WAAD;GAEE,QAAQ,gBAAgB;GACxB,UAAU,SAAS,IAAI,YAAY;GACnC,OAAO,OAAO;GACd,MAAM,OAAO;GACb,EALK,YAKL,CACF,EACD,QAAQ,oBAAC,MAAD;GAAM,OAAM;aAAO;GAAa,CAAA,GAAG,KAChC;;;AAIlB,SAAS,cAAc,EACrB,SACA,cACA,cACqB;CACrB,MAAM,UAAU,CACd;EAAE,OAAO;EAAM,OAAO;EAAO,EAC7B;EAAE,OAAO;EAAO,OAAO;EAAM,CAC9B;CACD,MAAM,CAAC,OAAO,YAAY,SAAS,eAAe,IAAI,EAAE;AAExD,WAAU,OAAO,QAAQ;AACvB,MAAI,IAAI,UAAW,IAAI,QAAQ,UAAU,KAAM;AAC7C,YAAS,WAAW,WAAW;AAC/B;;AAEF,MAAI,IAAI,aAAa,IAAI,WAAW,IAAI,cAAc,IAAI,WAAW;AACnE,aAAU,YAAa,YAAY,IAAI,IAAI,EAAG;AAC9C;;AAEF,MAAI,MAAM,aAAa,KAAK,KAAK;AAC/B,YAAS;IAAE,OAAO;IAAM,WAAW;IAAO,EAAE,WAAW;AACvD;;AAEF,MAAI,MAAM,aAAa,KAAK,KAAK;AAC/B,YAAS;IAAE,OAAO;IAAO,WAAW;IAAO,EAAE,WAAW;AACxD;;AAEF,MAAI,IAAI,OACN,UAAS;GAAE,OAAO,QAAQ,OAAQ;GAAO,WAAW;GAAO,EAAE,WAAW;GAE1E;AAEF,QACE,oBAAC,aAAD;EACW;EACT,QAAO;YAEN,QAAQ,KAAK,QAAQ,gBACpB,oBAAC,WAAD;GAEE,QAAQ,gBAAgB;GACxB,OAAO,OAAO;GACd,EAHK,OAAO,MAGZ,CACF;EACU,CAAA;;AAIlB,eAAsB,cACpB,SACA;AACA,QAAO,WAAmB,eACxB,oBAAC,YAAD;EAAY,GAAI;EAAqB;EAAc,CAAA,CACnD;;AAGJ,eAAsB,gBACpB,SACA;AACA,QAAO,WAAmB,eACxB,oBAAC,cAAD;EAAc,GAAI;EAAqB;EAAc,CAAA,CACrD;;AAGJ,eAAsB,qBACpB,SACA;AACA,QAAO,WAAqB,eAC1B,oBAAC,mBAAD;EAAmB,GAAI;EAAqB;EAAc,CAAA,CAC1D;;AAGJ,eAAsB,cACpB,SACA;AACA,QAAO,WAAmB,eACxB,oBAAC,YAAD;EAAY,GAAI;EAAqB;EAAc,CAAA,CACnD;;AAGJ,eAAsB,gBACpB,SACA;AACA,QAAO,WAAc,eACnB,oBAAC,cAAD;EAAc,GAAI;EAAqB;EAAc,CAAA,CACrD;;AAGJ,eAAsB,qBACpB,SACA;AACA,QAAO,WAAqB,eAC1B,oBAAC,mBAAD;EAAmB,GAAI;EAAqB;EAAc,CAAA,CAC1D;;AAGJ,eAAsB,iBACpB,SACA;AACA,QAAO,WAAoB,eACzB,oBAAC,eAAD;EAAe,GAAI;EAAqB;EAAc,CAAA,CACtD"}
|
|
1
|
+
{"version":3,"file":"inkPrompts.js","names":[],"sources":["../../src/console/inkPrompts.tsx"],"sourcesContent":["import { useState } from 'react';\nimport { Box, Text, useInput } from 'ink';\nimport { getSupportedLocale } from '@generaltranslation/supported-locales';\nimport {\n OptionRow,\n LocaleOptionsList,\n RemainingMatches,\n SelectedTags,\n} from './inkFields.js';\nimport { getFilteredLocaleOptions, getLocaleOptions } from './inkLocaleData.js';\nimport { InputBox, PromptFrame } from './inkLayout.js';\nimport { runPrompt } from './inkSession.js';\nimport { useTerminalSize } from './inkTerminal.js';\nimport { parseTypedLocale } from './promptParsing.js';\nimport type { CustomMapping } from 'generaltranslation/types';\nimport type {\n ConfirmPromptProps,\n EditableTextPromptProps,\n GlobPromptProps,\n LocaleMultiPromptProps,\n LocalePromptProps,\n MultiSelectPromptProps,\n SelectPromptProps,\n TextPromptProps,\n} from './inkTypes.js';\nimport {\n CANCELLED,\n SELECTED_TAG_ROW_INDEX,\n complete,\n getInputWidth,\n getOptionWidth,\n getSafeIndex,\n getScrollWindow,\n getVisibleCount,\n nextIndex,\n previousIndex,\n} from './inkUtils.js';\n\nfunction resolveLocaleChoice({\n query,\n highlightedLocale,\n preferHighlightedLocale,\n customMapping,\n}: {\n query: string;\n highlightedLocale?: string;\n preferHighlightedLocale: boolean;\n customMapping?: CustomMapping;\n}) {\n if (preferHighlightedLocale) return highlightedLocale;\n return parseTypedLocale(query, customMapping) ?? highlightedLocale;\n}\n\nfunction TextPrompt({\n message,\n defaultValue,\n validate,\n onComplete,\n footer = 'type to edit enter select esc cancel',\n placeholder,\n}: EditableTextPromptProps) {\n const { columns } = useTerminalSize();\n const [value, setValue] = useState(defaultValue ?? '');\n const [error, setError] = useState<string | undefined>();\n const inputWidth = getInputWidth(columns);\n\n useInput((input, key) => {\n if (key.escape || (key.ctrl && input === 'c')) {\n complete(CANCELLED, onComplete);\n return;\n }\n if (key.return) {\n const validation = validate?.(value);\n if (validation && validation !== true) {\n setError(validation.toString());\n return;\n }\n complete({ value, cancelled: false }, onComplete);\n return;\n }\n if (key.backspace || key.delete) {\n setValue((current) => current.slice(0, -1));\n setError(undefined);\n return;\n }\n if (input && !key.ctrl && !key.meta && !key.return) {\n setValue((current) => current + input);\n setError(undefined);\n }\n });\n\n return (\n <PromptFrame message={message} footer={footer}>\n <InputBox value={value} width={inputWidth} placeholder={placeholder} />\n {error ? <Text color='red'>{error}</Text> : null}\n </PromptFrame>\n );\n}\n\nfunction LocalePrompt({\n message,\n defaultValue,\n customMapping,\n onComplete,\n}: LocalePromptProps) {\n const { columns, rows } = useTerminalSize();\n const localeOptions = getLocaleOptions();\n const defaultLocale = defaultValue ? getSupportedLocale(defaultValue) : null;\n const defaultIndex = defaultLocale\n ? Math.max(\n 0,\n localeOptions.findIndex((option) => option.code === defaultLocale)\n )\n : 0;\n const [query, setQuery] = useState('');\n const [index, setIndex] = useState(defaultIndex);\n const [preferHighlightedLocale, setPreferHighlightedLocale] = useState(false);\n const [error, setError] = useState<string | undefined>();\n const filteredOptions = getFilteredLocaleOptions(query);\n const activeIndex = getSafeIndex(index, filteredOptions.length);\n const visibleCount = getVisibleCount(rows, 14);\n const { start, visibleItems: visibleOptions } = getScrollWindow({\n items: filteredOptions,\n index: activeIndex,\n visibleCount,\n });\n const inputWidth = getInputWidth(columns);\n const optionWidth = getOptionWidth(columns);\n\n useInput((input, key) => {\n if (key.escape || (key.ctrl && input === 'c')) {\n complete(CANCELLED, onComplete);\n return;\n }\n if (key.upArrow) {\n setPreferHighlightedLocale(true);\n setIndex((current) => previousIndex(current, filteredOptions.length));\n return;\n }\n if (key.downArrow) {\n setPreferHighlightedLocale(true);\n setIndex((current) => nextIndex(current, filteredOptions.length));\n return;\n }\n if (key.backspace || key.delete) {\n setQuery((current) => current.slice(0, -1));\n setIndex(0);\n setPreferHighlightedLocale(false);\n setError(undefined);\n return;\n }\n if (key.return) {\n const finalLocale = resolveLocaleChoice({\n query,\n highlightedLocale: filteredOptions[activeIndex]?.code,\n preferHighlightedLocale,\n customMapping,\n });\n if (!finalLocale) {\n setError('Enter a valid locale (e.g., en)');\n return;\n }\n complete({ value: finalLocale, cancelled: false }, onComplete);\n return;\n }\n if (input && !key.ctrl && !key.meta) {\n setQuery((current) => current + input);\n setIndex(0);\n setPreferHighlightedLocale(false);\n setError(undefined);\n }\n });\n\n return (\n <PromptFrame\n message={message}\n footer='↑↓ navigate enter select esc cancel'\n >\n <InputBox\n value={query}\n width={inputWidth}\n placeholder='Search locales...'\n />\n <LocaleOptionsList\n options={visibleOptions}\n activeIndex={activeIndex - start}\n width={optionWidth}\n />\n <RemainingMatches total={filteredOptions.length} visible={visibleCount} />\n {error ? <Text color='red'>{error}</Text> : null}\n </PromptFrame>\n );\n}\n\nfunction LocaleMultiPrompt({\n message,\n defaultValue = [],\n required,\n customMapping,\n onComplete,\n}: LocaleMultiPromptProps) {\n const { columns, rows } = useTerminalSize();\n const [query, setQuery] = useState('');\n const [index, setIndex] = useState(0);\n const [preferHighlightedLocale, setPreferHighlightedLocale] = useState(false);\n const [selected, setSelected] = useState<Set<string>>(new Set(defaultValue));\n const [error, setError] = useState<string | undefined>();\n const selectedLocales = [...selected];\n const filteredOptions = getFilteredLocaleOptions(query).filter(\n (option) => !selected.has(option.code)\n );\n const activeOptionIndex = getSafeIndex(index, filteredOptions.length);\n const visibleCount = getVisibleCount(rows, 16);\n const { start, visibleItems: visibleOptions } = getScrollWindow({\n items: filteredOptions,\n index: activeOptionIndex,\n visibleCount,\n });\n const inputWidth = getInputWidth(columns);\n const optionWidth = getOptionWidth(columns);\n const [selectedTagIndex, setSelectedTagIndex] = useState(0);\n const moveSelectedTag = (direction: -1 | 1) =>\n setSelectedTagIndex((current) =>\n Math.max(0, Math.min(selectedLocales.length - 1, current + direction))\n );\n const removeSelectedTag = () => {\n const localeToRemove = selectedLocales[selectedTagIndex];\n if (!localeToRemove) return;\n setSelected((current) => {\n const next = new Set(current);\n next.delete(localeToRemove);\n return next;\n });\n setSelectedTagIndex((current) =>\n Math.max(0, Math.min(current, selectedLocales.length - 2))\n );\n if (selectedLocales.length === 1) setIndex(0);\n setError(undefined);\n };\n const toggleVisibleLocale = () => {\n const selectedLocale = resolveLocaleChoice({\n query,\n highlightedLocale: filteredOptions[activeOptionIndex]?.code,\n preferHighlightedLocale,\n customMapping,\n });\n if (!selectedLocale) {\n setError('Enter a valid locale (e.g., es fr de)');\n return;\n }\n setSelected((current) => {\n const next = new Set(current);\n if (next.has(selectedLocale)) {\n next.delete(selectedLocale);\n } else {\n next.add(selectedLocale);\n }\n return next;\n });\n setQuery('');\n setError(undefined);\n };\n\n useInput((input, key) => {\n if (key.escape || (key.ctrl && input === 'c')) {\n complete(CANCELLED, onComplete);\n return;\n }\n if (key.upArrow) {\n setPreferHighlightedLocale(true);\n setIndex((current) => {\n if (current === SELECTED_TAG_ROW_INDEX) {\n if (selectedTagIndex > 0) {\n moveSelectedTag(-1);\n return SELECTED_TAG_ROW_INDEX;\n }\n return Math.max(filteredOptions.length - 1, 0);\n }\n if (current === 0 && selectedLocales.length > 0) {\n setSelectedTagIndex(selectedLocales.length - 1);\n return SELECTED_TAG_ROW_INDEX;\n }\n if (current === 0) {\n return Math.max(filteredOptions.length - 1, 0);\n }\n return current - 1;\n });\n return;\n }\n if (key.downArrow) {\n setPreferHighlightedLocale(true);\n setIndex((current) => {\n if (filteredOptions.length === 0) return 0;\n if (current === SELECTED_TAG_ROW_INDEX) {\n if (selectedTagIndex < selectedLocales.length - 1) {\n moveSelectedTag(1);\n return SELECTED_TAG_ROW_INDEX;\n }\n return 0;\n }\n return nextIndex(current, filteredOptions.length);\n });\n return;\n }\n if (index === SELECTED_TAG_ROW_INDEX && key.leftArrow) {\n setSelectedTagIndex((current) => Math.max(0, current - 1));\n return;\n }\n if (index === SELECTED_TAG_ROW_INDEX && key.rightArrow) {\n setSelectedTagIndex((current) =>\n Math.min(selectedLocales.length - 1, current + 1)\n );\n return;\n }\n if (key.backspace || key.delete) {\n setQuery((current) => current.slice(0, -1));\n setIndex(0);\n setPreferHighlightedLocale(false);\n setError(undefined);\n return;\n }\n if (input === ' ' && index === SELECTED_TAG_ROW_INDEX) {\n removeSelectedTag();\n return;\n }\n if (input === ' ') {\n toggleVisibleLocale();\n return;\n }\n if (key.return) {\n if (required && selected.size === 0) {\n setError('Select at least one locale');\n return;\n }\n complete({ value: [...selected], cancelled: false }, onComplete);\n return;\n }\n if (input && !key.ctrl && !key.meta) {\n setQuery((current) => current + input);\n setIndex(0);\n setPreferHighlightedLocale(false);\n setError(undefined);\n }\n });\n\n return (\n <PromptFrame\n message={message}\n footer='↑↓ navigate space toggle enter confirm esc cancel'\n >\n <InputBox\n value={query}\n width={inputWidth}\n placeholder='Search locales...'\n />\n <Box marginTop={1}>\n <SelectedTags\n selectedLocales={selectedLocales}\n active={index === SELECTED_TAG_ROW_INDEX}\n activeIndex={selectedTagIndex}\n width={optionWidth}\n />\n </Box>\n <LocaleOptionsList\n options={visibleOptions}\n activeIndex={\n index === SELECTED_TAG_ROW_INDEX\n ? SELECTED_TAG_ROW_INDEX\n : activeOptionIndex - start\n }\n width={optionWidth}\n />\n <RemainingMatches total={filteredOptions.length} visible={visibleCount} />\n {error ? <Text color='red'>{error}</Text> : null}\n </PromptFrame>\n );\n}\n\nfunction GlobPrompt({\n label,\n message,\n defaultValue,\n onComplete,\n}: GlobPromptProps) {\n return (\n <TextPrompt\n message={\n message ??\n `${label}: Enter space-separated glob patterns for files to translate. Include [locale].`\n }\n defaultValue={defaultValue}\n footer='enter save esc cancel'\n onComplete={onComplete}\n />\n );\n}\n\nfunction SelectPrompt<T>({\n message,\n options,\n defaultValue,\n onComplete,\n}: SelectPromptProps<T>) {\n const defaultIndex = Math.max(\n 0,\n options.findIndex((option) => option.value === defaultValue)\n );\n const [index, setIndex] = useState(defaultIndex);\n\n useInput((input, key) => {\n if (key.escape || (key.ctrl && input === 'c')) {\n complete(CANCELLED, onComplete);\n return;\n }\n if (key.upArrow) {\n setIndex((current) => (current === 0 ? options.length - 1 : current - 1));\n return;\n }\n if (key.downArrow) {\n setIndex((current) => (current + 1) % options.length);\n return;\n }\n if (key.return) {\n complete({ value: options[index]?.value, cancelled: false }, onComplete);\n }\n });\n\n return (\n <PromptFrame\n message={message}\n footer='↑↓ navigate enter select esc cancel'\n >\n {options.map((option, optionIndex) => (\n <OptionRow\n key={optionIndex}\n active={optionIndex === index}\n label={option.label}\n hint={option.hint}\n />\n ))}\n </PromptFrame>\n );\n}\n\nfunction MultiSelectPrompt<T extends string>({\n message,\n options,\n required,\n onComplete,\n}: MultiSelectPromptProps<T>) {\n const [index, setIndex] = useState(0);\n const [selected, setSelected] = useState<Set<number>>(new Set());\n const [error, setError] = useState<string | undefined>();\n\n useInput((input, key) => {\n if (key.escape || (key.ctrl && input === 'c')) {\n complete(CANCELLED, onComplete);\n return;\n }\n if (key.upArrow) {\n setIndex((current) => (current === 0 ? options.length - 1 : current - 1));\n return;\n }\n if (key.downArrow) {\n setIndex((current) => (current + 1) % options.length);\n return;\n }\n if (input === ' ') {\n setSelected((current) => {\n const next = new Set(current);\n if (next.has(index)) {\n next.delete(index);\n } else {\n next.add(index);\n }\n return next;\n });\n setError(undefined);\n return;\n }\n if (key.return) {\n if (required && selected.size === 0) {\n setError('Select at least one option');\n return;\n }\n const values = [...selected]\n .sort((a, b) => a - b)\n .map((selectedIndex) => options[selectedIndex]?.value)\n .filter((value): value is T => value != null);\n complete({ value: values, cancelled: false }, onComplete);\n }\n });\n\n return (\n <PromptFrame\n message={message}\n footer='↑↓ navigate space toggle enter select esc cancel'\n >\n {options.map((option, optionIndex) => (\n <OptionRow\n key={optionIndex}\n active={optionIndex === index}\n selected={selected.has(optionIndex)}\n label={option.label}\n hint={option.hint}\n />\n ))}\n {error ? <Text color='red'>{error}</Text> : null}\n </PromptFrame>\n );\n}\n\nfunction ConfirmPrompt({\n message,\n defaultValue,\n onComplete,\n}: ConfirmPromptProps) {\n const options = [\n { value: true, label: 'Yes' },\n { value: false, label: 'No' },\n ];\n const [index, setIndex] = useState(defaultValue ? 0 : 1);\n\n useInput((input, key) => {\n if (key.escape || (key.ctrl && input === 'c')) {\n complete(CANCELLED, onComplete);\n return;\n }\n if (key.leftArrow || key.upArrow || key.rightArrow || key.downArrow) {\n setIndex((current) => (current === 0 ? 1 : 0));\n return;\n }\n if (input.toLowerCase() === 'y') {\n complete({ value: true, cancelled: false }, onComplete);\n return;\n }\n if (input.toLowerCase() === 'n') {\n complete({ value: false, cancelled: false }, onComplete);\n return;\n }\n if (key.return) {\n complete({ value: options[index]!.value, cancelled: false }, onComplete);\n }\n });\n\n return (\n <PromptFrame\n message={message}\n footer='←→ choose y/n select enter confirm esc cancel'\n >\n {options.map((option, optionIndex) => (\n <OptionRow\n key={option.label}\n active={optionIndex === index}\n label={option.label}\n />\n ))}\n </PromptFrame>\n );\n}\n\nexport async function inkPromptText(\n options: Omit<TextPromptProps, 'onComplete'>\n) {\n return runPrompt<string>((onComplete) => (\n <TextPrompt {...options} onComplete={onComplete} />\n ));\n}\n\nexport async function inkPromptLocale(\n options: Omit<LocalePromptProps, 'onComplete'>\n) {\n return runPrompt<string>((onComplete) => (\n <LocalePrompt {...options} onComplete={onComplete} />\n ));\n}\n\nexport async function inkPromptLocaleMulti(\n options: Omit<LocaleMultiPromptProps, 'onComplete'>\n) {\n return runPrompt<string[]>((onComplete) => (\n <LocaleMultiPrompt {...options} onComplete={onComplete} />\n ));\n}\n\nexport async function inkPromptGlob(\n options: Omit<GlobPromptProps, 'onComplete'>\n) {\n return runPrompt<string>((onComplete) => (\n <GlobPrompt {...options} onComplete={onComplete} />\n ));\n}\n\nexport async function inkPromptSelect<T>(\n options: Omit<SelectPromptProps<T>, 'onComplete'>\n) {\n return runPrompt<T>((onComplete) => (\n <SelectPrompt {...options} onComplete={onComplete} />\n ));\n}\n\nexport async function inkPromptMultiSelect<T extends string>(\n options: Omit<MultiSelectPromptProps<T>, 'onComplete'>\n) {\n return runPrompt<Array<T>>((onComplete) => (\n <MultiSelectPrompt {...options} onComplete={onComplete} />\n ));\n}\n\nexport async function inkPromptConfirm(\n options: Omit<ConfirmPromptProps, 'onComplete'>\n) {\n return runPrompt<boolean>((onComplete) => (\n <ConfirmPrompt {...options} onComplete={onComplete} />\n ));\n}\n"],"mappings":"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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
|
+
import type { CustomMapping } from 'generaltranslation/types';
|
|
2
3
|
export type PromptOption<T> = {
|
|
3
4
|
value: T;
|
|
4
5
|
label: string;
|
|
@@ -24,12 +25,14 @@ export type LocaleOption = {
|
|
|
24
25
|
export type LocalePromptProps = {
|
|
25
26
|
message: string;
|
|
26
27
|
defaultValue?: string;
|
|
28
|
+
customMapping?: CustomMapping;
|
|
27
29
|
onComplete: (result: PromptResult<string>) => void;
|
|
28
30
|
};
|
|
29
31
|
export type LocaleMultiPromptProps = {
|
|
30
32
|
message: string;
|
|
31
33
|
defaultValue?: string[];
|
|
32
34
|
required: boolean;
|
|
35
|
+
customMapping?: CustomMapping;
|
|
33
36
|
onComplete: (result: PromptResult<string[]>) => void;
|
|
34
37
|
};
|
|
35
38
|
export type GlobPromptProps = {
|
package/dist/console/logger.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { SpinnerResult, ProgressResult } from '@clack/prompts';
|
|
2
2
|
export type LogFormat = 'default' | 'json';
|
|
3
3
|
export type LogLevel = 'debug' | 'info' | 'warn' | 'error';
|
|
4
|
+
export type ConsoleOutput = 'stdout' | 'stderr';
|
|
4
5
|
/**
|
|
5
6
|
* GT_LOG_FORMAT: default | json.
|
|
6
7
|
* - If default, logs will be pretty-printed using @clack/prompts.
|
|
@@ -16,8 +17,20 @@ declare class Logger {
|
|
|
16
17
|
private logFormat;
|
|
17
18
|
private logLevel;
|
|
18
19
|
private quiet;
|
|
20
|
+
private consoleOutput;
|
|
21
|
+
private consoleLoggers;
|
|
22
|
+
private clackOutput;
|
|
19
23
|
private constructor();
|
|
24
|
+
private createPinoLogger;
|
|
20
25
|
static getInstance(): Logger;
|
|
26
|
+
/**
|
|
27
|
+
* Route console output (Clack chatter and the JSON console logger) to
|
|
28
|
+
* stdout (the historical default) or stderr, so a command whose stdout is
|
|
29
|
+
* machine-readable can keep diagnostics off it. Reversible per invocation;
|
|
30
|
+
* a no-op when the direction is unchanged. The JSON logger keeps its
|
|
31
|
+
* current level and is flushed before switching. File logging is unaffected.
|
|
32
|
+
*/
|
|
33
|
+
setConsoleOutput(output: ConsoleOutput): void;
|
|
21
34
|
/**
|
|
22
35
|
* Enable or disable quiet mode. When quiet, informational chatter
|
|
23
36
|
* (info/step/success/message/debug/trace, spinners, progress bars, and
|
package/dist/console/logger.js
CHANGED
|
@@ -94,6 +94,9 @@ const logger = class Logger {
|
|
|
94
94
|
logFormat;
|
|
95
95
|
logLevel;
|
|
96
96
|
quiet = false;
|
|
97
|
+
consoleOutput = "stdout";
|
|
98
|
+
consoleLoggers = {};
|
|
99
|
+
clackOutput;
|
|
97
100
|
constructor() {
|
|
98
101
|
const format = (process.env.GT_LOG_FORMAT || "default").toLowerCase();
|
|
99
102
|
const logFile = process.env.GT_LOG_FILE;
|
|
@@ -108,20 +111,42 @@ const logger = class Logger {
|
|
|
108
111
|
}
|
|
109
112
|
this.logFormat = format;
|
|
110
113
|
this.logLevel = logLevel;
|
|
111
|
-
if (format === "json")
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
}
|
|
115
|
-
if (logFile) this.fileLogger =
|
|
116
|
-
|
|
114
|
+
if (format === "json") {
|
|
115
|
+
this.pinoLogger = this.createPinoLogger(process.stdout.fd, logLevel);
|
|
116
|
+
this.consoleLoggers.stdout = this.pinoLogger;
|
|
117
|
+
}
|
|
118
|
+
if (logFile) this.fileLogger = this.createPinoLogger(logFile, logLevel);
|
|
119
|
+
}
|
|
120
|
+
createPinoLogger(dest, level) {
|
|
121
|
+
return pino({
|
|
122
|
+
level,
|
|
117
123
|
mixin: () => ({ logId: randomUUID() })
|
|
118
|
-
}, destination(
|
|
124
|
+
}, destination(dest));
|
|
119
125
|
}
|
|
120
126
|
static getInstance() {
|
|
121
127
|
if (!Logger.instance) Logger.instance = new Logger();
|
|
122
128
|
return Logger.instance;
|
|
123
129
|
}
|
|
124
130
|
/**
|
|
131
|
+
* Route console output (Clack chatter and the JSON console logger) to
|
|
132
|
+
* stdout (the historical default) or stderr, so a command whose stdout is
|
|
133
|
+
* machine-readable can keep diagnostics off it. Reversible per invocation;
|
|
134
|
+
* a no-op when the direction is unchanged. The JSON logger keeps its
|
|
135
|
+
* current level and is flushed before switching. File logging is unaffected.
|
|
136
|
+
*/
|
|
137
|
+
setConsoleOutput(output) {
|
|
138
|
+
if (output === this.consoleOutput) return;
|
|
139
|
+
this.consoleOutput = output;
|
|
140
|
+
this.clackOutput = output === "stderr" ? { output: process.stderr } : void 0;
|
|
141
|
+
if (this.pinoLogger) {
|
|
142
|
+
this.pinoLogger.flush();
|
|
143
|
+
const next = this.consoleLoggers[output] ?? this.createPinoLogger(process[output].fd, this.pinoLogger.level);
|
|
144
|
+
next.level = this.pinoLogger.level;
|
|
145
|
+
this.consoleLoggers[output] = next;
|
|
146
|
+
this.pinoLogger = next;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
125
150
|
* Enable or disable quiet mode. When quiet, informational chatter
|
|
126
151
|
* (info/step/success/message/debug/trace, spinners, progress bars, and
|
|
127
152
|
* command intro/outro markers) is suppressed on the console, while warnings
|
|
@@ -139,42 +164,48 @@ const logger = class Logger {
|
|
|
139
164
|
trace(message) {
|
|
140
165
|
if (!this.quiet) if (this.logFormat === "default") {
|
|
141
166
|
endTerminalSession();
|
|
142
|
-
log.message(message, {
|
|
167
|
+
log.message(message, {
|
|
168
|
+
symbol: chalk.dim("•"),
|
|
169
|
+
...this.clackOutput
|
|
170
|
+
});
|
|
143
171
|
} else this.pinoLogger?.trace(message);
|
|
144
172
|
this.fileLogger?.trace(message);
|
|
145
173
|
}
|
|
146
174
|
debug(message) {
|
|
147
175
|
if (!this.quiet) if (this.logFormat === "default") {
|
|
148
176
|
endTerminalSession();
|
|
149
|
-
log.message(message, {
|
|
177
|
+
log.message(message, {
|
|
178
|
+
symbol: chalk.dim("◆"),
|
|
179
|
+
...this.clackOutput
|
|
180
|
+
});
|
|
150
181
|
} else this.pinoLogger?.debug(message);
|
|
151
182
|
this.fileLogger?.debug(message);
|
|
152
183
|
}
|
|
153
184
|
info(message) {
|
|
154
185
|
if (!this.quiet) if (this.logFormat === "default") {
|
|
155
186
|
endTerminalSession();
|
|
156
|
-
log.info(message);
|
|
187
|
+
log.info(message, this.clackOutput);
|
|
157
188
|
} else this.pinoLogger?.info(message);
|
|
158
189
|
this.fileLogger?.info(message);
|
|
159
190
|
}
|
|
160
191
|
warn(message) {
|
|
161
192
|
if (this.logFormat === "default") {
|
|
162
193
|
endTerminalSession();
|
|
163
|
-
log.warn(message);
|
|
194
|
+
log.warn(message, this.clackOutput);
|
|
164
195
|
} else this.pinoLogger?.warn(message);
|
|
165
196
|
this.fileLogger?.warn(message);
|
|
166
197
|
}
|
|
167
198
|
error(message) {
|
|
168
199
|
if (this.logFormat === "default") {
|
|
169
200
|
endTerminalSession();
|
|
170
|
-
log.error(message);
|
|
201
|
+
log.error(message, this.clackOutput);
|
|
171
202
|
} else this.pinoLogger?.error(message);
|
|
172
203
|
this.fileLogger?.error(message);
|
|
173
204
|
}
|
|
174
205
|
fatal(message) {
|
|
175
206
|
if (this.logFormat === "default") {
|
|
176
207
|
endTerminalSession();
|
|
177
|
-
log.error(message);
|
|
208
|
+
log.error(message, this.clackOutput);
|
|
178
209
|
} else this.pinoLogger?.fatal(message);
|
|
179
210
|
this.fileLogger?.fatal(message);
|
|
180
211
|
}
|
|
@@ -184,45 +215,54 @@ const logger = class Logger {
|
|
|
184
215
|
success(message) {
|
|
185
216
|
if (!this.quiet) if (this.logFormat === "default") {
|
|
186
217
|
endTerminalSession();
|
|
187
|
-
log.success(message);
|
|
218
|
+
log.success(message, this.clackOutput);
|
|
188
219
|
} else this.pinoLogger?.info(message);
|
|
189
220
|
this.fileLogger?.info(message);
|
|
190
221
|
}
|
|
191
222
|
step(message) {
|
|
192
223
|
if (!this.quiet) if (this.logFormat === "default") {
|
|
193
224
|
endTerminalSession();
|
|
194
|
-
log.step(message);
|
|
225
|
+
log.step(message, this.clackOutput);
|
|
195
226
|
} else this.pinoLogger?.info(message);
|
|
196
227
|
this.fileLogger?.info(message);
|
|
197
228
|
}
|
|
198
229
|
message(message, symbol) {
|
|
199
230
|
if (!this.quiet) if (this.logFormat === "default") {
|
|
200
231
|
endTerminalSession();
|
|
201
|
-
log.message(message, symbol ? {
|
|
232
|
+
log.message(message, symbol ? {
|
|
233
|
+
symbol,
|
|
234
|
+
...this.clackOutput
|
|
235
|
+
} : this.clackOutput);
|
|
202
236
|
} else this.pinoLogger?.info(message);
|
|
203
237
|
this.fileLogger?.info(message);
|
|
204
238
|
}
|
|
205
239
|
createSpinner(indicator = "timer") {
|
|
206
240
|
if (this.quiet) return new MockSpinner(this);
|
|
207
|
-
if (this.logFormat === "default") return wrapTerminalSessionAware(spinner({
|
|
241
|
+
if (this.logFormat === "default") return wrapTerminalSessionAware(spinner({
|
|
242
|
+
indicator,
|
|
243
|
+
...this.clackOutput
|
|
244
|
+
}));
|
|
208
245
|
else return new MockSpinner(this);
|
|
209
246
|
}
|
|
210
247
|
createProgressBar(total) {
|
|
211
248
|
if (this.quiet) return new MockProgress(total, this);
|
|
212
|
-
if (this.logFormat === "default") return wrapTerminalSessionAware(progress({
|
|
249
|
+
if (this.logFormat === "default") return wrapTerminalSessionAware(progress({
|
|
250
|
+
max: total,
|
|
251
|
+
...this.clackOutput
|
|
252
|
+
}));
|
|
213
253
|
else return new MockProgress(total, this);
|
|
214
254
|
}
|
|
215
255
|
startCommand(message) {
|
|
216
256
|
if (!this.quiet) if (this.logFormat === "default") {
|
|
217
257
|
endTerminalSession();
|
|
218
|
-
intro(chalk.cyan(message));
|
|
258
|
+
intro(chalk.cyan(message), this.clackOutput);
|
|
219
259
|
} else this.info(`╭─ ${message}`);
|
|
220
260
|
this.fileLogger?.info(`[START] ${message}`);
|
|
221
261
|
}
|
|
222
262
|
endCommand(message) {
|
|
223
263
|
if (!this.quiet) if (this.logFormat === "default") {
|
|
224
264
|
endTerminalSession();
|
|
225
|
-
outro(chalk.cyan(message));
|
|
265
|
+
outro(chalk.cyan(message), this.clackOutput);
|
|
226
266
|
} else this.info(`╰─ ${message}`);
|
|
227
267
|
this.fileLogger?.info(`[END] ${message}`);
|
|
228
268
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.js","names":[],"sources":["../../src/console/logger.ts"],"sourcesContent":["import chalk from 'chalk';\nimport { randomUUID } from 'node:crypto';\nimport { pino, destination } from 'pino';\nimport {\n log as clackLog,\n spinner,\n progress,\n intro,\n outro,\n} from '@clack/prompts';\nimport { endTerminalSession } from './terminalSession.js';\n\nimport type { Logger as PinoLogger } from 'pino';\nimport type { SpinnerResult, ProgressResult } from '@clack/prompts';\n\nfunction wrapTerminalSessionAware<T extends SpinnerResult | ProgressResult>(\n target: T\n): T {\n const start = target.start.bind(target);\n const stop = target.stop.bind(target);\n const message = target.message.bind(target);\n target.start = (msg?: string) => {\n endTerminalSession();\n return start(msg);\n };\n target.stop = (msg?: string, code?: number) => {\n endTerminalSession();\n return (stop as (m?: string, c?: number) => void)(msg, code);\n };\n target.message = (msg?: string) => {\n endTerminalSession();\n return message(msg);\n };\n if ('advance' in target) {\n const advance = target.advance.bind(target);\n target.advance = (amount: number, msg?: string) => {\n endTerminalSession();\n return advance(amount, msg);\n };\n }\n return target;\n}\n\nexport type LogFormat = 'default' | 'json';\nexport type LogLevel = 'debug' | 'info' | 'warn' | 'error';\n\n// Numeric ordering used to decide the quiet floor without lowering an\n// already-more-restrictive level chosen via GT_LOG_LEVEL.\nconst LOG_LEVEL_RANK: Record<LogLevel, number> = {\n debug: 10,\n info: 20,\n warn: 30,\n error: 40,\n};\n\n// Under --quiet, informational output is suppressed but warnings and errors\n// still print, so the console never drops below this level.\nconst QUIET_FLOOR_LEVEL: LogLevel = 'warn';\n\n// Mock spinner that logs to console instead of updating terminal UI\nclass MockSpinner implements SpinnerResult {\n private currentMessage: string = '';\n private logger: Logger;\n isCancelled: boolean = false;\n\n constructor(logger: Logger) {\n this.logger = logger;\n }\n\n start(message?: string): void {\n if (message) {\n this.currentMessage = message;\n this.logger.info(`[Spinner] ${message}`);\n }\n }\n\n stop(message?: string): void {\n const msg = message || this.currentMessage;\n if (msg) {\n this.logger.info(`[Spinner] ${msg}`);\n }\n this.currentMessage = '';\n }\n\n message(message?: string): void {\n if (message) {\n this.currentMessage = message;\n this.logger.info(`[Spinner] ${message}`);\n }\n }\n}\n\n// Mock progress bar that logs to console instead of updating terminal UI\nclass MockProgress implements ProgressResult {\n private max: number;\n private current: number = 0;\n private logger: Logger;\n isCancelled: boolean = false;\n\n constructor(max: number, logger: Logger) {\n this.max = max;\n this.logger = logger;\n }\n\n start(message?: string): void {\n const msg = message || 'Starting progress';\n this.logger.info(`[Progress] ${msg} (0/${this.max})`);\n }\n\n stop(message?: string): void {\n const msg = message || 'Complete';\n this.logger.info(`[Progress] ${msg} (${this.current}/${this.max})`);\n }\n\n message(message?: string): void {\n if (message) {\n this.logger.info(`[Progress] ${message} (${this.current}/${this.max})`);\n }\n }\n\n advance(amount: number, message?: string): void {\n this.current += amount;\n const msg = message || 'Progress';\n this.logger.info(`[Progress] ${msg} (${this.current}/${this.max})`);\n }\n}\n\n/**\n * GT_LOG_FORMAT: default | json.\n * - If default, logs will be pretty-printed using @clack/prompts.\n * - If json, logs will be written in JSON format to the console.\n * GT_LOG_FILE: If specified, logs will be written to the file.\n * GT_LOG_LEVEL: The level of logs to write. If not specified, defaults to 'info'.\n * - Valid levels: debug, info, warn, error.\n */\nclass Logger {\n private static instance: Logger;\n private pinoLogger: PinoLogger | null = null;\n private fileLogger: PinoLogger | null = null;\n private logFormat: LogFormat;\n private logLevel: LogLevel;\n private quiet = false;\n\n private constructor() {\n // Read configuration from environment variables\n const format = (\n process.env.GT_LOG_FORMAT || 'default'\n ).toLowerCase() as LogFormat;\n const logFile = process.env.GT_LOG_FILE;\n const logLevel = process.env.GT_LOG_LEVEL || 'info';\n\n if (format !== 'default' && format !== 'json') {\n console.error('Invalid log format');\n process.exit(1);\n }\n if (\n logLevel !== 'debug' &&\n logLevel !== 'info' &&\n logLevel !== 'warn' &&\n logLevel !== 'error'\n ) {\n console.error('Invalid log level');\n process.exit(1);\n }\n\n this.logFormat = format;\n this.logLevel = logLevel as LogLevel;\n\n // Console output (stdout) - only for JSON format\n // For 'default' format, we use @clack/prompts directly\n if (format === 'json') {\n this.pinoLogger = pino(\n {\n level: logLevel,\n mixin: () => ({\n logId: randomUUID(),\n }),\n },\n destination(1)\n );\n }\n\n // File output (if specified) - always JSON format\n if (logFile) {\n this.fileLogger = pino(\n {\n level: logLevel,\n mixin: () => ({\n logId: randomUUID(),\n }),\n },\n destination(logFile)\n );\n }\n }\n\n static getInstance(): Logger {\n if (!Logger.instance) {\n Logger.instance = new Logger();\n }\n return Logger.instance;\n }\n\n /**\n * Enable or disable quiet mode. When quiet, informational chatter\n * (info/step/success/message/debug/trace, spinners, progress bars, and\n * command intro/outro markers) is suppressed on the console, while warnings\n * and errors still print. Quiet wins over GT_LOG_LEVEL but never lowers an\n * already-more-restrictive level. File logging is unaffected so an explicit\n * GT_LOG_FILE still captures everything.\n */\n setQuiet(quiet: boolean): void {\n this.quiet = quiet;\n if (this.pinoLogger) {\n this.pinoLogger.level = quiet\n ? LOG_LEVEL_RANK[this.logLevel] > LOG_LEVEL_RANK[QUIET_FLOOR_LEVEL]\n ? this.logLevel\n : QUIET_FLOOR_LEVEL\n : this.logLevel;\n }\n }\n\n isQuiet(): boolean {\n return this.quiet;\n }\n\n // Standard logging methods\n trace(message: string): void {\n if (!this.quiet) {\n if (this.logFormat === 'default') {\n endTerminalSession();\n // @clack/prompts doesn't have trace, use message\n clackLog.message(message, { symbol: chalk.dim('•') });\n } else {\n this.pinoLogger?.trace(message);\n }\n }\n this.fileLogger?.trace(message);\n }\n\n debug(message: string): void {\n if (!this.quiet) {\n if (this.logFormat === 'default') {\n endTerminalSession();\n // @clack/prompts doesn't have debug, use message\n clackLog.message(message, { symbol: chalk.dim('◆') });\n } else {\n this.pinoLogger?.debug(message);\n }\n }\n this.fileLogger?.debug(message);\n }\n\n info(message: string): void {\n if (!this.quiet) {\n if (this.logFormat === 'default') {\n endTerminalSession();\n clackLog.info(message);\n } else {\n this.pinoLogger?.info(message);\n }\n }\n this.fileLogger?.info(message);\n }\n\n warn(message: string): void {\n if (this.logFormat === 'default') {\n endTerminalSession();\n clackLog.warn(message);\n } else {\n this.pinoLogger?.warn(message);\n }\n this.fileLogger?.warn(message);\n }\n\n error(message: string): void {\n if (this.logFormat === 'default') {\n endTerminalSession();\n clackLog.error(message);\n } else {\n this.pinoLogger?.error(message);\n }\n this.fileLogger?.error(message);\n }\n\n fatal(message: string): void {\n if (this.logFormat === 'default') {\n endTerminalSession();\n clackLog.error(message); // @clack/prompts doesn't have fatal, use error\n } else {\n this.pinoLogger?.fatal(message);\n }\n this.fileLogger?.fatal(message);\n }\n\n silent(message: string): void {\n // Silent doesn't log to console, only to file\n this.fileLogger?.silent(message);\n }\n\n // @clack/prompts specific methods (for 'default' format)\n success(message: string): void {\n if (!this.quiet) {\n if (this.logFormat === 'default') {\n endTerminalSession();\n clackLog.success(message);\n } else {\n this.pinoLogger?.info(message); // Map to info for non-default formats\n }\n }\n this.fileLogger?.info(message);\n }\n\n step(message: string): void {\n if (!this.quiet) {\n if (this.logFormat === 'default') {\n endTerminalSession();\n clackLog.step(message);\n } else {\n this.pinoLogger?.info(message); // Map to info for non-default formats\n }\n }\n this.fileLogger?.info(message);\n }\n\n message(message: string, symbol?: string): void {\n if (!this.quiet) {\n if (this.logFormat === 'default') {\n endTerminalSession();\n clackLog.message(message, symbol ? { symbol } : undefined);\n } else {\n this.pinoLogger?.info(message); // Map to info for non-default formats\n }\n }\n this.fileLogger?.info(message);\n }\n\n // Spinner functionality\n createSpinner(indicator: 'dots' | 'timer' = 'timer'): SpinnerResult {\n // Quiet mode suppresses spinner UI; the mock routes through the gated\n // info() so nothing reaches the console while file logging is preserved.\n if (this.quiet) {\n return new MockSpinner(this);\n }\n if (this.logFormat === 'default') {\n return wrapTerminalSessionAware(spinner({ indicator }));\n } else {\n return new MockSpinner(this);\n }\n }\n\n // Progress bar functionality\n createProgressBar(total: number): ProgressResult {\n if (this.quiet) {\n return new MockProgress(total, this);\n }\n if (this.logFormat === 'default') {\n return wrapTerminalSessionAware(progress({ max: total }));\n } else {\n return new MockProgress(total, this);\n }\n }\n\n // Command start/end markers\n startCommand(message: string): void {\n if (!this.quiet) {\n if (this.logFormat === 'default') {\n endTerminalSession();\n intro(chalk.cyan(message));\n } else {\n this.info(`╭─ ${message}`);\n }\n }\n this.fileLogger?.info(`[START] ${message}`);\n }\n\n endCommand(message: string): void {\n if (!this.quiet) {\n if (this.logFormat === 'default') {\n endTerminalSession();\n outro(chalk.cyan(message));\n } else {\n this.info(`╰─ ${message}`);\n }\n }\n this.fileLogger?.info(`[END] ${message}`);\n }\n\n // Flush logs to ensure they're written before process exit\n flush(): void {\n this.pinoLogger?.flush();\n this.fileLogger?.flush();\n }\n}\n\nexport const logger = Logger.getInstance();\n"],"mappings":";;;;;;AAeA,SAAS,yBACP,QACG;CACH,MAAM,QAAQ,OAAO,MAAM,KAAK,OAAO;CACvC,MAAM,OAAO,OAAO,KAAK,KAAK,OAAO;CACrC,MAAM,UAAU,OAAO,QAAQ,KAAK,OAAO;AAC3C,QAAO,SAAS,QAAiB;AAC/B,sBAAoB;AACpB,SAAO,MAAM,IAAI;;AAEnB,QAAO,QAAQ,KAAc,SAAkB;AAC7C,sBAAoB;AACpB,SAAQ,KAA0C,KAAK,KAAK;;AAE9D,QAAO,WAAW,QAAiB;AACjC,sBAAoB;AACpB,SAAO,QAAQ,IAAI;;AAErB,KAAI,aAAa,QAAQ;EACvB,MAAM,UAAU,OAAO,QAAQ,KAAK,OAAO;AAC3C,SAAO,WAAW,QAAgB,QAAiB;AACjD,uBAAoB;AACpB,UAAO,QAAQ,QAAQ,IAAI;;;AAG/B,QAAO;;AAQT,MAAM,iBAA2C;CAC/C,OAAO;CACP,MAAM;CACN,MAAM;CACN,OAAO;CACR;AAID,MAAM,oBAA8B;AAGpC,IAAM,cAAN,MAA2C;CACzC,iBAAiC;CACjC;CACA,cAAuB;CAEvB,YAAY,QAAgB;AAC1B,OAAK,SAAS;;CAGhB,MAAM,SAAwB;AAC5B,MAAI,SAAS;AACX,QAAK,iBAAiB;AACtB,QAAK,OAAO,KAAK,aAAa,UAAU;;;CAI5C,KAAK,SAAwB;EAC3B,MAAM,MAAM,WAAW,KAAK;AAC5B,MAAI,IACF,MAAK,OAAO,KAAK,aAAa,MAAM;AAEtC,OAAK,iBAAiB;;CAGxB,QAAQ,SAAwB;AAC9B,MAAI,SAAS;AACX,QAAK,iBAAiB;AACtB,QAAK,OAAO,KAAK,aAAa,UAAU;;;;AAM9C,IAAM,eAAN,MAA6C;CAC3C;CACA,UAA0B;CAC1B;CACA,cAAuB;CAEvB,YAAY,KAAa,QAAgB;AACvC,OAAK,MAAM;AACX,OAAK,SAAS;;CAGhB,MAAM,SAAwB;EAC5B,MAAM,MAAM,WAAW;AACvB,OAAK,OAAO,KAAK,cAAc,IAAI,MAAM,KAAK,IAAI,GAAG;;CAGvD,KAAK,SAAwB;EAC3B,MAAM,MAAM,WAAW;AACvB,OAAK,OAAO,KAAK,cAAc,IAAI,IAAI,KAAK,QAAQ,GAAG,KAAK,IAAI,GAAG;;CAGrE,QAAQ,SAAwB;AAC9B,MAAI,QACF,MAAK,OAAO,KAAK,cAAc,QAAQ,IAAI,KAAK,QAAQ,GAAG,KAAK,IAAI,GAAG;;CAI3E,QAAQ,QAAgB,SAAwB;AAC9C,OAAK,WAAW;EAChB,MAAM,MAAM,WAAW;AACvB,OAAK,OAAO,KAAK,cAAc,IAAI,IAAI,KAAK,QAAQ,GAAG,KAAK,IAAI,GAAG;;;AAgRvE,MAAa,SAAS,MApQhB,OAAO;CACX,OAAe;CACf,aAAwC;CACxC,aAAwC;CACxC;CACA;CACA,QAAgB;CAEhB,cAAsB;EAEpB,MAAM,UACJ,QAAQ,IAAI,iBAAiB,WAC7B,aAAa;EACf,MAAM,UAAU,QAAQ,IAAI;EAC5B,MAAM,WAAW,QAAQ,IAAI,gBAAgB;AAE7C,MAAI,WAAW,aAAa,WAAW,QAAQ;AAC7C,WAAQ,MAAM,qBAAqB;AACnC,WAAQ,KAAK,EAAE;;AAEjB,MACE,aAAa,WACb,aAAa,UACb,aAAa,UACb,aAAa,SACb;AACA,WAAQ,MAAM,oBAAoB;AAClC,WAAQ,KAAK,EAAE;;AAGjB,OAAK,YAAY;AACjB,OAAK,WAAW;AAIhB,MAAI,WAAW,OACb,MAAK,aAAa,KAChB;GACE,OAAO;GACP,cAAc,EACZ,OAAO,YAAY,EACpB;GACF,EACD,YAAY,EAAE,CACf;AAIH,MAAI,QACF,MAAK,aAAa,KAChB;GACE,OAAO;GACP,cAAc,EACZ,OAAO,YAAY,EACpB;GACF,EACD,YAAY,QAAQ,CACrB;;CAIL,OAAO,cAAsB;AAC3B,MAAI,CAAC,OAAO,SACV,QAAO,WAAW,IAAI,QAAQ;AAEhC,SAAO,OAAO;;;;;;;;;;CAWhB,SAAS,OAAsB;AAC7B,OAAK,QAAQ;AACb,MAAI,KAAK,WACP,MAAK,WAAW,QAAQ,QACpB,eAAe,KAAK,YAAY,eAAe,qBAC7C,KAAK,WACL,oBACF,KAAK;;CAIb,UAAmB;AACjB,SAAO,KAAK;;CAId,MAAM,SAAuB;AAC3B,MAAI,CAAC,KAAK,MACR,KAAI,KAAK,cAAc,WAAW;AAChC,uBAAoB;AAEpB,OAAS,QAAQ,SAAS,EAAE,QAAQ,MAAM,IAAI,IAAI,EAAE,CAAC;QAErD,MAAK,YAAY,MAAM,QAAQ;AAGnC,OAAK,YAAY,MAAM,QAAQ;;CAGjC,MAAM,SAAuB;AAC3B,MAAI,CAAC,KAAK,MACR,KAAI,KAAK,cAAc,WAAW;AAChC,uBAAoB;AAEpB,OAAS,QAAQ,SAAS,EAAE,QAAQ,MAAM,IAAI,IAAI,EAAE,CAAC;QAErD,MAAK,YAAY,MAAM,QAAQ;AAGnC,OAAK,YAAY,MAAM,QAAQ;;CAGjC,KAAK,SAAuB;AAC1B,MAAI,CAAC,KAAK,MACR,KAAI,KAAK,cAAc,WAAW;AAChC,uBAAoB;AACpB,OAAS,KAAK,QAAQ;QAEtB,MAAK,YAAY,KAAK,QAAQ;AAGlC,OAAK,YAAY,KAAK,QAAQ;;CAGhC,KAAK,SAAuB;AAC1B,MAAI,KAAK,cAAc,WAAW;AAChC,uBAAoB;AACpB,OAAS,KAAK,QAAQ;QAEtB,MAAK,YAAY,KAAK,QAAQ;AAEhC,OAAK,YAAY,KAAK,QAAQ;;CAGhC,MAAM,SAAuB;AAC3B,MAAI,KAAK,cAAc,WAAW;AAChC,uBAAoB;AACpB,OAAS,MAAM,QAAQ;QAEvB,MAAK,YAAY,MAAM,QAAQ;AAEjC,OAAK,YAAY,MAAM,QAAQ;;CAGjC,MAAM,SAAuB;AAC3B,MAAI,KAAK,cAAc,WAAW;AAChC,uBAAoB;AACpB,OAAS,MAAM,QAAQ;QAEvB,MAAK,YAAY,MAAM,QAAQ;AAEjC,OAAK,YAAY,MAAM,QAAQ;;CAGjC,OAAO,SAAuB;AAE5B,OAAK,YAAY,OAAO,QAAQ;;CAIlC,QAAQ,SAAuB;AAC7B,MAAI,CAAC,KAAK,MACR,KAAI,KAAK,cAAc,WAAW;AAChC,uBAAoB;AACpB,OAAS,QAAQ,QAAQ;QAEzB,MAAK,YAAY,KAAK,QAAQ;AAGlC,OAAK,YAAY,KAAK,QAAQ;;CAGhC,KAAK,SAAuB;AAC1B,MAAI,CAAC,KAAK,MACR,KAAI,KAAK,cAAc,WAAW;AAChC,uBAAoB;AACpB,OAAS,KAAK,QAAQ;QAEtB,MAAK,YAAY,KAAK,QAAQ;AAGlC,OAAK,YAAY,KAAK,QAAQ;;CAGhC,QAAQ,SAAiB,QAAuB;AAC9C,MAAI,CAAC,KAAK,MACR,KAAI,KAAK,cAAc,WAAW;AAChC,uBAAoB;AACpB,OAAS,QAAQ,SAAS,SAAS,EAAE,QAAQ,GAAG,KAAA,EAAU;QAE1D,MAAK,YAAY,KAAK,QAAQ;AAGlC,OAAK,YAAY,KAAK,QAAQ;;CAIhC,cAAc,YAA8B,SAAwB;AAGlE,MAAI,KAAK,MACP,QAAO,IAAI,YAAY,KAAK;AAE9B,MAAI,KAAK,cAAc,UACrB,QAAO,yBAAyB,QAAQ,EAAE,WAAW,CAAC,CAAC;MAEvD,QAAO,IAAI,YAAY,KAAK;;CAKhC,kBAAkB,OAA+B;AAC/C,MAAI,KAAK,MACP,QAAO,IAAI,aAAa,OAAO,KAAK;AAEtC,MAAI,KAAK,cAAc,UACrB,QAAO,yBAAyB,SAAS,EAAE,KAAK,OAAO,CAAC,CAAC;MAEzD,QAAO,IAAI,aAAa,OAAO,KAAK;;CAKxC,aAAa,SAAuB;AAClC,MAAI,CAAC,KAAK,MACR,KAAI,KAAK,cAAc,WAAW;AAChC,uBAAoB;AACpB,SAAM,MAAM,KAAK,QAAQ,CAAC;QAE1B,MAAK,KAAK,MAAM,UAAU;AAG9B,OAAK,YAAY,KAAK,WAAW,UAAU;;CAG7C,WAAW,SAAuB;AAChC,MAAI,CAAC,KAAK,MACR,KAAI,KAAK,cAAc,WAAW;AAChC,uBAAoB;AACpB,SAAM,MAAM,KAAK,QAAQ,CAAC;QAE1B,MAAK,KAAK,MAAM,UAAU;AAG9B,OAAK,YAAY,KAAK,SAAS,UAAU;;CAI3C,QAAc;AACZ,OAAK,YAAY,OAAO;AACxB,OAAK,YAAY,OAAO;;EAIC,aAAa"}
|
|
1
|
+
{"version":3,"file":"logger.js","names":[],"sources":["../../src/console/logger.ts"],"sourcesContent":["import chalk from 'chalk';\nimport { randomUUID } from 'node:crypto';\nimport { pino, destination } from 'pino';\nimport {\n log as clackLog,\n spinner,\n progress,\n intro,\n outro,\n} from '@clack/prompts';\nimport { endTerminalSession } from './terminalSession.js';\n\nimport type { Logger as PinoLogger } from 'pino';\nimport type { SpinnerResult, ProgressResult } from '@clack/prompts';\nimport type { Writable } from 'node:stream';\n\nfunction wrapTerminalSessionAware<T extends SpinnerResult | ProgressResult>(\n target: T\n): T {\n const start = target.start.bind(target);\n const stop = target.stop.bind(target);\n const message = target.message.bind(target);\n target.start = (msg?: string) => {\n endTerminalSession();\n return start(msg);\n };\n target.stop = (msg?: string, code?: number) => {\n endTerminalSession();\n return (stop as (m?: string, c?: number) => void)(msg, code);\n };\n target.message = (msg?: string) => {\n endTerminalSession();\n return message(msg);\n };\n if ('advance' in target) {\n const advance = target.advance.bind(target);\n target.advance = (amount: number, msg?: string) => {\n endTerminalSession();\n return advance(amount, msg);\n };\n }\n return target;\n}\n\nexport type LogFormat = 'default' | 'json';\nexport type LogLevel = 'debug' | 'info' | 'warn' | 'error';\nexport type ConsoleOutput = 'stdout' | 'stderr';\n\n// Numeric ordering used to decide the quiet floor without lowering an\n// already-more-restrictive level chosen via GT_LOG_LEVEL.\nconst LOG_LEVEL_RANK: Record<LogLevel, number> = {\n debug: 10,\n info: 20,\n warn: 30,\n error: 40,\n};\n\n// Under --quiet, informational output is suppressed but warnings and errors\n// still print, so the console never drops below this level.\nconst QUIET_FLOOR_LEVEL: LogLevel = 'warn';\n\n// Mock spinner that logs to console instead of updating terminal UI\nclass MockSpinner implements SpinnerResult {\n private currentMessage: string = '';\n private logger: Logger;\n isCancelled: boolean = false;\n\n constructor(logger: Logger) {\n this.logger = logger;\n }\n\n start(message?: string): void {\n if (message) {\n this.currentMessage = message;\n this.logger.info(`[Spinner] ${message}`);\n }\n }\n\n stop(message?: string): void {\n const msg = message || this.currentMessage;\n if (msg) {\n this.logger.info(`[Spinner] ${msg}`);\n }\n this.currentMessage = '';\n }\n\n message(message?: string): void {\n if (message) {\n this.currentMessage = message;\n this.logger.info(`[Spinner] ${message}`);\n }\n }\n}\n\n// Mock progress bar that logs to console instead of updating terminal UI\nclass MockProgress implements ProgressResult {\n private max: number;\n private current: number = 0;\n private logger: Logger;\n isCancelled: boolean = false;\n\n constructor(max: number, logger: Logger) {\n this.max = max;\n this.logger = logger;\n }\n\n start(message?: string): void {\n const msg = message || 'Starting progress';\n this.logger.info(`[Progress] ${msg} (0/${this.max})`);\n }\n\n stop(message?: string): void {\n const msg = message || 'Complete';\n this.logger.info(`[Progress] ${msg} (${this.current}/${this.max})`);\n }\n\n message(message?: string): void {\n if (message) {\n this.logger.info(`[Progress] ${message} (${this.current}/${this.max})`);\n }\n }\n\n advance(amount: number, message?: string): void {\n this.current += amount;\n const msg = message || 'Progress';\n this.logger.info(`[Progress] ${msg} (${this.current}/${this.max})`);\n }\n}\n\n/**\n * GT_LOG_FORMAT: default | json.\n * - If default, logs will be pretty-printed using @clack/prompts.\n * - If json, logs will be written in JSON format to the console.\n * GT_LOG_FILE: If specified, logs will be written to the file.\n * GT_LOG_LEVEL: The level of logs to write. If not specified, defaults to 'info'.\n * - Valid levels: debug, info, warn, error.\n */\nclass Logger {\n private static instance: Logger;\n private pinoLogger: PinoLogger | null = null;\n private fileLogger: PinoLogger | null = null;\n private logFormat: LogFormat;\n private logLevel: LogLevel;\n private quiet = false;\n private consoleOutput: ConsoleOutput = 'stdout';\n // One JSON console logger per stream so switching direction within a\n // process reuses the existing SonicBoom instead of recreating it.\n private consoleLoggers: Partial<Record<ConsoleOutput, PinoLogger>> = {};\n // Clack writes to stdout unless told otherwise; unset keeps its default so\n // ordinary commands are untouched while stderr routing redirects it.\n private clackOutput: { output: Writable } | undefined;\n\n private constructor() {\n // Read configuration from environment variables\n const format = (\n process.env.GT_LOG_FORMAT || 'default'\n ).toLowerCase() as LogFormat;\n const logFile = process.env.GT_LOG_FILE;\n const logLevel = process.env.GT_LOG_LEVEL || 'info';\n\n if (format !== 'default' && format !== 'json') {\n console.error('Invalid log format');\n process.exit(1);\n }\n if (\n logLevel !== 'debug' &&\n logLevel !== 'info' &&\n logLevel !== 'warn' &&\n logLevel !== 'error'\n ) {\n console.error('Invalid log level');\n process.exit(1);\n }\n\n this.logFormat = format;\n this.logLevel = logLevel as LogLevel;\n\n // Console output (stdout) - only for JSON format\n // For 'default' format, we use @clack/prompts directly\n if (format === 'json') {\n this.pinoLogger = this.createPinoLogger(process.stdout.fd, logLevel);\n this.consoleLoggers.stdout = this.pinoLogger;\n }\n\n // File output (if specified) - always JSON format\n if (logFile) {\n this.fileLogger = this.createPinoLogger(logFile, logLevel);\n }\n }\n\n private createPinoLogger(dest: number | string, level: string): PinoLogger {\n return pino(\n {\n level,\n mixin: () => ({\n logId: randomUUID(),\n }),\n },\n destination(dest)\n );\n }\n\n static getInstance(): Logger {\n if (!Logger.instance) {\n Logger.instance = new Logger();\n }\n return Logger.instance;\n }\n\n /**\n * Route console output (Clack chatter and the JSON console logger) to\n * stdout (the historical default) or stderr, so a command whose stdout is\n * machine-readable can keep diagnostics off it. Reversible per invocation;\n * a no-op when the direction is unchanged. The JSON logger keeps its\n * current level and is flushed before switching. File logging is unaffected.\n */\n setConsoleOutput(output: ConsoleOutput): void {\n if (output === this.consoleOutput) return;\n this.consoleOutput = output;\n this.clackOutput =\n output === 'stderr' ? { output: process.stderr } : undefined;\n if (this.pinoLogger) {\n this.pinoLogger.flush();\n const next =\n this.consoleLoggers[output] ??\n this.createPinoLogger(process[output].fd, this.pinoLogger.level);\n next.level = this.pinoLogger.level;\n this.consoleLoggers[output] = next;\n this.pinoLogger = next;\n }\n }\n\n /**\n * Enable or disable quiet mode. When quiet, informational chatter\n * (info/step/success/message/debug/trace, spinners, progress bars, and\n * command intro/outro markers) is suppressed on the console, while warnings\n * and errors still print. Quiet wins over GT_LOG_LEVEL but never lowers an\n * already-more-restrictive level. File logging is unaffected so an explicit\n * GT_LOG_FILE still captures everything.\n */\n setQuiet(quiet: boolean): void {\n this.quiet = quiet;\n if (this.pinoLogger) {\n this.pinoLogger.level = quiet\n ? LOG_LEVEL_RANK[this.logLevel] > LOG_LEVEL_RANK[QUIET_FLOOR_LEVEL]\n ? this.logLevel\n : QUIET_FLOOR_LEVEL\n : this.logLevel;\n }\n }\n\n isQuiet(): boolean {\n return this.quiet;\n }\n\n // Standard logging methods\n trace(message: string): void {\n if (!this.quiet) {\n if (this.logFormat === 'default') {\n endTerminalSession();\n // @clack/prompts doesn't have trace, use message\n clackLog.message(message, {\n symbol: chalk.dim('•'),\n ...this.clackOutput,\n });\n } else {\n this.pinoLogger?.trace(message);\n }\n }\n this.fileLogger?.trace(message);\n }\n\n debug(message: string): void {\n if (!this.quiet) {\n if (this.logFormat === 'default') {\n endTerminalSession();\n // @clack/prompts doesn't have debug, use message\n clackLog.message(message, {\n symbol: chalk.dim('◆'),\n ...this.clackOutput,\n });\n } else {\n this.pinoLogger?.debug(message);\n }\n }\n this.fileLogger?.debug(message);\n }\n\n info(message: string): void {\n if (!this.quiet) {\n if (this.logFormat === 'default') {\n endTerminalSession();\n clackLog.info(message, this.clackOutput);\n } else {\n this.pinoLogger?.info(message);\n }\n }\n this.fileLogger?.info(message);\n }\n\n warn(message: string): void {\n if (this.logFormat === 'default') {\n endTerminalSession();\n clackLog.warn(message, this.clackOutput);\n } else {\n this.pinoLogger?.warn(message);\n }\n this.fileLogger?.warn(message);\n }\n\n error(message: string): void {\n if (this.logFormat === 'default') {\n endTerminalSession();\n clackLog.error(message, this.clackOutput);\n } else {\n this.pinoLogger?.error(message);\n }\n this.fileLogger?.error(message);\n }\n\n fatal(message: string): void {\n if (this.logFormat === 'default') {\n endTerminalSession();\n // @clack/prompts doesn't have fatal, use error\n clackLog.error(message, this.clackOutput);\n } else {\n this.pinoLogger?.fatal(message);\n }\n this.fileLogger?.fatal(message);\n }\n\n silent(message: string): void {\n // Silent doesn't log to console, only to file\n this.fileLogger?.silent(message);\n }\n\n // @clack/prompts specific methods (for 'default' format)\n success(message: string): void {\n if (!this.quiet) {\n if (this.logFormat === 'default') {\n endTerminalSession();\n clackLog.success(message, this.clackOutput);\n } else {\n this.pinoLogger?.info(message); // Map to info for non-default formats\n }\n }\n this.fileLogger?.info(message);\n }\n\n step(message: string): void {\n if (!this.quiet) {\n if (this.logFormat === 'default') {\n endTerminalSession();\n clackLog.step(message, this.clackOutput);\n } else {\n this.pinoLogger?.info(message); // Map to info for non-default formats\n }\n }\n this.fileLogger?.info(message);\n }\n\n message(message: string, symbol?: string): void {\n if (!this.quiet) {\n if (this.logFormat === 'default') {\n endTerminalSession();\n clackLog.message(\n message,\n symbol ? { symbol, ...this.clackOutput } : this.clackOutput\n );\n } else {\n this.pinoLogger?.info(message); // Map to info for non-default formats\n }\n }\n this.fileLogger?.info(message);\n }\n\n // Spinner functionality\n createSpinner(indicator: 'dots' | 'timer' = 'timer'): SpinnerResult {\n // Quiet mode suppresses spinner UI; the mock routes through the gated\n // info() so nothing reaches the console while file logging is preserved.\n if (this.quiet) {\n return new MockSpinner(this);\n }\n if (this.logFormat === 'default') {\n return wrapTerminalSessionAware(\n spinner({ indicator, ...this.clackOutput })\n );\n } else {\n return new MockSpinner(this);\n }\n }\n\n // Progress bar functionality\n createProgressBar(total: number): ProgressResult {\n if (this.quiet) {\n return new MockProgress(total, this);\n }\n if (this.logFormat === 'default') {\n return wrapTerminalSessionAware(\n progress({ max: total, ...this.clackOutput })\n );\n } else {\n return new MockProgress(total, this);\n }\n }\n\n // Command start/end markers\n startCommand(message: string): void {\n if (!this.quiet) {\n if (this.logFormat === 'default') {\n endTerminalSession();\n intro(chalk.cyan(message), this.clackOutput);\n } else {\n this.info(`╭─ ${message}`);\n }\n }\n this.fileLogger?.info(`[START] ${message}`);\n }\n\n endCommand(message: string): void {\n if (!this.quiet) {\n if (this.logFormat === 'default') {\n endTerminalSession();\n outro(chalk.cyan(message), this.clackOutput);\n } else {\n this.info(`╰─ ${message}`);\n }\n }\n this.fileLogger?.info(`[END] ${message}`);\n }\n\n // Flush logs to ensure they're written before process exit\n flush(): void {\n this.pinoLogger?.flush();\n this.fileLogger?.flush();\n }\n}\n\nexport const logger = Logger.getInstance();\n"],"mappings":";;;;;;AAgBA,SAAS,yBACP,QACG;CACH,MAAM,QAAQ,OAAO,MAAM,KAAK,OAAO;CACvC,MAAM,OAAO,OAAO,KAAK,KAAK,OAAO;CACrC,MAAM,UAAU,OAAO,QAAQ,KAAK,OAAO;AAC3C,QAAO,SAAS,QAAiB;AAC/B,sBAAoB;AACpB,SAAO,MAAM,IAAI;;AAEnB,QAAO,QAAQ,KAAc,SAAkB;AAC7C,sBAAoB;AACpB,SAAQ,KAA0C,KAAK,KAAK;;AAE9D,QAAO,WAAW,QAAiB;AACjC,sBAAoB;AACpB,SAAO,QAAQ,IAAI;;AAErB,KAAI,aAAa,QAAQ;EACvB,MAAM,UAAU,OAAO,QAAQ,KAAK,OAAO;AAC3C,SAAO,WAAW,QAAgB,QAAiB;AACjD,uBAAoB;AACpB,UAAO,QAAQ,QAAQ,IAAI;;;AAG/B,QAAO;;AAST,MAAM,iBAA2C;CAC/C,OAAO;CACP,MAAM;CACN,MAAM;CACN,OAAO;CACR;AAID,MAAM,oBAA8B;AAGpC,IAAM,cAAN,MAA2C;CACzC,iBAAiC;CACjC;CACA,cAAuB;CAEvB,YAAY,QAAgB;AAC1B,OAAK,SAAS;;CAGhB,MAAM,SAAwB;AAC5B,MAAI,SAAS;AACX,QAAK,iBAAiB;AACtB,QAAK,OAAO,KAAK,aAAa,UAAU;;;CAI5C,KAAK,SAAwB;EAC3B,MAAM,MAAM,WAAW,KAAK;AAC5B,MAAI,IACF,MAAK,OAAO,KAAK,aAAa,MAAM;AAEtC,OAAK,iBAAiB;;CAGxB,QAAQ,SAAwB;AAC9B,MAAI,SAAS;AACX,QAAK,iBAAiB;AACtB,QAAK,OAAO,KAAK,aAAa,UAAU;;;;AAM9C,IAAM,eAAN,MAA6C;CAC3C;CACA,UAA0B;CAC1B;CACA,cAAuB;CAEvB,YAAY,KAAa,QAAgB;AACvC,OAAK,MAAM;AACX,OAAK,SAAS;;CAGhB,MAAM,SAAwB;EAC5B,MAAM,MAAM,WAAW;AACvB,OAAK,OAAO,KAAK,cAAc,IAAI,MAAM,KAAK,IAAI,GAAG;;CAGvD,KAAK,SAAwB;EAC3B,MAAM,MAAM,WAAW;AACvB,OAAK,OAAO,KAAK,cAAc,IAAI,IAAI,KAAK,QAAQ,GAAG,KAAK,IAAI,GAAG;;CAGrE,QAAQ,SAAwB;AAC9B,MAAI,QACF,MAAK,OAAO,KAAK,cAAc,QAAQ,IAAI,KAAK,QAAQ,GAAG,KAAK,IAAI,GAAG;;CAI3E,QAAQ,QAAgB,SAAwB;AAC9C,OAAK,WAAW;EAChB,MAAM,MAAM,WAAW;AACvB,OAAK,OAAO,KAAK,cAAc,IAAI,IAAI,KAAK,QAAQ,GAAG,KAAK,IAAI,GAAG;;;AAyTvE,MAAa,SAAS,MA7ShB,OAAO;CACX,OAAe;CACf,aAAwC;CACxC,aAAwC;CACxC;CACA;CACA,QAAgB;CAChB,gBAAuC;CAGvC,iBAAqE,EAAE;CAGvE;CAEA,cAAsB;EAEpB,MAAM,UACJ,QAAQ,IAAI,iBAAiB,WAC7B,aAAa;EACf,MAAM,UAAU,QAAQ,IAAI;EAC5B,MAAM,WAAW,QAAQ,IAAI,gBAAgB;AAE7C,MAAI,WAAW,aAAa,WAAW,QAAQ;AAC7C,WAAQ,MAAM,qBAAqB;AACnC,WAAQ,KAAK,EAAE;;AAEjB,MACE,aAAa,WACb,aAAa,UACb,aAAa,UACb,aAAa,SACb;AACA,WAAQ,MAAM,oBAAoB;AAClC,WAAQ,KAAK,EAAE;;AAGjB,OAAK,YAAY;AACjB,OAAK,WAAW;AAIhB,MAAI,WAAW,QAAQ;AACrB,QAAK,aAAa,KAAK,iBAAiB,QAAQ,OAAO,IAAI,SAAS;AACpE,QAAK,eAAe,SAAS,KAAK;;AAIpC,MAAI,QACF,MAAK,aAAa,KAAK,iBAAiB,SAAS,SAAS;;CAI9D,iBAAyB,MAAuB,OAA2B;AACzE,SAAO,KACL;GACE;GACA,cAAc,EACZ,OAAO,YAAY,EACpB;GACF,EACD,YAAY,KAAK,CAClB;;CAGH,OAAO,cAAsB;AAC3B,MAAI,CAAC,OAAO,SACV,QAAO,WAAW,IAAI,QAAQ;AAEhC,SAAO,OAAO;;;;;;;;;CAUhB,iBAAiB,QAA6B;AAC5C,MAAI,WAAW,KAAK,cAAe;AACnC,OAAK,gBAAgB;AACrB,OAAK,cACH,WAAW,WAAW,EAAE,QAAQ,QAAQ,QAAQ,GAAG,KAAA;AACrD,MAAI,KAAK,YAAY;AACnB,QAAK,WAAW,OAAO;GACvB,MAAM,OACJ,KAAK,eAAe,WACpB,KAAK,iBAAiB,QAAQ,QAAQ,IAAI,KAAK,WAAW,MAAM;AAClE,QAAK,QAAQ,KAAK,WAAW;AAC7B,QAAK,eAAe,UAAU;AAC9B,QAAK,aAAa;;;;;;;;;;;CAYtB,SAAS,OAAsB;AAC7B,OAAK,QAAQ;AACb,MAAI,KAAK,WACP,MAAK,WAAW,QAAQ,QACpB,eAAe,KAAK,YAAY,eAAe,qBAC7C,KAAK,WACL,oBACF,KAAK;;CAIb,UAAmB;AACjB,SAAO,KAAK;;CAId,MAAM,SAAuB;AAC3B,MAAI,CAAC,KAAK,MACR,KAAI,KAAK,cAAc,WAAW;AAChC,uBAAoB;AAEpB,OAAS,QAAQ,SAAS;IACxB,QAAQ,MAAM,IAAI,IAAI;IACtB,GAAG,KAAK;IACT,CAAC;QAEF,MAAK,YAAY,MAAM,QAAQ;AAGnC,OAAK,YAAY,MAAM,QAAQ;;CAGjC,MAAM,SAAuB;AAC3B,MAAI,CAAC,KAAK,MACR,KAAI,KAAK,cAAc,WAAW;AAChC,uBAAoB;AAEpB,OAAS,QAAQ,SAAS;IACxB,QAAQ,MAAM,IAAI,IAAI;IACtB,GAAG,KAAK;IACT,CAAC;QAEF,MAAK,YAAY,MAAM,QAAQ;AAGnC,OAAK,YAAY,MAAM,QAAQ;;CAGjC,KAAK,SAAuB;AAC1B,MAAI,CAAC,KAAK,MACR,KAAI,KAAK,cAAc,WAAW;AAChC,uBAAoB;AACpB,OAAS,KAAK,SAAS,KAAK,YAAY;QAExC,MAAK,YAAY,KAAK,QAAQ;AAGlC,OAAK,YAAY,KAAK,QAAQ;;CAGhC,KAAK,SAAuB;AAC1B,MAAI,KAAK,cAAc,WAAW;AAChC,uBAAoB;AACpB,OAAS,KAAK,SAAS,KAAK,YAAY;QAExC,MAAK,YAAY,KAAK,QAAQ;AAEhC,OAAK,YAAY,KAAK,QAAQ;;CAGhC,MAAM,SAAuB;AAC3B,MAAI,KAAK,cAAc,WAAW;AAChC,uBAAoB;AACpB,OAAS,MAAM,SAAS,KAAK,YAAY;QAEzC,MAAK,YAAY,MAAM,QAAQ;AAEjC,OAAK,YAAY,MAAM,QAAQ;;CAGjC,MAAM,SAAuB;AAC3B,MAAI,KAAK,cAAc,WAAW;AAChC,uBAAoB;AAEpB,OAAS,MAAM,SAAS,KAAK,YAAY;QAEzC,MAAK,YAAY,MAAM,QAAQ;AAEjC,OAAK,YAAY,MAAM,QAAQ;;CAGjC,OAAO,SAAuB;AAE5B,OAAK,YAAY,OAAO,QAAQ;;CAIlC,QAAQ,SAAuB;AAC7B,MAAI,CAAC,KAAK,MACR,KAAI,KAAK,cAAc,WAAW;AAChC,uBAAoB;AACpB,OAAS,QAAQ,SAAS,KAAK,YAAY;QAE3C,MAAK,YAAY,KAAK,QAAQ;AAGlC,OAAK,YAAY,KAAK,QAAQ;;CAGhC,KAAK,SAAuB;AAC1B,MAAI,CAAC,KAAK,MACR,KAAI,KAAK,cAAc,WAAW;AAChC,uBAAoB;AACpB,OAAS,KAAK,SAAS,KAAK,YAAY;QAExC,MAAK,YAAY,KAAK,QAAQ;AAGlC,OAAK,YAAY,KAAK,QAAQ;;CAGhC,QAAQ,SAAiB,QAAuB;AAC9C,MAAI,CAAC,KAAK,MACR,KAAI,KAAK,cAAc,WAAW;AAChC,uBAAoB;AACpB,OAAS,QACP,SACA,SAAS;IAAE;IAAQ,GAAG,KAAK;IAAa,GAAG,KAAK,YACjD;QAED,MAAK,YAAY,KAAK,QAAQ;AAGlC,OAAK,YAAY,KAAK,QAAQ;;CAIhC,cAAc,YAA8B,SAAwB;AAGlE,MAAI,KAAK,MACP,QAAO,IAAI,YAAY,KAAK;AAE9B,MAAI,KAAK,cAAc,UACrB,QAAO,yBACL,QAAQ;GAAE;GAAW,GAAG,KAAK;GAAa,CAAC,CAC5C;MAED,QAAO,IAAI,YAAY,KAAK;;CAKhC,kBAAkB,OAA+B;AAC/C,MAAI,KAAK,MACP,QAAO,IAAI,aAAa,OAAO,KAAK;AAEtC,MAAI,KAAK,cAAc,UACrB,QAAO,yBACL,SAAS;GAAE,KAAK;GAAO,GAAG,KAAK;GAAa,CAAC,CAC9C;MAED,QAAO,IAAI,aAAa,OAAO,KAAK;;CAKxC,aAAa,SAAuB;AAClC,MAAI,CAAC,KAAK,MACR,KAAI,KAAK,cAAc,WAAW;AAChC,uBAAoB;AACpB,SAAM,MAAM,KAAK,QAAQ,EAAE,KAAK,YAAY;QAE5C,MAAK,KAAK,MAAM,UAAU;AAG9B,OAAK,YAAY,KAAK,WAAW,UAAU;;CAG7C,WAAW,SAAuB;AAChC,MAAI,CAAC,KAAK,MACR,KAAI,KAAK,cAAc,WAAW;AAChC,uBAAoB;AACpB,SAAM,MAAM,KAAK,QAAQ,EAAE,KAAK,YAAY;QAE5C,MAAK,KAAK,MAAM,UAAU;AAG9B,OAAK,YAAY,KAAK,SAAS,UAAU;;CAI3C,QAAc;AACZ,OAAK,YAAY,OAAO;AACxB,OAAK,YAAY,OAAO;;EAIC,aAAa"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FileToUpload } from 'generaltranslation/types';
|
|
1
|
+
import type { CustomMapping, FileToUpload } from 'generaltranslation/types';
|
|
2
2
|
import { type InlineLibrary } from '../types/libraries.js';
|
|
3
3
|
/**
|
|
4
4
|
* Strip ANSI escape codes from a string (e.g., chalk color codes)
|
|
@@ -17,14 +17,16 @@ export declare function promptText({ message, defaultValue, validate, }: {
|
|
|
17
17
|
defaultValue?: string;
|
|
18
18
|
validate?: (value: string) => boolean | string;
|
|
19
19
|
}): Promise<string>;
|
|
20
|
-
export declare function promptLocale({ message, defaultValue, }: {
|
|
20
|
+
export declare function promptLocale({ message, defaultValue, customMapping, }: {
|
|
21
21
|
message: string;
|
|
22
22
|
defaultValue?: string;
|
|
23
|
+
customMapping?: CustomMapping;
|
|
23
24
|
}): Promise<string>;
|
|
24
|
-
export declare function promptLocaleList({ message, defaultValue, required, }: {
|
|
25
|
+
export declare function promptLocaleList({ message, defaultValue, required, customMapping, }: {
|
|
25
26
|
message: string;
|
|
26
27
|
defaultValue?: string[];
|
|
27
28
|
required?: boolean;
|
|
29
|
+
customMapping?: CustomMapping;
|
|
28
30
|
}): Promise<string[]>;
|
|
29
31
|
export declare function promptGlobPatterns({ label, message, defaultValue, }: {
|
|
30
32
|
label: string;
|