gt 2.21.5 → 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 +32 -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 +4 -1
- 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/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":"api.js","names":[],"sources":["../../../src/cli/commands/api.ts"],"sourcesContent":["import fs from 'node:fs';\nimport {\n createApiClient,\n type ApiClientConfig,\n type Client,\n} from 'generaltranslation/api';\nimport openApiSpec from 'generaltranslation/api/openapi.json' with { type: 'json' };\nimport {\n createDiagnosticMessage,\n defaultBaseUrl,\n formatDiagnosticErrorDetails,\n} from 'generaltranslation/internal';\nimport { resolveConfig } from '../../config/resolveConfig.js';\nimport { exitSync } from '../../console/logging.js';\nimport { loadConfig } from '../../fs/config/loadConfig.js';\nimport { resolveProjectId } from '../../fs/utils.js';\nimport type { SharedFlags } from '../../types/index.js';\n\nexport type ApiCommandOptions = SharedFlags & {\n header?: string[];\n include?: boolean;\n input?: string;\n method: string;\n spec?: boolean;\n};\n\ntype ApiCommandDependencies = {\n exit?: (code: number) => never;\n fetch?: ApiClientConfig['fetch'];\n writeStderr?: (output: string) => void;\n writeStdout?: (output: string | Uint8Array) => void;\n};\n\ntype ApiRequestOptions = Parameters<Client['request']>[0];\n\nconst STANDARD_HTTP_METHODS = new Set([\n 'GET',\n 'HEAD',\n 'POST',\n 'PUT',\n 'PATCH',\n 'DELETE',\n 'OPTIONS',\n]);\n\nfunction fail(\n diagnostic: string,\n {\n exit = exitSync,\n writeStderr = (output) => process.stderr.write(output),\n }: ApiCommandDependencies\n): never {\n writeStderr(`${diagnostic}\\n`);\n return exit(1);\n}\n\nfunction parseMethod(\n value: string,\n dependencies: ApiCommandDependencies\n): ApiRequestOptions['method'] {\n const method = value.toUpperCase();\n if (!STANDARD_HTTP_METHODS.has(method)) {\n fail(\n createDiagnosticMessage({\n source: 'gt',\n severity: 'Error',\n whatHappened: 'The API request method is invalid',\n details: value,\n fix: `Use one of ${[...STANDARD_HTTP_METHODS].join(', ')}`,\n }),\n dependencies\n );\n }\n // The set validation narrows Commander input to the generated HTTP method union.\n return method as ApiRequestOptions['method'];\n}\n\nfunction parseHeaders(\n values: string[],\n dependencies: ApiCommandDependencies\n): Headers {\n const headers = new Headers();\n for (const header of values) {\n const separator = header.indexOf(':');\n if (separator < 1) {\n fail(\n createDiagnosticMessage({\n source: 'gt',\n severity: 'Error',\n whatHappened: 'The API request header is invalid',\n details: header,\n fix: 'Pass headers as `--header \"Key: Value\"`',\n }),\n dependencies\n );\n }\n headers.append(\n header.slice(0, separator).trim(),\n header.slice(separator + 1).trim()\n );\n }\n return headers;\n}\n\nfunction readInput(\n input: string,\n dependencies: ApiCommandDependencies\n): string {\n try {\n return fs.readFileSync(input === '-' ? 0 : input, 'utf8');\n } catch (error) {\n return fail(\n createDiagnosticMessage({\n source: 'gt',\n severity: 'Error',\n whatHappened: 'The API request body could not be read',\n fix:\n input === '-'\n ? 'Pipe a request body to standard input or remove `--input -`'\n : 'Check the `--input` file path and permissions',\n details: formatDiagnosticErrorDetails(error),\n }),\n dependencies\n );\n }\n}\n\nfunction writeResponseMetadata(\n response: Response,\n writeStdout: (output: string | Uint8Array) => void\n): void {\n writeStdout(\n `HTTP ${response.status}${response.statusText ? ` ${response.statusText}` : ''}\\n`\n );\n response.headers.forEach((value, name) => {\n writeStdout(`${name}: ${value}\\n`);\n });\n writeStdout('\\n');\n}\n\nfunction resolveApiProjectId(\n config: Record<string, unknown>,\n flagProjectId: string | undefined,\n dependencies: ApiCommandDependencies\n): string | undefined {\n const configProjectId =\n typeof config.projectId === 'string' ? config.projectId : undefined;\n const environmentProjectId = resolveProjectId();\n\n if (configProjectId && flagProjectId && configProjectId !== flagProjectId) {\n fail(\n createDiagnosticMessage({\n source: 'gt',\n severity: 'Error',\n whatHappened: 'The project IDs do not match',\n details: [\n `Configuration: ${configProjectId}`,\n `--project-id: ${flagProjectId}`,\n ],\n fix: 'Use the same project ID in all configurations',\n }),\n dependencies\n );\n }\n\n if (\n configProjectId &&\n environmentProjectId &&\n configProjectId !== environmentProjectId\n ) {\n fail(\n createDiagnosticMessage({\n source: 'gt',\n severity: 'Error',\n whatHappened: 'The project IDs do not match',\n details: [\n `Configuration: ${configProjectId}`,\n `Environment: ${environmentProjectId}`,\n ],\n fix: 'Use the same project ID in all configurations',\n }),\n dependencies\n );\n }\n\n return flagProjectId ?? configProjectId ?? environmentProjectId;\n}\n\nexport async function handleApiCommand(\n endpoint: string | undefined,\n options: ApiCommandOptions,\n dependencies: ApiCommandDependencies = {}\n): Promise<void> {\n if (!dependencies.writeStdout) {\n process.stdout.once('error', (error: NodeJS.ErrnoException) => {\n if (error.code === 'EPIPE') process.exit(0);\n throw error;\n });\n }\n const writeStdout =\n dependencies.writeStdout ?? ((output) => process.stdout.write(output));\n const writeStderr =\n dependencies.writeStderr ?? ((output) => process.stderr.write(output));\n\n if (options.spec) {\n writeStdout(`${JSON.stringify(openApiSpec, null, 2)}\\n`);\n return;\n }\n\n if (!endpoint) {\n fail(\n createDiagnosticMessage({\n source: 'gt',\n severity: 'Error',\n whatHappened: 'No API endpoint was provided',\n fix: 'Pass an endpoint or use `gt api --spec` to inspect the OpenAPI specification',\n }),\n dependencies\n );\n }\n\n const method = parseMethod(options.method, dependencies);\n const configPath = options.config?.endsWith('.json')\n ? options.config\n : options.config\n ? `${options.config}.json`\n : undefined;\n const config = configPath\n ? loadConfig(configPath)\n : (resolveConfig(process.cwd())?.config ?? {});\n const client = createApiClient({\n apiKey: options.apiKey ?? process.env.GT_API_KEY,\n baseUrl:\n typeof config.baseUrl === 'string' ? config.baseUrl : defaultBaseUrl,\n fetch: dependencies.fetch,\n projectId: resolveApiProjectId(config, options.projectId, dependencies),\n retryPolicy: 'none',\n });\n const normalizedEndpoint = endpoint.startsWith('/')\n ? endpoint\n : `/${endpoint}`;\n const headers = parseHeaders(options.header ?? [], dependencies);\n const body = options.input\n ? readInput(options.input, dependencies)\n : undefined;\n let rawResponse: Response | undefined;\n\n client.interceptors.response.use((response) => {\n // Keep a clone because the generated client consumes non-2xx bodies.\n rawResponse = response.clone();\n return response;\n });\n\n const result = await client\n .request({\n body,\n bodySerializer: () => body,\n headers,\n method,\n parseAs: 'stream',\n throwOnError: false,\n url: normalizedEndpoint,\n })\n .catch((error) =>\n fail(\n createDiagnosticMessage({\n source: 'gt',\n severity: 'Error',\n whatHappened: 'The API request failed before a response was received',\n details: formatDiagnosticErrorDetails(error),\n }),\n dependencies\n )\n );\n\n if (!rawResponse) {\n fail(\n createDiagnosticMessage({\n source: 'gt',\n severity: 'Error',\n whatHappened: 'The API request did not return a response',\n details: formatDiagnosticErrorDetails(result?.error),\n }),\n dependencies\n );\n }\n\n if (options.include) writeResponseMetadata(rawResponse, writeStdout);\n writeStdout(Buffer.from(await rawResponse.arrayBuffer()));\n\n if (!rawResponse.ok) {\n writeStderr(\n `${method} ${normalizedEndpoint} returned HTTP ${rawResponse.status}${rawResponse.statusText ? ` ${rawResponse.statusText}` : ''}\\n`\n );\n (dependencies.exit ?? exitSync)(1);\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"api.js","names":[],"sources":["../../../src/cli/commands/api.ts"],"sourcesContent":["import fs from 'node:fs';\nimport {\n createApiClient,\n type ApiClientConfig,\n type Client,\n} from 'generaltranslation/api';\nimport openApiSpec from 'generaltranslation/api/openapi.json' with { type: 'json' };\nimport {\n createDiagnosticMessage,\n formatDiagnosticErrorDetails,\n} from 'generaltranslation/diagnostics';\nimport { defaultBaseUrl } from 'generaltranslation/internal';\nimport { createUserTokenProvider } from '../../auth/oauth.js';\nimport { resolveConfig } from '../../config/resolveConfig.js';\nimport { exitSync } from '../../console/logging.js';\nimport { loadConfig } from '../../fs/config/loadConfig.js';\nimport { resolveProjectId } from '../../fs/utils.js';\nimport type { SharedFlags } from '../../types/index.js';\n\nexport type ApiCommandOptions = SharedFlags & {\n header?: string[];\n include?: boolean;\n input?: string;\n method: string;\n spec?: boolean;\n};\n\ntype ApiCommandDependencies = {\n exit?: (code: number) => never;\n fetch?: ApiClientConfig['fetch'];\n writeStderr?: (output: string) => void;\n writeStdout?: (output: string | Uint8Array) => void;\n};\n\ntype ApiRequestOptions = Parameters<Client['request']>[0];\n\nconst STANDARD_HTTP_METHODS = new Set([\n 'GET',\n 'HEAD',\n 'POST',\n 'PUT',\n 'PATCH',\n 'DELETE',\n 'OPTIONS',\n]);\n\nfunction fail(\n diagnostic: string,\n {\n exit = exitSync,\n writeStderr = (output) => process.stderr.write(output),\n }: ApiCommandDependencies\n): never {\n writeStderr(`${diagnostic}\\n`);\n return exit(1);\n}\n\nfunction parseMethod(\n value: string,\n dependencies: ApiCommandDependencies\n): ApiRequestOptions['method'] {\n const method = value.toUpperCase();\n if (!STANDARD_HTTP_METHODS.has(method)) {\n fail(\n createDiagnosticMessage({\n source: 'gt',\n severity: 'Error',\n whatHappened: 'The API request method is invalid',\n details: value,\n fix: `Use one of ${[...STANDARD_HTTP_METHODS].join(', ')}`,\n }),\n dependencies\n );\n }\n // The set validation narrows Commander input to the generated HTTP method union.\n return method as ApiRequestOptions['method'];\n}\n\nfunction parseHeaders(\n values: string[],\n dependencies: ApiCommandDependencies\n): Headers {\n const headers = new Headers();\n for (const header of values) {\n const separator = header.indexOf(':');\n if (separator < 1) {\n fail(\n createDiagnosticMessage({\n source: 'gt',\n severity: 'Error',\n whatHappened: 'The API request header is invalid',\n details: header,\n fix: 'Pass headers as `--header \"Key: Value\"`',\n }),\n dependencies\n );\n }\n headers.append(\n header.slice(0, separator).trim(),\n header.slice(separator + 1).trim()\n );\n }\n return headers;\n}\n\nfunction readInput(\n input: string,\n dependencies: ApiCommandDependencies\n): string {\n try {\n return fs.readFileSync(input === '-' ? 0 : input, 'utf8');\n } catch (error) {\n return fail(\n createDiagnosticMessage({\n source: 'gt',\n severity: 'Error',\n whatHappened: 'The API request body could not be read',\n fix:\n input === '-'\n ? 'Pipe a request body to standard input or remove `--input -`'\n : 'Check the `--input` file path and permissions',\n details: formatDiagnosticErrorDetails(error),\n }),\n dependencies\n );\n }\n}\n\nfunction writeResponseMetadata(\n response: Response,\n writeStdout: (output: string | Uint8Array) => void\n): void {\n writeStdout(\n `HTTP ${response.status}${response.statusText ? ` ${response.statusText}` : ''}\\n`\n );\n response.headers.forEach((value, name) => {\n writeStdout(`${name}: ${value}\\n`);\n });\n writeStdout('\\n');\n}\n\nfunction resolveApiProjectId(\n config: Record<string, unknown>,\n flagProjectId: string | undefined,\n dependencies: ApiCommandDependencies\n): string | undefined {\n const configProjectId =\n typeof config.projectId === 'string' ? config.projectId : undefined;\n const environmentProjectId = resolveProjectId();\n\n if (configProjectId && flagProjectId && configProjectId !== flagProjectId) {\n fail(\n createDiagnosticMessage({\n source: 'gt',\n severity: 'Error',\n whatHappened: 'The project IDs do not match',\n details: [\n `Configuration: ${configProjectId}`,\n `--project-id: ${flagProjectId}`,\n ],\n fix: 'Use the same project ID in all configurations',\n }),\n dependencies\n );\n }\n\n if (\n configProjectId &&\n environmentProjectId &&\n configProjectId !== environmentProjectId\n ) {\n fail(\n createDiagnosticMessage({\n source: 'gt',\n severity: 'Error',\n whatHappened: 'The project IDs do not match',\n details: [\n `Configuration: ${configProjectId}`,\n `Environment: ${environmentProjectId}`,\n ],\n fix: 'Use the same project ID in all configurations',\n }),\n dependencies\n );\n }\n\n return flagProjectId ?? configProjectId ?? environmentProjectId;\n}\n\nexport async function handleApiCommand(\n endpoint: string | undefined,\n options: ApiCommandOptions,\n dependencies: ApiCommandDependencies = {}\n): Promise<void> {\n if (!dependencies.writeStdout) {\n process.stdout.once('error', (error: NodeJS.ErrnoException) => {\n if (error.code === 'EPIPE') process.exit(0);\n throw error;\n });\n }\n const writeStdout =\n dependencies.writeStdout ?? ((output) => process.stdout.write(output));\n const writeStderr =\n dependencies.writeStderr ?? ((output) => process.stderr.write(output));\n\n if (options.spec) {\n writeStdout(`${JSON.stringify(openApiSpec, null, 2)}\\n`);\n return;\n }\n\n if (!endpoint) {\n fail(\n createDiagnosticMessage({\n source: 'gt',\n severity: 'Error',\n whatHappened: 'No API endpoint was provided',\n fix: 'Pass an endpoint or use `gt api --spec` to inspect the OpenAPI specification',\n }),\n dependencies\n );\n }\n\n const method = parseMethod(options.method, dependencies);\n const configPath = options.config?.endsWith('.json')\n ? options.config\n : options.config\n ? `${options.config}.json`\n : undefined;\n const config = configPath\n ? loadConfig(configPath)\n : (resolveConfig(process.cwd())?.config ?? {});\n const baseUrl =\n typeof config.baseUrl === 'string' ? config.baseUrl : defaultBaseUrl;\n const client = createApiClient({\n apiKey: options.apiKey ?? process.env.GT_API_KEY,\n userTokenProvider: createUserTokenProvider({ baseUrl }),\n baseUrl,\n fetch: dependencies.fetch,\n projectId: resolveApiProjectId(config, options.projectId, dependencies),\n retryPolicy: 'none',\n });\n const normalizedEndpoint = endpoint.startsWith('/')\n ? endpoint\n : `/${endpoint}`;\n const headers = parseHeaders(options.header ?? [], dependencies);\n const body = options.input\n ? readInput(options.input, dependencies)\n : undefined;\n let rawResponse: Response | undefined;\n\n client.interceptors.response.use((response) => {\n // Keep a clone because the generated client consumes non-2xx bodies.\n rawResponse = response.clone();\n return response;\n });\n\n const result = await client\n .request({\n body,\n bodySerializer: () => body,\n headers,\n method,\n parseAs: 'stream',\n throwOnError: false,\n url: normalizedEndpoint,\n })\n .catch((error) =>\n fail(\n createDiagnosticMessage({\n source: 'gt',\n severity: 'Error',\n whatHappened: 'The API request failed before a response was received',\n details: formatDiagnosticErrorDetails(error),\n }),\n dependencies\n )\n );\n\n if (!rawResponse) {\n fail(\n createDiagnosticMessage({\n source: 'gt',\n severity: 'Error',\n whatHappened: 'The API request did not return a response',\n details: formatDiagnosticErrorDetails(result?.error),\n }),\n dependencies\n );\n }\n\n if (options.include) writeResponseMetadata(rawResponse, writeStdout);\n writeStdout(Buffer.from(await rawResponse.arrayBuffer()));\n\n if (!rawResponse.ok) {\n writeStderr(\n `${method} ${normalizedEndpoint} returned HTTP ${rawResponse.status}${rawResponse.statusText ? ` ${rawResponse.statusText}` : ''}\\n`\n );\n (dependencies.exit ?? exitSync)(1);\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { logger } from "../../console/logger.js";
|
|
2
|
-
import { gt } from "../../utils/gt.js";
|
|
3
2
|
import { exitSync, logErrorAndExit } from "../../console/logging.js";
|
|
4
3
|
import { getRelative, readFile } from "../../fs/findFilepath.js";
|
|
5
4
|
import { fileEncodingSkipReason, noDefaultLocaleError } from "../../console/index.js";
|
|
5
|
+
import { api } from "../../utils/api.js";
|
|
6
6
|
import { readFileContent } from "../../fs/fileContent.js";
|
|
7
7
|
import { validateJsonSchema } from "../../formats/json/utils.js";
|
|
8
8
|
import { extractJson } from "../../formats/json/extractJson.js";
|
|
@@ -55,7 +55,7 @@ async function upload(settings) {
|
|
|
55
55
|
const compositeInfo = compositeJsonFiles.get(file.fileName);
|
|
56
56
|
const xcstringsCatalog = xcstringsCatalogs.get(file.fileName);
|
|
57
57
|
for (const locale of locales) if (xcstringsCatalog) {
|
|
58
|
-
const slice = sliceTranslationCatalog(xcstringsCatalog,
|
|
58
|
+
const slice = sliceTranslationCatalog(xcstringsCatalog, api.resolveCanonicalLocale(locale));
|
|
59
59
|
if (!slice) continue;
|
|
60
60
|
translations.push({
|
|
61
61
|
content: serializeXcstringsSlice(slice),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"upload.js","names":[],"sources":["../../../src/cli/commands/upload.ts"],"sourcesContent":["import {\n fileEncodingSkipReason,\n noDefaultLocaleError,\n} from '../../console/index.js';\nimport { exitSync, logErrorAndExit } from '../../console/logging.js';\nimport { logger } from '../../console/logger.js';\nimport { getRelative, readFile } from '../../fs/findFilepath.js';\nimport { readFileContent } from '../../fs/fileContent.js';\nimport { Settings } from '../../types/index.js';\nimport { UploadOptions } from '../base.js';\nimport { extractJson } from '../../formats/json/extractJson.js';\nimport { validateJsonSchema } from '../../formats/json/utils.js';\nimport { runUploadFilesWorkflow } from '../../workflows/upload.js';\nimport { existsSync } from 'node:fs';\nimport { createFileMapping } from '../../formats/files/fileMapping.js';\nimport type { FileToUpload } from 'generaltranslation/types';\nimport {\n hasValidCredentials,\n hasValidServiceLocales,\n} from './utils/validation.js';\nimport { runPublishWorkflow } from '../../workflows/publish.js';\nimport { aggregateFiles } from '../../formats/files/aggregateFiles.js';\nimport { recordWarning } from '../../state/translateWarnings.js';\nimport {\n parseXcstringsCatalog,\n serializeXcstringsSlice,\n sliceTranslationCatalog,\n type XcstringsCatalog,\n} from '../../formats/xcstrings/parseXcstrings.js';\nimport {
|
|
1
|
+
{"version":3,"file":"upload.js","names":[],"sources":["../../../src/cli/commands/upload.ts"],"sourcesContent":["import {\n fileEncodingSkipReason,\n noDefaultLocaleError,\n} from '../../console/index.js';\nimport { exitSync, logErrorAndExit } from '../../console/logging.js';\nimport { logger } from '../../console/logger.js';\nimport { getRelative, readFile } from '../../fs/findFilepath.js';\nimport { readFileContent } from '../../fs/fileContent.js';\nimport { Settings } from '../../types/index.js';\nimport { UploadOptions } from '../base.js';\nimport { extractJson } from '../../formats/json/extractJson.js';\nimport { validateJsonSchema } from '../../formats/json/utils.js';\nimport { runUploadFilesWorkflow } from '../../workflows/upload.js';\nimport { existsSync } from 'node:fs';\nimport { createFileMapping } from '../../formats/files/fileMapping.js';\nimport type { FileToUpload } from 'generaltranslation/types';\nimport {\n hasValidCredentials,\n hasValidServiceLocales,\n} from './utils/validation.js';\nimport { runPublishWorkflow } from '../../workflows/publish.js';\nimport { aggregateFiles } from '../../formats/files/aggregateFiles.js';\nimport { recordWarning } from '../../state/translateWarnings.js';\nimport {\n parseXcstringsCatalog,\n serializeXcstringsSlice,\n sliceTranslationCatalog,\n type XcstringsCatalog,\n} from '../../formats/xcstrings/parseXcstrings.js';\nimport { api } from '../../utils/api.js';\n\n/**\n * Sends multiple files to the API for translation\n * @param settings - Translation options including API settings\n * @returns Promise that resolves when translation is complete\n */\nexport async function upload(\n settings: Settings & UploadOptions\n): Promise<void> {\n if (!settings.files) {\n return;\n }\n\n const additionalOptions = settings.options || {};\n const {\n resolvedPaths: filePaths,\n placeholderPaths,\n transformPaths,\n transformFormats,\n } = settings.files;\n\n // Reuse the same source aggregation path as translate/stage so source\n // parsing behavior stays consistent across commands.\n const { files: allFiles, publishMap } = await aggregateFiles(settings);\n const sourceFileNames = new Set(allFiles.map((file) => file.fileName));\n const compositeJsonFiles = new Map<\n string,\n { filePath: string; content: string }\n >();\n\n if (filePaths.json) {\n for (const filePath of filePaths.json) {\n const relativePath = getRelative(filePath);\n if (!sourceFileNames.has(relativePath)) continue;\n\n const jsonSchema = validateJsonSchema(additionalOptions, filePath);\n if (jsonSchema?.composite) {\n compositeJsonFiles.set(relativePath, {\n filePath,\n content: readFile(filePath),\n });\n }\n }\n }\n\n // An .xcstrings catalog carries its own translations, so each locale's\n // upload is a slice of the same file rather than a separate translation\n // file. Catalogs aggregateFiles could not parse are already reported.\n const xcstringsCatalogs = new Map<string, XcstringsCatalog>();\n if (filePaths.xcstrings) {\n for (const filePath of filePaths.xcstrings) {\n const relativePath = getRelative(filePath);\n if (!sourceFileNames.has(relativePath)) continue;\n xcstringsCatalogs.set(\n relativePath,\n parseXcstringsCatalog(readFile(filePath))\n );\n }\n }\n\n if (allFiles.length === 0) {\n logger.error(\n 'No files to upload were found. Check your configuration and try again.'\n );\n return;\n }\n\n if (!settings.defaultLocale) {\n return logErrorAndExit(noDefaultLocaleError);\n }\n if (!hasValidCredentials(settings) || !hasValidServiceLocales(settings))\n return exitSync(1);\n\n const locales = settings.locales || [];\n // Create file mapping for all file types\n const fileMapping = createFileMapping(\n filePaths,\n placeholderPaths,\n transformPaths,\n transformFormats,\n locales,\n settings.defaultLocale\n );\n\n // construct object\n const uploadData = allFiles.map((file) => {\n const sourceFile: FileToUpload = { ...file };\n\n const translations: FileToUpload[] = [];\n const compositeInfo = compositeJsonFiles.get(file.fileName);\n const xcstringsCatalog = xcstringsCatalogs.get(file.fileName);\n\n for (const locale of locales) {\n if (xcstringsCatalog) {\n // Catalog keys are canonical tags; the configured locale may be an alias.\n const slice = sliceTranslationCatalog(\n xcstringsCatalog,\n api.resolveCanonicalLocale(locale)\n );\n // A locale the catalog does not carry has nothing to upload\n if (!slice) continue;\n translations.push({\n content: serializeXcstringsSlice(slice),\n fileName: file.fileName,\n fileFormat: file.transformFormat ?? file.fileFormat,\n dataFormat: file.dataFormat,\n locale,\n fileId: file.fileId,\n versionId: file.versionId,\n });\n } else if (compositeInfo) {\n // Composite JSON: extract translations from the same source file\n const extracted = extractJson(\n compositeInfo.content,\n compositeInfo.filePath,\n additionalOptions,\n locale,\n settings.defaultLocale\n );\n if (extracted) {\n translations.push({\n content: extracted,\n fileName: file.fileName,\n fileFormat: file.transformFormat ?? file.fileFormat,\n dataFormat: file.dataFormat,\n locale,\n fileId: file.fileId,\n versionId: file.versionId,\n });\n }\n } else {\n // Non-composite: look for separate translation files\n const translatedFileName = fileMapping[locale]?.[file.fileName];\n if (translatedFileName && existsSync(translatedFileName)) {\n const translationFormat = file.transformFormat ?? file.fileFormat;\n let translatedContent: string;\n try {\n translatedContent = readFileContent(\n translatedFileName,\n translationFormat\n );\n } catch (error) {\n // One undecodable locale should not block the others: skip it and\n // report it in the summary.\n const relativePath = getRelative(translatedFileName);\n const reason = fileEncodingSkipReason(error);\n logger.warn(`Skipping ${relativePath}: ${reason}`);\n recordWarning('skipped_file', relativePath, reason);\n continue;\n }\n translations.push({\n content: translatedContent,\n fileName: translatedFileName,\n fileFormat: translationFormat,\n dataFormat: file.dataFormat,\n locale,\n fileId: file.fileId,\n versionId: file.versionId,\n });\n }\n }\n }\n return {\n source: sourceFile,\n translations,\n };\n });\n\n try {\n // Send all files in a single API call\n const { branchData } = await runUploadFilesWorkflow({\n files: uploadData,\n options: settings,\n });\n\n // Publish files to CDN if publish config exists\n await runPublishWorkflow(\n allFiles,\n publishMap,\n branchData.currentBranch.id,\n settings\n );\n } catch (error) {\n logErrorAndExit(`Error uploading files: ${error}`);\n }\n}\n"],"mappings":"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"}
|
|
@@ -10,12 +10,12 @@ export declare function hasValidLocales(settings: Settings, { forApi }?: {
|
|
|
10
10
|
/** API-backed commands require canonical codes or explicit aliases to them. */
|
|
11
11
|
export declare function hasValidServiceLocales(settings: Settings): boolean;
|
|
12
12
|
/**
|
|
13
|
-
* Validate
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Validate credentials
|
|
13
|
+
* Validate credentials. Authentication itself is not checked here: the API
|
|
14
|
+
* client uses the API key when set and otherwise the signed-in user, which
|
|
15
|
+
* reports `gt login` at the first request.
|
|
18
16
|
* @param settings - The settings to validate
|
|
19
|
-
* @returns True if
|
|
17
|
+
* @returns True if a project ID is configured
|
|
20
18
|
*/
|
|
21
|
-
export declare function hasValidCredentials(settings: Settings):
|
|
19
|
+
export declare function hasValidCredentials(settings: Settings): settings is Settings & {
|
|
20
|
+
projectId: string;
|
|
21
|
+
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { logger } from "../../../console/logger.js";
|
|
2
|
-
import {
|
|
3
|
-
import { createDiagnosticMessage } from "generaltranslation/
|
|
2
|
+
import { noDefaultLocaleError, noLocalesError, noProjectIdError } from "../../../console/index.js";
|
|
3
|
+
import { createDiagnosticMessage } from "generaltranslation/diagnostics";
|
|
4
4
|
import { resolveCanonicalLocale, standardizeLocale } from "@generaltranslation/format";
|
|
5
5
|
//#region src/cli/commands/utils/validation.ts
|
|
6
6
|
/**
|
|
@@ -39,26 +39,13 @@ function hasValidServiceLocales(settings) {
|
|
|
39
39
|
return true;
|
|
40
40
|
}
|
|
41
41
|
/**
|
|
42
|
-
* Validate
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
if (!settings.apiKey) {
|
|
46
|
-
logger.error(noApiKeyError);
|
|
47
|
-
return false;
|
|
48
|
-
}
|
|
49
|
-
if (settings.apiKey.startsWith("gtx-dev-")) {
|
|
50
|
-
logger.error(devApiKeyError);
|
|
51
|
-
return false;
|
|
52
|
-
}
|
|
53
|
-
return true;
|
|
54
|
-
}
|
|
55
|
-
/**
|
|
56
|
-
* Validate credentials
|
|
42
|
+
* Validate credentials. Authentication itself is not checked here: the API
|
|
43
|
+
* client uses the API key when set and otherwise the signed-in user, which
|
|
44
|
+
* reports `gt login` at the first request.
|
|
57
45
|
* @param settings - The settings to validate
|
|
58
|
-
* @returns True if
|
|
46
|
+
* @returns True if a project ID is configured
|
|
59
47
|
*/
|
|
60
48
|
function hasValidCredentials(settings) {
|
|
61
|
-
if (!hasValidApiKey(settings)) return false;
|
|
62
49
|
if (!settings.projectId) {
|
|
63
50
|
logger.error(noProjectIdError);
|
|
64
51
|
return false;
|
|
@@ -66,6 +53,6 @@ function hasValidCredentials(settings) {
|
|
|
66
53
|
return true;
|
|
67
54
|
}
|
|
68
55
|
//#endregion
|
|
69
|
-
export {
|
|
56
|
+
export { hasValidCredentials, hasValidLocales, hasValidServiceLocales };
|
|
70
57
|
|
|
71
58
|
//# sourceMappingURL=validation.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation.js","names":[],"sources":["../../../../src/cli/commands/utils/validation.ts"],"sourcesContent":["import {\n resolveCanonicalLocale,\n standardizeLocale,\n} from '@generaltranslation/format';\nimport { createDiagnosticMessage } from 'generaltranslation/
|
|
1
|
+
{"version":3,"file":"validation.js","names":[],"sources":["../../../../src/cli/commands/utils/validation.ts"],"sourcesContent":["import {\n resolveCanonicalLocale,\n standardizeLocale,\n} from '@generaltranslation/format';\nimport { createDiagnosticMessage } from 'generaltranslation/diagnostics';\nimport {\n noDefaultLocaleError,\n noLocalesError,\n noProjectIdError,\n} from '../../../console/index.js';\nimport { logger } from '../../../console/logger.js';\nimport { Settings } from '../../../types/index.js';\n\n/**\n * Validate locales\n * @param settings - The settings to validate\n * @returns True if has locales and default locale\n */\nexport function hasValidLocales(\n settings: Settings,\n { forApi = false }: { forApi?: boolean } = {}\n): boolean {\n if (!settings.locales) {\n logger.error(noLocalesError);\n return false;\n }\n if (!settings.defaultLocale) {\n logger.error(noDefaultLocaleError);\n return false;\n }\n return !forApi || hasValidServiceLocales(settings);\n}\n\n/** API-backed commands require canonical codes or explicit aliases to them. */\nexport function hasValidServiceLocales(settings: Settings): boolean {\n for (const locale of [settings.defaultLocale, ...(settings.locales ?? [])]) {\n if (!locale) continue;\n const code = resolveCanonicalLocale(locale, settings.customMapping);\n const canonicalCode = standardizeLocale(code);\n if (code !== canonicalCode) {\n logger.error(\n createDiagnosticMessage({\n source: 'gt',\n severity: 'Error',\n whatHappened: `Locale \"${locale}\" is not configured for GT API use`,\n why: 'GT API commands require canonical locale codes or an explicit mapping to one',\n fix: `Use \"${canonicalCode}\" or set customMapping[${JSON.stringify(locale)}].code to \"${canonicalCode}\" in gt.config.json`,\n })\n );\n return false;\n }\n }\n return true;\n}\n\n/**\n * Validate credentials. Authentication itself is not checked here: the API\n * client uses the API key when set and otherwise the signed-in user, which\n * reports `gt login` at the first request.\n * @param settings - The settings to validate\n * @returns True if a project ID is configured\n */\nexport function hasValidCredentials(\n settings: Settings\n): settings is Settings & { projectId: string } {\n if (!settings.projectId) {\n logger.error(noProjectIdError);\n return false;\n }\n return true;\n}\n"],"mappings":";;;;;;;;;;AAkBA,SAAgB,gBACd,UACA,EAAE,SAAS,UAAgC,EAAE,EACpC;AACT,KAAI,CAAC,SAAS,SAAS;AACrB,SAAO,MAAM,eAAe;AAC5B,SAAO;;AAET,KAAI,CAAC,SAAS,eAAe;AAC3B,SAAO,MAAM,qBAAqB;AAClC,SAAO;;AAET,QAAO,CAAC,UAAU,uBAAuB,SAAS;;;AAIpD,SAAgB,uBAAuB,UAA6B;AAClE,MAAK,MAAM,UAAU,CAAC,SAAS,eAAe,GAAI,SAAS,WAAW,EAAE,CAAE,EAAE;AAC1E,MAAI,CAAC,OAAQ;EACb,MAAM,OAAO,uBAAuB,QAAQ,SAAS,cAAc;EACnE,MAAM,gBAAgB,kBAAkB,KAAK;AAC7C,MAAI,SAAS,eAAe;AAC1B,UAAO,MACL,wBAAwB;IACtB,QAAQ;IACR,UAAU;IACV,cAAc,WAAW,OAAO;IAChC,KAAK;IACL,KAAK,QAAQ,cAAc,yBAAyB,KAAK,UAAU,OAAO,CAAC,aAAa,cAAc;IACvG,CAAC,CACH;AACD,UAAO;;;AAGX,QAAO;;;;;;;;;AAUT,SAAgB,oBACd,UAC8C;AAC9C,KAAI,CAAC,SAAS,WAAW;AACvB,SAAO,MAAM,iBAAiB;AAC9B,SAAO;;AAET,QAAO"}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { logger } from "../console/logger.js";
|
|
2
2
|
import "../utils/constants.js";
|
|
3
|
-
import { gt } from "../utils/gt.js";
|
|
4
3
|
import { displayProjectId, exitSync, logErrorAndExit, warnApiKeyInConfig, warnDeprecatedField } from "../console/logging.js";
|
|
5
4
|
import { loadConfig } from "../fs/config/loadConfig.js";
|
|
6
5
|
import { GT_PARSING_FLAGS_DEFAULT } from "./defaults.js";
|
|
@@ -8,6 +7,7 @@ import { normalizeFilesOptions } from "../formats/files/transformFormat.js";
|
|
|
8
7
|
import { resolveFiles } from "../fs/config/parseFilesConfig.js";
|
|
9
8
|
import { validateSettings } from "./validateSettings.js";
|
|
10
9
|
import { resolveProjectId } from "../fs/utils.js";
|
|
10
|
+
import { createUserTokenProvider } from "../auth/oauth.js";
|
|
11
11
|
import { resolveConfig } from "./resolveConfig.js";
|
|
12
12
|
import { configureApiClient } from "../utils/api.js";
|
|
13
13
|
import { generatePreset } from "./optionPresets.js";
|
|
@@ -81,9 +81,10 @@ async function generateSettings(flags, cwd = process.cwd(), options) {
|
|
|
81
81
|
mergedOptions.defaultLocale = mergedOptions.defaultLocale || libraryDefaultLocale;
|
|
82
82
|
mergedOptions.locales = Array.from(new Set([...gtConfig.locales || [], ...flags.locales || []]));
|
|
83
83
|
mergedOptions.locales = mergedOptions.locales.filter((locale) => locale !== mergedOptions.defaultLocale);
|
|
84
|
-
mergedOptions.apiKey = mergedOptions.apiKey || process.env.GT_API_KEY;
|
|
85
84
|
mergedOptions.projectId = mergedOptions.projectId || resolveProjectId();
|
|
86
85
|
mergedOptions.baseUrl = mergedOptions.baseUrl || defaultBaseUrl;
|
|
86
|
+
mergedOptions.apiKey = mergedOptions.apiKey || process.env.GT_API_KEY;
|
|
87
|
+
mergedOptions.userTokenProvider = createUserTokenProvider({ baseUrl: mergedOptions.baseUrl });
|
|
87
88
|
mergedOptions.dashboardUrl = mergedOptions.dashboardUrl || "https://dash.generaltranslation.com";
|
|
88
89
|
mergedOptions.locales = mergedOptions.locales || [];
|
|
89
90
|
if (!mergedOptions.config) mergedOptions.config = "";
|
|
@@ -166,16 +167,10 @@ async function generateSettings(flags, cwd = process.cwd(), options) {
|
|
|
166
167
|
configureApiClient({
|
|
167
168
|
projectId: mergedOptions.projectId,
|
|
168
169
|
apiKey: mergedOptions.apiKey,
|
|
170
|
+
userTokenProvider: mergedOptions.userTokenProvider,
|
|
169
171
|
baseUrl: mergedOptions.baseUrl,
|
|
170
172
|
customMapping: mergedOptions.customMapping
|
|
171
173
|
});
|
|
172
|
-
gt.setConfig({
|
|
173
|
-
projectId: mergedOptions.projectId,
|
|
174
|
-
apiKey: mergedOptions.apiKey,
|
|
175
|
-
baseUrl: mergedOptions.baseUrl,
|
|
176
|
-
sourceLocale: mergedOptions.defaultLocale,
|
|
177
|
-
customMapping: mergedOptions.customMapping
|
|
178
|
-
});
|
|
179
174
|
return mergedOptions;
|
|
180
175
|
}
|
|
181
176
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generateSettings.js","names":[],"sources":["../../src/config/generateSettings.ts"],"sourcesContent":["import {\n displayProjectId,\n exitSync,\n logErrorAndExit,\n warnApiKeyInConfig,\n warnDeprecatedField,\n} from '../console/logging.js';\nimport { loadConfig } from '../fs/config/loadConfig.js';\nimport { FilesOptions, Settings } from '../types/index.js';\nimport {\n defaultBaseUrl,\n libraryDefaultLocale,\n} from 'generaltranslation/internal';\nimport { resolveFiles } from '../fs/config/parseFilesConfig.js';\nimport { validateSettings } from './validateSettings.js';\nimport {\n DEFAULT_GIT_REMOTE_NAME,\n GT_DASHBOARD_URL,\n} from '../utils/constants.js';\nimport { resolveProjectId } from '../fs/utils.js';\nimport crypto from 'node:crypto';\nimport { execSync } from 'node:child_process';\nimport path from 'node:path';\nimport chalk from 'chalk';\nimport { resolveConfig } from './resolveConfig.js';\nimport { configureApiClient } from '../utils/api.js';\nimport { gt } from '../utils/gt.js';\nimport { generatePreset } from './optionPresets.js';\nimport { GT_PARSING_FLAGS_DEFAULT } from './defaults.js';\nimport { normalizeFilesOptions } from '../formats/files/transformFormat.js';\nimport { determineLibrary } from '../fs/determineFramework/index.js';\nimport { logger } from '../console/logger.js';\n\nexport const DEFAULT_SRC_PATTERNS = [\n 'src/**/*.{js,jsx,ts,tsx}',\n 'app/**/*.{js,jsx,ts,tsx}',\n 'pages/**/*.{js,jsx,ts,tsx}',\n 'components/**/*.{js,jsx,ts,tsx}',\n];\n\nexport const DEFAULT_PYTHON_SRC_PATTERNS = ['**/*.py'];\nexport const DEFAULT_PYTHON_SRC_EXCLUDES = [\n 'venv/**',\n '.venv/**',\n '__pycache__/**',\n '**/migrations/**',\n '**/tests/**',\n '**/test_*.py',\n '**/*_test.py',\n];\n\ntype GenerateSettingsInput = Partial<Omit<Settings, 'tag'>> & {\n config?: string;\n projectId?: string;\n locales?: string[];\n options?: Settings['options'];\n files?: unknown;\n publish?: boolean;\n omitConfigIds?: boolean;\n saveLocal?: boolean;\n tag?: string | boolean;\n message?: string;\n branch?: string;\n enableBranching?: boolean;\n disableBranchDetection?: boolean;\n remoteName?: string;\n experimentalLocalizeStaticImports?: boolean;\n experimentalLocalizeStaticUrls?: boolean;\n experimentalLocalizeRelativeAssets?: boolean;\n experimentalHideDefaultLocale?: boolean;\n experimentalFlattenJsonFiles?: boolean;\n experimentalClearLocaleDirs?: boolean;\n clearLocaleDirsExclude?: string[];\n [key: string]: unknown;\n};\n\nfunction hasConfiguredTranslationFiles(files: unknown): boolean {\n if (!files || typeof files !== 'object' || Array.isArray(files)) {\n return false;\n }\n return Object.keys(files).some((key) => key !== 'gt');\n}\n\n/**\n * Generates settings from any\n * @param flags - The CLI flags to generate settings from\n * @param cwd - The current working directory\n * @param options - Additional options\n * @param options.requireConfig - If true, exit with an error when no config file is found\n * @returns The generated settings\n */\nexport async function generateSettings(\n flags: GenerateSettingsInput,\n cwd: string = process.cwd(),\n options?: { requireConfig?: boolean }\n): Promise<Settings> {\n // Load config file\n let gtConfig: GenerateSettingsInput = {};\n\n if (flags.config && !flags.config.endsWith('.json')) {\n flags.config = `${flags.config}.json`;\n }\n if (flags.config) {\n gtConfig = loadConfig(flags.config);\n } else {\n const config = resolveConfig(cwd);\n if (config) {\n gtConfig = config.config as GenerateSettingsInput;\n flags.config = config.path;\n } else {\n if (options?.requireConfig) {\n return logErrorAndExit(\n 'No gt.config.json file was found. Run `npx gt init` to create one, pass --config, or run this command from your project root.'\n );\n }\n gtConfig = {};\n }\n }\n\n // Warn if apiKey is present in gt.config.json\n if (gtConfig.apiKey) {\n warnApiKeyInConfig(flags.config ?? 'gt.config.json');\n exitSync(1);\n }\n const projectIdEnv = resolveProjectId();\n // Resolve mismatched projectIds\n if (\n gtConfig.projectId &&\n flags.projectId &&\n gtConfig.projectId !== flags.projectId\n ) {\n logErrorAndExit(\n `Project ID mismatch: gt.config.json uses ${chalk.green(gtConfig.projectId)}, but the CLI flag uses ${chalk.green(flags.projectId)}. Use the same projectId in all configs.`\n );\n } else if (\n gtConfig.projectId &&\n projectIdEnv &&\n gtConfig.projectId !== projectIdEnv\n ) {\n logErrorAndExit(\n `Project ID mismatch: gt.config.json uses ${chalk.green(gtConfig.projectId)}, but GT_PROJECT_ID uses ${chalk.green(projectIdEnv)}. Use the same projectId in all configs.`\n );\n }\n\n if (\n flags.options?.docsUrlPattern &&\n !flags.options?.docsUrlPattern.includes('[locale]')\n ) {\n logErrorAndExit(\n 'Static URLs could not be localized because the URL pattern is missing \"[locale]\". Add \"[locale]\" where the locale should appear in the generated URL.'\n );\n }\n\n if (\n flags.options?.docsImportPattern &&\n !flags.options?.docsImportPattern.includes('[locale]')\n ) {\n logErrorAndExit(\n 'Static imports could not be localized because the import pattern is missing \"[locale]\". Add \"[locale]\" where the locale should appear in the generated import path.'\n );\n }\n\n if (flags.options?.copyFiles) {\n for (const file of flags.options.copyFiles) {\n if (!file.includes('[locale]')) {\n logErrorAndExit(\n 'Files could not be copied because the file path is missing \"[locale]\". Add \"[locale]\" where the locale should appear in the copied path.'\n );\n }\n }\n }\n\n // Warn on deprecated includeSourceCodeContext\n const configuredFiles = gtConfig.files as FilesOptions | undefined;\n if (configuredFiles?.gt?.includeSourceCodeContext != null) {\n warnDeprecatedField(\n 'files.gt.includeSourceCodeContext',\n 'files.gt.parsingFlags.includeSourceCodeContext'\n );\n }\n\n // merge options\n const mergedOptions: Settings = { ...gtConfig, ...flags } as Settings;\n\n if (\n determineLibrary().library === 'base' &&\n !hasConfiguredTranslationFiles(mergedOptions.files)\n ) {\n logger.warn(\n chalk.yellow(\n 'No package.json or Python project file found in the current directory. Run this command from the root of your project.'\n )\n );\n }\n\n // Add defaultLocale if not provided\n mergedOptions.defaultLocale =\n mergedOptions.defaultLocale || libraryDefaultLocale;\n\n // merge locales\n mergedOptions.locales = Array.from(\n new Set([...(gtConfig.locales || []), ...(flags.locales || [])])\n );\n // Separate defaultLocale from locales\n mergedOptions.locales = mergedOptions.locales.filter(\n (locale) => locale !== mergedOptions.defaultLocale\n );\n\n // Add apiKey if not provided\n mergedOptions.apiKey = mergedOptions.apiKey || process.env.GT_API_KEY;\n\n // Add projectId if not provided\n mergedOptions.projectId = mergedOptions.projectId || resolveProjectId();\n\n // Add baseUrl if not provided\n mergedOptions.baseUrl = mergedOptions.baseUrl || defaultBaseUrl;\n\n // Add dashboardUrl if not provided\n mergedOptions.dashboardUrl = mergedOptions.dashboardUrl || GT_DASHBOARD_URL;\n\n // Add locales if not provided\n mergedOptions.locales = mergedOptions.locales || [];\n\n // Only set config path if one was actually found or explicitly provided.\n // Do not default to a phantom path — that would cause downstream writes\n // (e.g. updateConfig) to silently create a config file.\n if (!mergedOptions.config) {\n mergedOptions.config = '';\n }\n\n // Display projectId if present\n if (mergedOptions.projectId) {\n displayProjectId(mergedOptions.projectId);\n }\n\n // Add stageTranslations if not provided\n // For human review, always stage the project\n mergedOptions.stageTranslations = mergedOptions.stageTranslations ?? false;\n\n // Top-level default for whether translated files require approval before use.\n // Effective policy is hash-changing, so reject anything but a real boolean.\n if (\n mergedOptions.requiresReview !== undefined &&\n typeof mergedOptions.requiresReview !== 'boolean'\n ) {\n logErrorAndExit(\n 'requiresReview in gt.config.json must be a boolean. Use files.<type>.requiresReview for glob-scoped overrides.'\n );\n }\n mergedOptions.requiresReview = mergedOptions.requiresReview ?? false;\n\n // Add publish — only set if explicitly configured or passed via flag.\n // When neither is set, leave undefined so the publish step knows\n // there is no global publish intent.\n if (flags.publish) {\n mergedOptions.publish = true;\n } else if (gtConfig.publish !== undefined) {\n mergedOptions.publish = gtConfig.publish;\n } else {\n mergedOptions.publish = undefined;\n }\n\n mergedOptions.omitConfigIds =\n flags.omitConfigIds === true || gtConfig.omitConfigIds === true;\n\n // Don't default src here — each pipeline (JS/Python) has its own defaults.\n // Only set src if the user explicitly provided it via flags or config.\n\n // Resolve all glob patterns in the files object\n const compositePatterns = Object.entries(\n mergedOptions.options?.jsonSchema || {}\n )\n .filter(([, schema]) => schema.composite)\n .map(([key]) => key);\n mergedOptions.files = mergedOptions.files\n ? resolveFiles(\n normalizeFilesOptions(mergedOptions.files as FilesOptions),\n mergedOptions.defaultLocale,\n mergedOptions.locales,\n cwd,\n compositePatterns,\n mergedOptions.requiresReview\n )\n : {\n resolvedPaths: {},\n placeholderPaths: {},\n transformPaths: {},\n transformFormats: {},\n publishPaths: new Set<string>(),\n unpublishPaths: new Set<string>(),\n requiresReviewPaths: new Set<string>(),\n parsingFlags: {},\n gtJson: {\n parsingFlags: GT_PARSING_FLAGS_DEFAULT,\n },\n };\n\n mergedOptions.options = {\n ...mergedOptions.options,\n mintlify: {\n ...mergedOptions.options?.mintlify,\n inferTitleFromFilename:\n gtConfig.options?.mintlify?.inferTitleFromFilename ||\n mergedOptions.options?.mintlify?.inferTitleFromFilename,\n },\n experimentalLocalizeStaticImports:\n gtConfig.options?.experimentalLocalizeStaticImports ||\n flags.experimentalLocalizeStaticImports,\n experimentalLocalizeStaticUrls:\n gtConfig.options?.experimentalLocalizeStaticUrls ||\n flags.experimentalLocalizeStaticUrls,\n experimentalLocalizeRelativeAssets:\n gtConfig.options?.experimentalLocalizeRelativeAssets ||\n flags.experimentalLocalizeRelativeAssets,\n experimentalHideDefaultLocale:\n gtConfig.options?.experimentalHideDefaultLocale ||\n flags.experimentalHideDefaultLocale,\n experimentalFlattenJsonFiles:\n gtConfig.options?.experimentalFlattenJsonFiles ||\n flags.experimentalFlattenJsonFiles,\n experimentalClearLocaleDirs:\n gtConfig.options?.experimentalClearLocaleDirs ||\n flags.experimentalClearLocaleDirs,\n clearLocaleDirsExclude:\n gtConfig.options?.clearLocaleDirsExclude || flags.clearLocaleDirsExclude,\n saveLocal: flags.saveLocal ?? gtConfig.options?.saveLocal ?? false,\n };\n\n if (\n mergedOptions.omitConfigIds &&\n (mergedOptions.publish === true ||\n mergedOptions.files.gtJson.publish === true)\n ) {\n logger.warn(\n chalk.yellow(\n 'Config IDs will be omitted even though CDN publishing is enabled. Remote cache/CDN consumers may load the latest available translations instead of a pinned version.'\n )\n );\n }\n\n // Add additional options if provided\n if (mergedOptions.options) {\n if (mergedOptions.options.jsonSchema) {\n for (const fileGlob of Object.keys(mergedOptions.options.jsonSchema)) {\n const jsonSchema = mergedOptions.options.jsonSchema[fileGlob];\n if (jsonSchema.preset) {\n mergedOptions.options.jsonSchema[fileGlob] = {\n ...generatePreset(jsonSchema.preset, 'json'),\n ...jsonSchema,\n };\n }\n }\n }\n if (mergedOptions.options.yamlSchema) {\n for (const fileGlob of Object.keys(mergedOptions.options.yamlSchema)) {\n const yamlSchema = mergedOptions.options.yamlSchema[fileGlob];\n if (yamlSchema.preset) {\n mergedOptions.options.yamlSchema[fileGlob] = {\n ...generatePreset(yamlSchema.preset, 'yaml'),\n ...yamlSchema,\n };\n }\n }\n }\n }\n\n // Add parsing options if not provided\n mergedOptions.parsingOptions = mergedOptions.parsingOptions || {};\n mergedOptions.parsingOptions.conditionNames = mergedOptions.parsingOptions\n .conditionNames || [\n 'development',\n 'browser',\n 'module',\n 'import',\n 'require',\n 'default',\n ];\n\n // Add branch options if not provided\n const branchOptions = mergedOptions.branchOptions || {};\n // If --branch is set, enable branching\n branchOptions.enabled =\n flags.enableBranching ??\n gtConfig.branchOptions?.enabled ??\n (flags.branch ? true : false);\n branchOptions.currentBranch =\n flags.branch ?? gtConfig.branchOptions?.currentBranch ?? undefined;\n branchOptions.autoDetectBranches = flags.disableBranchDetection\n ? false\n : (gtConfig.branchOptions?.autoDetectBranches ?? true);\n branchOptions.remoteName =\n flags.remoteName ??\n gtConfig.branchOptions?.remoteName ??\n DEFAULT_GIT_REMOTE_NAME;\n mergedOptions.branchOptions = branchOptions;\n\n // Map -m/--message flag to tagMessage\n if (flags.message) {\n mergedOptions.tagMessage = flags.message;\n }\n\n // Resolve tag:\n // --tag (bare) or -m without --tag: try git SHA, fall back to random hex\n // --tag <value>: use as-is\n // No flags: no tag\n if (flags.tag === true || (!flags.tag && mergedOptions.tagMessage)) {\n try {\n mergedOptions.tag = execSync('git rev-parse --short HEAD', {\n encoding: 'utf-8',\n }).trim();\n // If no message provided, use git commit message\n if (!mergedOptions.tagMessage) {\n mergedOptions.tagMessage = execSync('git log -1 --format=%s', {\n encoding: 'utf-8',\n }).trim();\n }\n } catch {\n // Not in a git repo or git unavailable — fall back to random hex\n mergedOptions.tag = crypto.randomBytes(4).toString('hex');\n }\n }\n\n mergedOptions.configDirectory = path.join(cwd, '.gt');\n\n validateSettings(mergedOptions);\n\n // Keep both clients on the same resolved credentials while consumers migrate.\n configureApiClient({\n projectId: mergedOptions.projectId,\n apiKey: mergedOptions.apiKey,\n baseUrl: mergedOptions.baseUrl,\n customMapping: mergedOptions.customMapping,\n });\n gt.setConfig({\n projectId: mergedOptions.projectId,\n apiKey: mergedOptions.apiKey,\n baseUrl: mergedOptions.baseUrl,\n sourceLocale: mergedOptions.defaultLocale,\n customMapping: mergedOptions.customMapping,\n });\n\n return mergedOptions;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"generateSettings.js","names":[],"sources":["../../src/config/generateSettings.ts"],"sourcesContent":["import {\n displayProjectId,\n exitSync,\n logErrorAndExit,\n warnApiKeyInConfig,\n warnDeprecatedField,\n} from '../console/logging.js';\nimport { loadConfig } from '../fs/config/loadConfig.js';\nimport { FilesOptions, Settings } from '../types/index.js';\nimport {\n defaultBaseUrl,\n libraryDefaultLocale,\n} from 'generaltranslation/internal';\nimport { resolveFiles } from '../fs/config/parseFilesConfig.js';\nimport { validateSettings } from './validateSettings.js';\nimport {\n DEFAULT_GIT_REMOTE_NAME,\n GT_DASHBOARD_URL,\n} from '../utils/constants.js';\nimport { resolveProjectId } from '../fs/utils.js';\nimport { createUserTokenProvider } from '../auth/oauth.js';\nimport crypto from 'node:crypto';\nimport { execSync } from 'node:child_process';\nimport path from 'node:path';\nimport chalk from 'chalk';\nimport { resolveConfig } from './resolveConfig.js';\nimport { configureApiClient } from '../utils/api.js';\nimport { generatePreset } from './optionPresets.js';\nimport { GT_PARSING_FLAGS_DEFAULT } from './defaults.js';\nimport { normalizeFilesOptions } from '../formats/files/transformFormat.js';\nimport { determineLibrary } from '../fs/determineFramework/index.js';\nimport { logger } from '../console/logger.js';\n\nexport const DEFAULT_SRC_PATTERNS = [\n 'src/**/*.{js,jsx,ts,tsx}',\n 'app/**/*.{js,jsx,ts,tsx}',\n 'pages/**/*.{js,jsx,ts,tsx}',\n 'components/**/*.{js,jsx,ts,tsx}',\n];\n\nexport const DEFAULT_PYTHON_SRC_PATTERNS = ['**/*.py'];\nexport const DEFAULT_PYTHON_SRC_EXCLUDES = [\n 'venv/**',\n '.venv/**',\n '__pycache__/**',\n '**/migrations/**',\n '**/tests/**',\n '**/test_*.py',\n '**/*_test.py',\n];\n\ntype GenerateSettingsInput = Partial<Omit<Settings, 'tag'>> & {\n config?: string;\n projectId?: string;\n locales?: string[];\n options?: Settings['options'];\n files?: unknown;\n publish?: boolean;\n omitConfigIds?: boolean;\n saveLocal?: boolean;\n tag?: string | boolean;\n message?: string;\n branch?: string;\n enableBranching?: boolean;\n disableBranchDetection?: boolean;\n remoteName?: string;\n experimentalLocalizeStaticImports?: boolean;\n experimentalLocalizeStaticUrls?: boolean;\n experimentalLocalizeRelativeAssets?: boolean;\n experimentalHideDefaultLocale?: boolean;\n experimentalFlattenJsonFiles?: boolean;\n experimentalClearLocaleDirs?: boolean;\n clearLocaleDirsExclude?: string[];\n [key: string]: unknown;\n};\n\nfunction hasConfiguredTranslationFiles(files: unknown): boolean {\n if (!files || typeof files !== 'object' || Array.isArray(files)) {\n return false;\n }\n return Object.keys(files).some((key) => key !== 'gt');\n}\n\n/**\n * Generates settings from any\n * @param flags - The CLI flags to generate settings from\n * @param cwd - The current working directory\n * @param options - Additional options\n * @param options.requireConfig - If true, exit with an error when no config file is found\n * @returns The generated settings\n */\nexport async function generateSettings(\n flags: GenerateSettingsInput,\n cwd: string = process.cwd(),\n options?: { requireConfig?: boolean }\n): Promise<Settings> {\n // Load config file\n let gtConfig: GenerateSettingsInput = {};\n\n if (flags.config && !flags.config.endsWith('.json')) {\n flags.config = `${flags.config}.json`;\n }\n if (flags.config) {\n gtConfig = loadConfig(flags.config);\n } else {\n const config = resolveConfig(cwd);\n if (config) {\n gtConfig = config.config as GenerateSettingsInput;\n flags.config = config.path;\n } else {\n if (options?.requireConfig) {\n return logErrorAndExit(\n 'No gt.config.json file was found. Run `npx gt init` to create one, pass --config, or run this command from your project root.'\n );\n }\n gtConfig = {};\n }\n }\n\n // Warn if apiKey is present in gt.config.json\n if (gtConfig.apiKey) {\n warnApiKeyInConfig(flags.config ?? 'gt.config.json');\n exitSync(1);\n }\n const projectIdEnv = resolveProjectId();\n // Resolve mismatched projectIds\n if (\n gtConfig.projectId &&\n flags.projectId &&\n gtConfig.projectId !== flags.projectId\n ) {\n logErrorAndExit(\n `Project ID mismatch: gt.config.json uses ${chalk.green(gtConfig.projectId)}, but the CLI flag uses ${chalk.green(flags.projectId)}. Use the same projectId in all configs.`\n );\n } else if (\n gtConfig.projectId &&\n projectIdEnv &&\n gtConfig.projectId !== projectIdEnv\n ) {\n logErrorAndExit(\n `Project ID mismatch: gt.config.json uses ${chalk.green(gtConfig.projectId)}, but GT_PROJECT_ID uses ${chalk.green(projectIdEnv)}. Use the same projectId in all configs.`\n );\n }\n\n if (\n flags.options?.docsUrlPattern &&\n !flags.options?.docsUrlPattern.includes('[locale]')\n ) {\n logErrorAndExit(\n 'Static URLs could not be localized because the URL pattern is missing \"[locale]\". Add \"[locale]\" where the locale should appear in the generated URL.'\n );\n }\n\n if (\n flags.options?.docsImportPattern &&\n !flags.options?.docsImportPattern.includes('[locale]')\n ) {\n logErrorAndExit(\n 'Static imports could not be localized because the import pattern is missing \"[locale]\". Add \"[locale]\" where the locale should appear in the generated import path.'\n );\n }\n\n if (flags.options?.copyFiles) {\n for (const file of flags.options.copyFiles) {\n if (!file.includes('[locale]')) {\n logErrorAndExit(\n 'Files could not be copied because the file path is missing \"[locale]\". Add \"[locale]\" where the locale should appear in the copied path.'\n );\n }\n }\n }\n\n // Warn on deprecated includeSourceCodeContext\n const configuredFiles = gtConfig.files as FilesOptions | undefined;\n if (configuredFiles?.gt?.includeSourceCodeContext != null) {\n warnDeprecatedField(\n 'files.gt.includeSourceCodeContext',\n 'files.gt.parsingFlags.includeSourceCodeContext'\n );\n }\n\n // merge options\n const mergedOptions: Settings = { ...gtConfig, ...flags } as Settings;\n\n if (\n determineLibrary().library === 'base' &&\n !hasConfiguredTranslationFiles(mergedOptions.files)\n ) {\n logger.warn(\n chalk.yellow(\n 'No package.json or Python project file found in the current directory. Run this command from the root of your project.'\n )\n );\n }\n\n // Add defaultLocale if not provided\n mergedOptions.defaultLocale =\n mergedOptions.defaultLocale || libraryDefaultLocale;\n\n // merge locales\n mergedOptions.locales = Array.from(\n new Set([...(gtConfig.locales || []), ...(flags.locales || [])])\n );\n // Separate defaultLocale from locales\n mergedOptions.locales = mergedOptions.locales.filter(\n (locale) => locale !== mergedOptions.defaultLocale\n );\n\n // Add projectId if not provided\n mergedOptions.projectId = mergedOptions.projectId || resolveProjectId();\n\n // Add baseUrl if not provided\n mergedOptions.baseUrl = mergedOptions.baseUrl || defaultBaseUrl;\n\n // The API client prefers apiKey when both are set; the provider is lazy.\n mergedOptions.apiKey = mergedOptions.apiKey || process.env.GT_API_KEY;\n mergedOptions.userTokenProvider = createUserTokenProvider({\n baseUrl: mergedOptions.baseUrl,\n });\n\n // Add dashboardUrl if not provided\n mergedOptions.dashboardUrl = mergedOptions.dashboardUrl || GT_DASHBOARD_URL;\n\n // Add locales if not provided\n mergedOptions.locales = mergedOptions.locales || [];\n\n // Only set config path if one was actually found or explicitly provided.\n // Do not default to a phantom path — that would cause downstream writes\n // (e.g. updateConfig) to silently create a config file.\n if (!mergedOptions.config) {\n mergedOptions.config = '';\n }\n\n // Display projectId if present\n if (mergedOptions.projectId) {\n displayProjectId(mergedOptions.projectId);\n }\n\n // Add stageTranslations if not provided\n // For human review, always stage the project\n mergedOptions.stageTranslations = mergedOptions.stageTranslations ?? false;\n\n // Top-level default for whether translated files require approval before use.\n // Effective policy is hash-changing, so reject anything but a real boolean.\n if (\n mergedOptions.requiresReview !== undefined &&\n typeof mergedOptions.requiresReview !== 'boolean'\n ) {\n logErrorAndExit(\n 'requiresReview in gt.config.json must be a boolean. Use files.<type>.requiresReview for glob-scoped overrides.'\n );\n }\n mergedOptions.requiresReview = mergedOptions.requiresReview ?? false;\n\n // Add publish — only set if explicitly configured or passed via flag.\n // When neither is set, leave undefined so the publish step knows\n // there is no global publish intent.\n if (flags.publish) {\n mergedOptions.publish = true;\n } else if (gtConfig.publish !== undefined) {\n mergedOptions.publish = gtConfig.publish;\n } else {\n mergedOptions.publish = undefined;\n }\n\n mergedOptions.omitConfigIds =\n flags.omitConfigIds === true || gtConfig.omitConfigIds === true;\n\n // Don't default src here — each pipeline (JS/Python) has its own defaults.\n // Only set src if the user explicitly provided it via flags or config.\n\n // Resolve all glob patterns in the files object\n const compositePatterns = Object.entries(\n mergedOptions.options?.jsonSchema || {}\n )\n .filter(([, schema]) => schema.composite)\n .map(([key]) => key);\n mergedOptions.files = mergedOptions.files\n ? resolveFiles(\n normalizeFilesOptions(mergedOptions.files as FilesOptions),\n mergedOptions.defaultLocale,\n mergedOptions.locales,\n cwd,\n compositePatterns,\n mergedOptions.requiresReview\n )\n : {\n resolvedPaths: {},\n placeholderPaths: {},\n transformPaths: {},\n transformFormats: {},\n publishPaths: new Set<string>(),\n unpublishPaths: new Set<string>(),\n requiresReviewPaths: new Set<string>(),\n parsingFlags: {},\n gtJson: {\n parsingFlags: GT_PARSING_FLAGS_DEFAULT,\n },\n };\n\n mergedOptions.options = {\n ...mergedOptions.options,\n mintlify: {\n ...mergedOptions.options?.mintlify,\n inferTitleFromFilename:\n gtConfig.options?.mintlify?.inferTitleFromFilename ||\n mergedOptions.options?.mintlify?.inferTitleFromFilename,\n },\n experimentalLocalizeStaticImports:\n gtConfig.options?.experimentalLocalizeStaticImports ||\n flags.experimentalLocalizeStaticImports,\n experimentalLocalizeStaticUrls:\n gtConfig.options?.experimentalLocalizeStaticUrls ||\n flags.experimentalLocalizeStaticUrls,\n experimentalLocalizeRelativeAssets:\n gtConfig.options?.experimentalLocalizeRelativeAssets ||\n flags.experimentalLocalizeRelativeAssets,\n experimentalHideDefaultLocale:\n gtConfig.options?.experimentalHideDefaultLocale ||\n flags.experimentalHideDefaultLocale,\n experimentalFlattenJsonFiles:\n gtConfig.options?.experimentalFlattenJsonFiles ||\n flags.experimentalFlattenJsonFiles,\n experimentalClearLocaleDirs:\n gtConfig.options?.experimentalClearLocaleDirs ||\n flags.experimentalClearLocaleDirs,\n clearLocaleDirsExclude:\n gtConfig.options?.clearLocaleDirsExclude || flags.clearLocaleDirsExclude,\n saveLocal: flags.saveLocal ?? gtConfig.options?.saveLocal ?? false,\n };\n\n if (\n mergedOptions.omitConfigIds &&\n (mergedOptions.publish === true ||\n mergedOptions.files.gtJson.publish === true)\n ) {\n logger.warn(\n chalk.yellow(\n 'Config IDs will be omitted even though CDN publishing is enabled. Remote cache/CDN consumers may load the latest available translations instead of a pinned version.'\n )\n );\n }\n\n // Add additional options if provided\n if (mergedOptions.options) {\n if (mergedOptions.options.jsonSchema) {\n for (const fileGlob of Object.keys(mergedOptions.options.jsonSchema)) {\n const jsonSchema = mergedOptions.options.jsonSchema[fileGlob];\n if (jsonSchema.preset) {\n mergedOptions.options.jsonSchema[fileGlob] = {\n ...generatePreset(jsonSchema.preset, 'json'),\n ...jsonSchema,\n };\n }\n }\n }\n if (mergedOptions.options.yamlSchema) {\n for (const fileGlob of Object.keys(mergedOptions.options.yamlSchema)) {\n const yamlSchema = mergedOptions.options.yamlSchema[fileGlob];\n if (yamlSchema.preset) {\n mergedOptions.options.yamlSchema[fileGlob] = {\n ...generatePreset(yamlSchema.preset, 'yaml'),\n ...yamlSchema,\n };\n }\n }\n }\n }\n\n // Add parsing options if not provided\n mergedOptions.parsingOptions = mergedOptions.parsingOptions || {};\n mergedOptions.parsingOptions.conditionNames = mergedOptions.parsingOptions\n .conditionNames || [\n 'development',\n 'browser',\n 'module',\n 'import',\n 'require',\n 'default',\n ];\n\n // Add branch options if not provided\n const branchOptions = mergedOptions.branchOptions || {};\n // If --branch is set, enable branching\n branchOptions.enabled =\n flags.enableBranching ??\n gtConfig.branchOptions?.enabled ??\n (flags.branch ? true : false);\n branchOptions.currentBranch =\n flags.branch ?? gtConfig.branchOptions?.currentBranch ?? undefined;\n branchOptions.autoDetectBranches = flags.disableBranchDetection\n ? false\n : (gtConfig.branchOptions?.autoDetectBranches ?? true);\n branchOptions.remoteName =\n flags.remoteName ??\n gtConfig.branchOptions?.remoteName ??\n DEFAULT_GIT_REMOTE_NAME;\n mergedOptions.branchOptions = branchOptions;\n\n // Map -m/--message flag to tagMessage\n if (flags.message) {\n mergedOptions.tagMessage = flags.message;\n }\n\n // Resolve tag:\n // --tag (bare) or -m without --tag: try git SHA, fall back to random hex\n // --tag <value>: use as-is\n // No flags: no tag\n if (flags.tag === true || (!flags.tag && mergedOptions.tagMessage)) {\n try {\n mergedOptions.tag = execSync('git rev-parse --short HEAD', {\n encoding: 'utf-8',\n }).trim();\n // If no message provided, use git commit message\n if (!mergedOptions.tagMessage) {\n mergedOptions.tagMessage = execSync('git log -1 --format=%s', {\n encoding: 'utf-8',\n }).trim();\n }\n } catch {\n // Not in a git repo or git unavailable — fall back to random hex\n mergedOptions.tag = crypto.randomBytes(4).toString('hex');\n }\n }\n\n mergedOptions.configDirectory = path.join(cwd, '.gt');\n\n validateSettings(mergedOptions);\n\n configureApiClient({\n projectId: mergedOptions.projectId,\n apiKey: mergedOptions.apiKey,\n userTokenProvider: mergedOptions.userTokenProvider,\n baseUrl: mergedOptions.baseUrl,\n customMapping: mergedOptions.customMapping,\n });\n\n return mergedOptions;\n}\n"],"mappings":"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"}
|
|
@@ -16,13 +16,21 @@ function generatePreset(preset, type) {
|
|
|
16
16
|
"$..anchor",
|
|
17
17
|
"$..dropdown",
|
|
18
18
|
"$..product",
|
|
19
|
-
"$..description"
|
|
19
|
+
"$..description",
|
|
20
|
+
"$..header",
|
|
21
|
+
"$..label"
|
|
20
22
|
],
|
|
21
23
|
omitProperties: ["default"],
|
|
22
|
-
transform: {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
transform: {
|
|
25
|
+
"$..pages[*]": {
|
|
26
|
+
match: "^{locale}/(.*)$",
|
|
27
|
+
replace: "{locale}/$1"
|
|
28
|
+
},
|
|
29
|
+
"$..root": {
|
|
30
|
+
match: "^{locale}/(.*)$",
|
|
31
|
+
replace: "{locale}/$1"
|
|
32
|
+
}
|
|
33
|
+
}
|
|
26
34
|
},
|
|
27
35
|
"$.redirects": {
|
|
28
36
|
type: "array",
|
|
@@ -55,7 +63,9 @@ function generatePreset(preset, type) {
|
|
|
55
63
|
"$..anchor",
|
|
56
64
|
"$..dropdown",
|
|
57
65
|
"$..product",
|
|
58
|
-
"$..description"
|
|
66
|
+
"$..description",
|
|
67
|
+
"$..header",
|
|
68
|
+
"$..label"
|
|
59
69
|
],
|
|
60
70
|
omitProperties: ["default"],
|
|
61
71
|
transform: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"optionPresets.js","names":[],"sources":["../../src/config/optionPresets.ts"],"sourcesContent":["import { JsonSchema, YamlSchema } from '../types/index.js';\n\nexport function generatePreset(\n preset: JsonSchema['preset'],\n type: 'json'\n): JsonSchema;\nexport function generatePreset(\n preset: YamlSchema['preset'],\n type: 'yaml'\n): YamlSchema;\nexport function generatePreset(\n preset: string | undefined,\n type: 'json' | 'yaml'\n): JsonSchema | YamlSchema {\n if (type === 'json') {\n switch (preset) {\n case 'mintlify':\n // https://mintlify.com/docs/navigation\n return {\n resolveRefs: true,\n composite: {\n '$.navigation.languages': {\n type: 'array',\n key: '$.language',\n experimentalSort: 'localesAlphabetical',\n splitEntries: true,\n include: [\n '$..group',\n '$..tab',\n '$..item',\n '$..anchor',\n '$..dropdown',\n '$..product',\n '$..description',\n ],\n omitProperties: ['default'],\n transform: {\n '$..pages[*]': {\n match: '^{locale}/(.*)$',\n replace: '{locale}/$1',\n },\n },\n },\n '$.redirects': {\n type: 'array',\n key: '$.language',\n include: [],\n transform: {\n '$.source': {\n match: '^/{locale}/(.*)$',\n replace: '/{locale}/$1',\n },\n '$.destination': {\n match: '^/{locale}/(.*)$',\n replace: '/{locale}/$1',\n },\n },\n },\n },\n };\n case 'mintlify-hide-default':\n // Mintlify with hideDefaultLocale — paths don't have locale prefix in source\n return {\n resolveRefs: true,\n composite: {\n '$.navigation.languages': {\n type: 'array',\n key: '$.language',\n experimentalSort: 'localesAlphabetical',\n splitEntries: true,\n include: [\n '$..group',\n '$..tab',\n '$..item',\n '$..anchor',\n '$..dropdown',\n '$..product',\n '$..description',\n ],\n omitProperties: ['default'],\n transform: {\n '$..pages[*]': {\n match: '^/?(.*)$',\n replace: '{locale}/$1',\n },\n '$..root': {\n match: '^/?(.*)$',\n replace: '{locale}/$1',\n },\n },\n },\n },\n };\n case 'openapi':\n return {\n include: ['$..summary', '$..description'],\n };\n default:\n return {};\n }\n } else {\n switch (preset) {\n case 'mintlify':\n return {\n include: ['$..summary', '$..description'],\n };\n case 'openapi':\n return {\n include: ['$..summary', '$..description'],\n };\n default:\n return {};\n }\n }\n}\n"],"mappings":";AAUA,SAAgB,eACd,QACA,MACyB;AACzB,KAAI,SAAS,OACX,SAAQ,QAAR;EACE,KAAK,WAEH,QAAO;GACL,aAAa;GACb,WAAW;IACT,0BAA0B;KACxB,MAAM;KACN,KAAK;KACL,kBAAkB;KAClB,cAAc;KACd,SAAS;MACP;MACA;MACA;MACA;MACA;MACA;MACA;MACD;KACD,gBAAgB,CAAC,UAAU;KAC3B,WAAW,
|
|
1
|
+
{"version":3,"file":"optionPresets.js","names":[],"sources":["../../src/config/optionPresets.ts"],"sourcesContent":["import { JsonSchema, YamlSchema } from '../types/index.js';\n\nexport function generatePreset(\n preset: JsonSchema['preset'],\n type: 'json'\n): JsonSchema;\nexport function generatePreset(\n preset: YamlSchema['preset'],\n type: 'yaml'\n): YamlSchema;\nexport function generatePreset(\n preset: string | undefined,\n type: 'json' | 'yaml'\n): JsonSchema | YamlSchema {\n if (type === 'json') {\n switch (preset) {\n case 'mintlify':\n // https://mintlify.com/docs/navigation\n return {\n resolveRefs: true,\n composite: {\n '$.navigation.languages': {\n type: 'array',\n key: '$.language',\n experimentalSort: 'localesAlphabetical',\n splitEntries: true,\n include: [\n '$..group',\n '$..tab',\n '$..item',\n '$..anchor',\n '$..dropdown',\n '$..product',\n '$..description',\n '$..header',\n '$..label',\n ],\n omitProperties: ['default'],\n transform: {\n '$..pages[*]': {\n match: '^{locale}/(.*)$',\n replace: '{locale}/$1',\n },\n '$..root': {\n match: '^{locale}/(.*)$',\n replace: '{locale}/$1',\n },\n },\n },\n '$.redirects': {\n type: 'array',\n key: '$.language',\n include: [],\n transform: {\n '$.source': {\n match: '^/{locale}/(.*)$',\n replace: '/{locale}/$1',\n },\n '$.destination': {\n match: '^/{locale}/(.*)$',\n replace: '/{locale}/$1',\n },\n },\n },\n },\n };\n case 'mintlify-hide-default':\n // Mintlify with hideDefaultLocale — paths don't have locale prefix in source\n return {\n resolveRefs: true,\n composite: {\n '$.navigation.languages': {\n type: 'array',\n key: '$.language',\n experimentalSort: 'localesAlphabetical',\n splitEntries: true,\n include: [\n '$..group',\n '$..tab',\n '$..item',\n '$..anchor',\n '$..dropdown',\n '$..product',\n '$..description',\n '$..header',\n '$..label',\n ],\n omitProperties: ['default'],\n transform: {\n '$..pages[*]': {\n match: '^/?(.*)$',\n replace: '{locale}/$1',\n },\n '$..root': {\n match: '^/?(.*)$',\n replace: '{locale}/$1',\n },\n },\n },\n },\n };\n case 'openapi':\n return {\n include: ['$..summary', '$..description'],\n };\n default:\n return {};\n }\n } else {\n switch (preset) {\n case 'mintlify':\n return {\n include: ['$..summary', '$..description'],\n };\n case 'openapi':\n return {\n include: ['$..summary', '$..description'],\n };\n default:\n return {};\n }\n }\n}\n"],"mappings":";AAUA,SAAgB,eACd,QACA,MACyB;AACzB,KAAI,SAAS,OACX,SAAQ,QAAR;EACE,KAAK,WAEH,QAAO;GACL,aAAa;GACb,WAAW;IACT,0BAA0B;KACxB,MAAM;KACN,KAAK;KACL,kBAAkB;KAClB,cAAc;KACd,SAAS;MACP;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACD;KACD,gBAAgB,CAAC,UAAU;KAC3B,WAAW;MACT,eAAe;OACb,OAAO;OACP,SAAS;OACV;MACD,WAAW;OACT,OAAO;OACP,SAAS;OACV;MACF;KACF;IACD,eAAe;KACb,MAAM;KACN,KAAK;KACL,SAAS,EAAE;KACX,WAAW;MACT,YAAY;OACV,OAAO;OACP,SAAS;OACV;MACD,iBAAiB;OACf,OAAO;OACP,SAAS;OACV;MACF;KACF;IACF;GACF;EACH,KAAK,wBAEH,QAAO;GACL,aAAa;GACb,WAAW,EACT,0BAA0B;IACxB,MAAM;IACN,KAAK;IACL,kBAAkB;IAClB,cAAc;IACd,SAAS;KACP;KACA;KACA;KACA;KACA;KACA;KACA;KACA;KACA;KACD;IACD,gBAAgB,CAAC,UAAU;IAC3B,WAAW;KACT,eAAe;MACb,OAAO;MACP,SAAS;MACV;KACD,WAAW;MACT,OAAO;MACP,SAAS;MACV;KACF;IACF,EACF;GACF;EACH,KAAK,UACH,QAAO,EACL,SAAS,CAAC,cAAc,iBAAiB,EAC1C;EACH,QACE,QAAO,EAAE;;KAGb,SAAQ,QAAR;EACE,KAAK,WACH,QAAO,EACL,SAAS,CAAC,cAAc,iBAAiB,EAC1C;EACH,KAAK,UACH,QAAO,EACL,SAAS,CAAC,cAAc,iBAAiB,EAC1C;EACH,QACE,QAAO,EAAE"}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
-
import { Settings } from '../types/index.js';
|
|
2
|
-
export declare function validateSettings(settings: Settings
|
|
1
|
+
import type { Settings } from '../types/index.js';
|
|
2
|
+
export declare function validateSettings(settings: Omit<Settings, 'modelProvider'> & {
|
|
3
|
+
modelProvider?: unknown;
|
|
4
|
+
}): asserts settings is Settings;
|
|
3
5
|
export declare function validateConfigExists(): string;
|
|
@@ -1,9 +1,18 @@
|
|
|
1
1
|
import { logErrorAndExit } from "../console/logging.js";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import fs from "node:fs";
|
|
4
|
+
import { createDiagnosticMessage } from "generaltranslation/diagnostics";
|
|
5
|
+
import { isModelProvider, supportedModelProviders } from "generaltranslation/internal";
|
|
4
6
|
import { isSupersetLocale, isValidLocale } from "@generaltranslation/format";
|
|
5
7
|
//#region src/config/validateSettings.ts
|
|
6
8
|
function validateSettings(settings) {
|
|
9
|
+
if (settings.modelProvider !== void 0 && !isModelProvider(settings.modelProvider)) return logErrorAndExit(createDiagnosticMessage({
|
|
10
|
+
source: "gt",
|
|
11
|
+
severity: "Error",
|
|
12
|
+
whatHappened: "The configured model provider is not supported",
|
|
13
|
+
details: String(settings.modelProvider),
|
|
14
|
+
fix: `Use one of: ${supportedModelProviders.join(", ")}`
|
|
15
|
+
}));
|
|
7
16
|
for (const locale of settings.locales) if (!isValidLocale(locale, settings.customMapping)) return logErrorAndExit(`Locale "${locale}" is not valid in the provided locales: "${settings?.locales?.join()}". Use a valid BCP 47 locale code or add a custom mapping in gt.config.json.`);
|
|
8
17
|
if (settings.defaultLocale && !isValidLocale(settings.defaultLocale, settings.customMapping)) return logErrorAndExit(`defaultLocale "${settings.defaultLocale}" is not valid. Use a valid BCP 47 locale code or add a custom mapping in gt.config.json.`);
|
|
9
18
|
if (settings.defaultLocale && settings.locales.some((locale) => isSupersetLocale(settings.defaultLocale, locale) && !isSupersetLocale(locale, settings.defaultLocale))) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validateSettings.js","names":[],"sources":["../../src/config/validateSettings.ts"],"sourcesContent":["import { isValidLocale, isSupersetLocale } from '@generaltranslation/format';\nimport { Settings } from '../types/index.js';\nimport { logErrorAndExit } from '../console/logging.js';\nimport fs from 'node:fs';\nimport path from 'node:path';\n\nexport function validateSettings(settings: Settings) {\n // Validate locales\n for (const locale of settings.locales) {\n if (!isValidLocale(locale, settings.customMapping)) {\n return logErrorAndExit(\n `Locale \"${locale}\" is not valid in the provided locales: \"${settings?.locales?.join()}\". Use a valid BCP 47 locale code or add a custom mapping in gt.config.json.`\n );\n }\n }\n if (\n settings.defaultLocale &&\n !isValidLocale(settings.defaultLocale, settings.customMapping)\n ) {\n return logErrorAndExit(\n `defaultLocale \"${settings.defaultLocale}\" is not valid. Use a valid BCP 47 locale code or add a custom mapping in gt.config.json.`\n );\n }\n\n // defaultLocale cannot be a superset of any other locale\n if (\n settings.defaultLocale &&\n settings.locales.some(\n (locale) =>\n isSupersetLocale(settings.defaultLocale, locale) &&\n !isSupersetLocale(locale, settings.defaultLocale)\n )\n ) {\n const locale = settings.locales.find((locale) =>\n isSupersetLocale(settings.defaultLocale, locale)\n );\n return logErrorAndExit(\n `defaultLocale \"${settings.defaultLocale}\" is broader than configured locale \"${locale}\". Change defaultLocale to a more specific locale.`\n );\n }\n}\n\nexport function validateConfigExists() {\n const possibleConfigPaths = ['gt.config.json', 'src/gt.config.json'];\n for (const possibleConfigPath of possibleConfigPaths) {\n if (\n fs.existsSync(\n path.resolve(path.relative(process.cwd(), possibleConfigPath))\n )\n ) {\n return possibleConfigPath;\n }\n }\n return logErrorAndExit(\n 'No gt.config.json file was found. Run this command from your project root, pass --config, or run npx gt init to create one.'\n );\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"validateSettings.js","names":[],"sources":["../../src/config/validateSettings.ts"],"sourcesContent":["import { isValidLocale, isSupersetLocale } from '@generaltranslation/format';\nimport { createDiagnosticMessage } from 'generaltranslation/diagnostics';\nimport {\n isModelProvider,\n supportedModelProviders,\n} from 'generaltranslation/internal';\nimport type { Settings } from '../types/index.js';\nimport { logErrorAndExit } from '../console/logging.js';\nimport fs from 'node:fs';\nimport path from 'node:path';\n\nexport function validateSettings(\n settings: Omit<Settings, 'modelProvider'> & { modelProvider?: unknown }\n): asserts settings is Settings {\n if (\n settings.modelProvider !== undefined &&\n !isModelProvider(settings.modelProvider)\n ) {\n return logErrorAndExit(\n createDiagnosticMessage({\n source: 'gt',\n severity: 'Error',\n whatHappened: 'The configured model provider is not supported',\n details: String(settings.modelProvider),\n fix: `Use one of: ${supportedModelProviders.join(', ')}`,\n })\n );\n }\n\n // Validate locales\n for (const locale of settings.locales) {\n if (!isValidLocale(locale, settings.customMapping)) {\n return logErrorAndExit(\n `Locale \"${locale}\" is not valid in the provided locales: \"${settings?.locales?.join()}\". Use a valid BCP 47 locale code or add a custom mapping in gt.config.json.`\n );\n }\n }\n if (\n settings.defaultLocale &&\n !isValidLocale(settings.defaultLocale, settings.customMapping)\n ) {\n return logErrorAndExit(\n `defaultLocale \"${settings.defaultLocale}\" is not valid. Use a valid BCP 47 locale code or add a custom mapping in gt.config.json.`\n );\n }\n\n // defaultLocale cannot be a superset of any other locale\n if (\n settings.defaultLocale &&\n settings.locales.some(\n (locale) =>\n isSupersetLocale(settings.defaultLocale, locale) &&\n !isSupersetLocale(locale, settings.defaultLocale)\n )\n ) {\n const locale = settings.locales.find((locale) =>\n isSupersetLocale(settings.defaultLocale, locale)\n );\n return logErrorAndExit(\n `defaultLocale \"${settings.defaultLocale}\" is broader than configured locale \"${locale}\". Change defaultLocale to a more specific locale.`\n );\n }\n}\n\nexport function validateConfigExists() {\n const possibleConfigPaths = ['gt.config.json', 'src/gt.config.json'];\n for (const possibleConfigPath of possibleConfigPaths) {\n if (\n fs.existsSync(\n path.resolve(path.relative(process.cwd(), possibleConfigPath))\n )\n ) {\n return possibleConfigPath;\n }\n }\n return logErrorAndExit(\n 'No gt.config.json file was found. Run this command from your project root, pass --config, or run npx gt init to create one.'\n );\n}\n"],"mappings":";;;;;;;AAWA,SAAgB,iBACd,UAC8B;AAC9B,KACE,SAAS,kBAAkB,KAAA,KAC3B,CAAC,gBAAgB,SAAS,cAAc,CAExC,QAAO,gBACL,wBAAwB;EACtB,QAAQ;EACR,UAAU;EACV,cAAc;EACd,SAAS,OAAO,SAAS,cAAc;EACvC,KAAK,eAAe,wBAAwB,KAAK,KAAK;EACvD,CAAC,CACH;AAIH,MAAK,MAAM,UAAU,SAAS,QAC5B,KAAI,CAAC,cAAc,QAAQ,SAAS,cAAc,CAChD,QAAO,gBACL,WAAW,OAAO,2CAA2C,UAAU,SAAS,MAAM,CAAC,8EACxF;AAGL,KACE,SAAS,iBACT,CAAC,cAAc,SAAS,eAAe,SAAS,cAAc,CAE9D,QAAO,gBACL,kBAAkB,SAAS,cAAc,2FAC1C;AAIH,KACE,SAAS,iBACT,SAAS,QAAQ,MACd,WACC,iBAAiB,SAAS,eAAe,OAAO,IAChD,CAAC,iBAAiB,QAAQ,SAAS,cAAc,CACpD,EACD;EACA,MAAM,SAAS,SAAS,QAAQ,MAAM,WACpC,iBAAiB,SAAS,eAAe,OAAO,CACjD;AACD,SAAO,gBACL,kBAAkB,SAAS,cAAc,uCAAuC,OAAO,oDACxF;;;AAIL,SAAgB,uBAAuB;AAErC,MAAK,MAAM,sBAAsB,CADJ,kBAAkB,qBACK,CAClD,KACE,GAAG,WACD,KAAK,QAAQ,KAAK,SAAS,QAAQ,KAAK,EAAE,mBAAmB,CAAC,CAC/D,CAED,QAAO;AAGX,QAAO,gBACL,8HACD"}
|
package/dist/console/index.d.ts
CHANGED
|
@@ -37,8 +37,6 @@ export declare const noLocalesError = "No target locales were found. Add locales
|
|
|
37
37
|
export declare const noDefaultLocaleError = "No default locale was found. Add defaultLocale to gt.config.json or pass it with --default-locale.";
|
|
38
38
|
export declare const noFilesError = "The files configuration is missing or invalid. Check the files section in gt.config.json and try again.";
|
|
39
39
|
export declare const noSourceFileError = "No source translation file was found. Check your translations directory and default locale configuration.";
|
|
40
|
-
export declare const noApiKeyError = "No API key was found. Pass --api-key or set the GT_API_KEY environment variable.";
|
|
41
|
-
export declare 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";
|
|
42
40
|
export declare const noProjectIdError = "No project ID was found. Pass --project-id, add projectId to gt.config.json, or set the GT_PROJECT_ID environment variable.";
|
|
43
41
|
export declare const noVersionIdError = "No version ID was found. Pass --version-id or add _versionId to gt.config.json.";
|
|
44
42
|
export declare 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.";
|
package/dist/console/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { BRANCH_COMPONENT } from "../react/jsx/utils/constants.js";
|
|
2
2
|
import { colorizeComponent, colorizeContent, colorizeFilepath, colorizeFunctionName, colorizeIdString, colorizeLine } from "./colors.js";
|
|
3
3
|
import { formatCodeClamp } from "./formatting.js";
|
|
4
|
-
import { createDiagnosticMessage } from "generaltranslation/
|
|
4
|
+
import { createDiagnosticMessage } from "generaltranslation/diagnostics";
|
|
5
5
|
//#region src/console/index.ts
|
|
6
6
|
const withWillErrorInNextVersion = (message) => `${message} (This will become an error in the next major version of the CLI.)`;
|
|
7
7
|
const withDeriveComponentError = (message) => `<Derive> rules violation: ${message}`;
|
|
@@ -50,8 +50,6 @@ const noLocalesError = `No target locales were found. Add locales to gt.config.j
|
|
|
50
50
|
const noDefaultLocaleError = `No default locale was found. Add defaultLocale to gt.config.json or pass it with --default-locale.`;
|
|
51
51
|
const noFilesError = `The files configuration is missing or invalid. Check the files section in gt.config.json and try again.`;
|
|
52
52
|
const noSourceFileError = `No source translation file was found. Check your translations directory and default locale configuration.`;
|
|
53
|
-
const noApiKeyError = `No API key was found. Pass --api-key or set the GT_API_KEY environment variable.`;
|
|
54
|
-
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`;
|
|
55
53
|
const noProjectIdError = `No project ID was found. Pass --project-id, add projectId to gt.config.json, or set the GT_PROJECT_ID environment variable.`;
|
|
56
54
|
const noVersionIdError = `No version ID was found. Pass --version-id or add _versionId to gt.config.json.`;
|
|
57
55
|
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.`;
|
|
@@ -62,6 +60,6 @@ const xcstringsSourceLanguageMismatchError = (catalogs, defaultLocale) => `The f
|
|
|
62
60
|
const fileEncodingSkipReason = (error) => `File could not be decoded: ${error instanceof Error ? error.message : String(error)}`;
|
|
63
61
|
const withOriginalError = (message, error) => error != null ? `${message} Original error: ${String(error)}` : message;
|
|
64
62
|
//#endregion
|
|
65
|
-
export { branchResolutionError,
|
|
63
|
+
export { branchResolutionError, fileEncodingSkipReason, invalidConfigurationError, lottieExpressionsError, lottieTranslateError, noDefaultLocaleError, noFilesError, noLocalesError, noProjectIdError, noSourceFileError, noVersionIdError, warnApiKeyInConfigSync, warnAsyncUseGT, warnAutoderiveNoResultsSync, warnDataAttrOnBranch, warnDeprecatedTSugarPropsSync, warnDeriveCircularSpreadSync, warnDeriveDestructuringSync, warnDeriveFunctionNoResultsSync, warnDeriveFunctionNotWrappedSync, warnDeriveNonConstVariableSync, warnDeriveOptionalChainingSync, warnDeriveUnresolvableValueSync, warnDuplicateFunctionDefinitionSync, warnFailedToConstructJsxTreeSync, warnFunctionNotFoundSync, warnHasUnwrappedExpressionSync, warnInvalidDeclareVarNameSync, warnInvalidDeriveInitSync, warnInvalidFormatSync, warnInvalidIcuSync, warnInvalidMaxCharsSync, warnInvalidRequiresReviewSync, warnInvalidReturnSync, warnMissingReturnSync, warnNestedInternalTComponent, warnNestedTComponent, warnNonStaticExpressionSync, warnNonStringSync, warnRecursiveFunctionCallSync, warnSyncGetGT, warnTemplateLiteralSync, warnTernarySync, warnUnresolvedImportSync, warnVariablePropSync, withLocation, withOriginalError, xcstringsSourceLanguageMismatchError };
|
|
66
64
|
|
|
67
65
|
//# sourceMappingURL=index.js.map
|