@intlayer/cli 5.8.1-canary.0 → 6.0.0-canary.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/dist/cjs/IntlayerEventListener.cjs +240 -0
- package/dist/cjs/IntlayerEventListener.cjs.map +1 -0
- package/dist/cjs/cli.cjs +29 -7
- package/dist/cjs/cli.cjs.map +1 -1
- package/dist/cjs/config.cjs +5 -1
- package/dist/cjs/config.cjs.map +1 -1
- package/dist/cjs/fill/autoFill.cjs +105 -0
- package/dist/cjs/fill/autoFill.cjs.map +1 -0
- package/dist/cjs/fill/formatAutoFillData.cjs +108 -0
- package/dist/cjs/fill/formatAutoFillData.cjs.map +1 -0
- package/dist/cjs/fill/formatAutoFilledFilePath.cjs +46 -0
- package/dist/cjs/fill/formatAutoFilledFilePath.cjs.map +1 -0
- package/dist/cjs/fill/getTargetDictionary.cjs +86 -0
- package/dist/cjs/fill/getTargetDictionary.cjs.map +1 -0
- package/dist/cjs/fill/index.cjs +257 -0
- package/dist/cjs/fill/index.cjs.map +1 -0
- package/dist/cjs/index.cjs +4 -2
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/listContentDeclaration.cjs +37 -19
- package/dist/cjs/listContentDeclaration.cjs.map +1 -1
- package/dist/cjs/liveSync.cjs +254 -0
- package/dist/cjs/liveSync.cjs.map +1 -0
- package/dist/cjs/pull.cjs +18 -22
- package/dist/cjs/pull.cjs.map +1 -1
- package/dist/cjs/push.cjs +28 -27
- package/dist/cjs/push.cjs.map +1 -1
- package/dist/cjs/pushConfig.cjs +8 -15
- package/dist/cjs/pushConfig.cjs.map +1 -1
- package/dist/cjs/reviewDoc.cjs +43 -26
- package/dist/cjs/reviewDoc.cjs.map +1 -1
- package/dist/cjs/test/index.cjs +91 -0
- package/dist/cjs/test/index.cjs.map +1 -0
- package/dist/cjs/test/listMissingTranslations.cjs +73 -0
- package/dist/cjs/test/listMissingTranslations.cjs.map +1 -0
- package/dist/cjs/translateDoc.cjs +40 -24
- package/dist/cjs/translateDoc.cjs.map +1 -1
- package/dist/cjs/utils/checkAIAccess.cjs +5 -1
- package/dist/cjs/utils/checkAIAccess.cjs.map +1 -1
- package/dist/esm/IntlayerEventListener.mjs +206 -0
- package/dist/esm/IntlayerEventListener.mjs.map +1 -0
- package/dist/esm/cli.mjs +26 -4
- package/dist/esm/cli.mjs.map +1 -1
- package/dist/esm/config.mjs +5 -1
- package/dist/esm/config.mjs.map +1 -1
- package/dist/esm/fill/autoFill.mjs +92 -0
- package/dist/esm/fill/autoFill.mjs.map +1 -0
- package/dist/esm/fill/formatAutoFillData.mjs +84 -0
- package/dist/esm/fill/formatAutoFillData.mjs.map +1 -0
- package/dist/esm/fill/formatAutoFilledFilePath.mjs +22 -0
- package/dist/esm/fill/formatAutoFilledFilePath.mjs.map +1 -0
- package/dist/esm/fill/getTargetDictionary.mjs +51 -0
- package/dist/esm/fill/getTargetDictionary.mjs.map +1 -0
- package/dist/esm/fill/index.mjs +240 -0
- package/dist/esm/fill/index.mjs.map +1 -0
- package/dist/esm/index.mjs +2 -1
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/listContentDeclaration.mjs +38 -17
- package/dist/esm/listContentDeclaration.mjs.map +1 -1
- package/dist/esm/liveSync.mjs +220 -0
- package/dist/esm/liveSync.mjs.map +1 -0
- package/dist/esm/pull.mjs +19 -21
- package/dist/esm/pull.mjs.map +1 -1
- package/dist/esm/push.mjs +33 -27
- package/dist/esm/push.mjs.map +1 -1
- package/dist/esm/pushConfig.mjs +8 -15
- package/dist/esm/pushConfig.mjs.map +1 -1
- package/dist/esm/reviewDoc.mjs +53 -28
- package/dist/esm/reviewDoc.mjs.map +1 -1
- package/dist/esm/test/index.mjs +74 -0
- package/dist/esm/test/index.mjs.map +1 -0
- package/dist/esm/test/listMissingTranslations.mjs +41 -0
- package/dist/esm/test/listMissingTranslations.mjs.map +1 -0
- package/dist/esm/translateDoc.mjs +50 -27
- package/dist/esm/translateDoc.mjs.map +1 -1
- package/dist/esm/utils/checkAIAccess.mjs +5 -1
- package/dist/esm/utils/checkAIAccess.mjs.map +1 -1
- package/dist/types/IntlayerEventListener.d.ts +85 -0
- package/dist/types/IntlayerEventListener.d.ts.map +1 -0
- package/dist/types/cli.d.ts.map +1 -1
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/fill/autoFill.d.ts +4 -0
- package/dist/types/fill/autoFill.d.ts.map +1 -0
- package/dist/types/fill/formatAutoFillData.d.ts +9 -0
- package/dist/types/fill/formatAutoFillData.d.ts.map +1 -0
- package/dist/types/fill/formatAutoFilledFilePath.d.ts +3 -0
- package/dist/types/fill/formatAutoFilledFilePath.d.ts.map +1 -0
- package/dist/types/fill/getTargetDictionary.d.ts +4 -0
- package/dist/types/fill/getTargetDictionary.d.ts.map +1 -0
- package/dist/types/{fill.d.ts → fill/index.d.ts} +2 -5
- package/dist/types/fill/index.d.ts.map +1 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/listContentDeclaration.d.ts +4 -5
- package/dist/types/listContentDeclaration.d.ts.map +1 -1
- package/dist/types/liveSync.d.ts +6 -0
- package/dist/types/liveSync.d.ts.map +1 -0
- package/dist/types/pull.d.ts.map +1 -1
- package/dist/types/push.d.ts +1 -1
- package/dist/types/push.d.ts.map +1 -1
- package/dist/types/pushConfig.d.ts +0 -1
- package/dist/types/pushConfig.d.ts.map +1 -1
- package/dist/types/reviewDoc.d.ts.map +1 -1
- package/dist/types/test/index.d.ts +8 -0
- package/dist/types/test/index.d.ts.map +1 -0
- package/dist/types/test/listMissingTranslations.d.ts +12 -0
- package/dist/types/test/listMissingTranslations.d.ts.map +1 -0
- package/dist/types/translateDoc.d.ts.map +1 -1
- package/dist/types/utils/checkAIAccess.d.ts.map +1 -1
- package/package.json +17 -15
- package/dist/cjs/fill.cjs +0 -405
- package/dist/cjs/fill.cjs.map +0 -1
- package/dist/esm/fill.mjs +0 -385
- package/dist/esm/fill.mjs.map +0 -1
- package/dist/types/fill.d.ts.map +0 -1
package/dist/cjs/push.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/push.ts"],"sourcesContent":["import { getDictionaryAPI, getOAuthAPI } from '@intlayer/api';\nimport { listGitFiles, ListGitFilesOptions } from '@intlayer/chokidar';\nimport {\n getAppLogger,\n getConfiguration,\n GetConfigurationOptions,\n} from '@intlayer/config';\nimport type { Dictionary } from '@intlayer/core';\nimport dictionariesRecord from '@intlayer/dictionaries-entry';\nimport * as fsPromises from 'fs/promises';\nimport pLimit from 'p-limit';\nimport { relative } from 'path';\nimport * as readline from 'readline';\n\ntype PushOptions = {\n deleteLocaleDictionary?: boolean;\n keepLocaleDictionary?: boolean;\n dictionaries?: string[];\n gitOptions?: ListGitFilesOptions;\n configOptions?: GetConfigurationOptions;\n};\n\ntype DictionariesStatus = {\n dictionary: Dictionary;\n status: 'pending' | 'pushing' | 'modified' | 'pushed' | 'unknown' | 'error';\n icon: string;\n index: number;\n error?: Error;\n errorMessage?: string;\n spinnerFrameIndex?: number;\n};\n\nconst spinnerFrames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];\n\nconst RESET = '\\x1b[0m';\nconst GREEN = '\\x1b[32m';\nconst RED = '\\x1b[31m';\nconst BLUE = '\\x1b[34m';\nconst GREY = '\\x1b[90m';\nconst GREY_DARK = '\\x1b[90m';\n\n/**\n * Get all locale dictionaries and push them simultaneously.\n */\nexport const push = async (options?: PushOptions): Promise<void> => {\n const config = getConfiguration(options?.configOptions);\n const appLogger = getAppLogger(config);\n const { clientId, clientSecret } = config.editor;\n try {\n if (!clientId || !clientSecret) {\n throw new Error(\n 'Missing OAuth2 client ID or client secret. To get access token go to https://intlayer.org/dashboard/project.'\n );\n }\n\n const intlayerAuthAPI = getOAuthAPI(config);\n const oAuth2TokenResult = await intlayerAuthAPI.getOAuth2AccessToken();\n\n const oAuth2AccessToken = oAuth2TokenResult.data?.accessToken;\n\n let dictionaries: Dictionary[] = Object.values(dictionariesRecord);\n const existingDictionariesKeys: string[] = Object.keys(dictionariesRecord);\n\n if (options?.dictionaries) {\n // Check if the provided dictionaries exist\n const noneExistingDictionariesOption = options.dictionaries.filter(\n (dictionaryId) => !existingDictionariesKeys.includes(dictionaryId)\n );\n\n if (noneExistingDictionariesOption.length > 0) {\n appLogger(\n `The following dictionaries do not exist: ${noneExistingDictionariesOption.join(\n ', '\n )} and have been ignored.`,\n {\n level: 'error',\n }\n );\n }\n\n // Filter the dictionaries from the provided list of IDs\n dictionaries = dictionaries.filter((dictionary) =>\n options.dictionaries!.includes(dictionary.key)\n );\n }\n\n if (options?.gitOptions) {\n const gitFiles = await listGitFiles(options.gitOptions);\n }\n\n // Check if the dictionaries list is empty\n if (dictionaries.length === 0) {\n appLogger('No local dictionaries found', {\n level: 'error',\n });\n return;\n }\n\n appLogger('Pushing dictionaries:', {});\n\n // Prepare dictionaries statuses\n const dictionariesStatuses: DictionariesStatus[] = dictionaries.map(\n (dictionary, index) => ({\n dictionary,\n icon: getStatusIcon('pending'),\n status: 'pending',\n index,\n spinnerFrameIndex: 0,\n })\n );\n\n // Output initial statuses\n for (const statusObj of dictionariesStatuses) {\n process.stdout.write(getStatusLine(statusObj) + '\\n');\n }\n\n const successfullyPushedDictionaries: Dictionary[] = [];\n\n // Start spinner timer\n const spinnerTimer = setInterval(() => {\n updateAllStatusLines(dictionariesStatuses);\n }, 100); // Update every 100ms\n\n const processDictionary = async (\n statusObj: DictionariesStatus\n ): Promise<void> => {\n statusObj.status = 'pushing';\n\n try {\n const intlayerDictionaryAPI = getDictionaryAPI(undefined, config);\n const pushResult = await intlayerDictionaryAPI.pushDictionaries(\n [statusObj.dictionary],\n {\n headers: {\n Authorization: `Bearer ${oAuth2AccessToken}`,\n },\n }\n );\n\n const updatedDictionaries = pushResult.data?.updatedDictionaries || [];\n const newDictionaries = pushResult.data?.newDictionaries || [];\n\n if (updatedDictionaries.includes(statusObj.dictionary.key)) {\n statusObj.status = 'modified';\n successfullyPushedDictionaries.push(statusObj.dictionary);\n } else if (newDictionaries.includes(statusObj.dictionary.key)) {\n statusObj.status = 'pushed';\n successfullyPushedDictionaries.push(statusObj.dictionary);\n } else {\n statusObj.status = 'unknown';\n }\n } catch (error) {\n statusObj.status = 'error';\n statusObj.error = error as Error;\n statusObj.errorMessage = `Error pushing dictionary ${statusObj.dictionary.key}: ${error}`;\n }\n };\n\n // Process dictionaries in parallel with a concurrency limit\n const limit = pLimit(5); // Limit the number of concurrent requests\n const pushPromises = dictionariesStatuses.map((statusObj) =>\n limit(() => processDictionary(statusObj))\n );\n await Promise.all(pushPromises);\n\n // Stop the spinner timer\n clearInterval(spinnerTimer);\n\n // Update statuses one last time\n updateAllStatusLines(dictionariesStatuses);\n\n // Output any error messages\n for (const statusObj of dictionariesStatuses) {\n if (statusObj.errorMessage) {\n appLogger(statusObj.errorMessage, {\n level: 'error',\n });\n }\n }\n\n // Handle delete or keep options\n const deleteOption = options?.deleteLocaleDictionary;\n const keepOption = options?.keepLocaleDictionary;\n\n if (deleteOption && keepOption) {\n throw new Error(\n 'Cannot specify both --deleteLocaleDictionary and --keepLocaleDictionary options.'\n );\n }\n\n if (deleteOption) {\n // Delete only the successfully pushed dictionaries\n await deleteLocalDictionaries(successfullyPushedDictionaries, options);\n } else if (keepOption) {\n // Do nothing, keep the local dictionaries\n } else {\n // Ask the user\n const answer = await askUser(\n 'Do you want to delete the local dictionaries that were successfully pushed? (yes/no): '\n );\n if (answer.toLowerCase() === 'yes' || answer.toLowerCase() === 'y') {\n await deleteLocalDictionaries(successfullyPushedDictionaries, options);\n }\n }\n } catch (error) {\n appLogger(error, {\n level: 'error',\n });\n }\n};\n\nconst askUser = (question: string): Promise<string> => {\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n return new Promise((resolve) => {\n rl.question(question, (answer: string) => {\n rl.close();\n resolve(answer);\n });\n });\n};\n\nconst deleteLocalDictionaries = async (\n dictionariesToDelete: Dictionary[],\n options?: PushOptions\n): Promise<void> => {\n const config = getConfiguration(options?.configOptions);\n const appLogger = getAppLogger(config);\n const { baseDir } = config.content;\n\n // Use a Set to collect all unique file paths\n const filePathsSet: Set<string> = new Set();\n\n for (const dictionary of dictionariesToDelete) {\n const { filePath } = dictionary;\n\n if (!filePath) {\n appLogger(`Dictionary ${dictionary.key} does not have a file path`, {\n level: 'error',\n });\n continue;\n }\n\n filePathsSet.add(filePath);\n }\n\n for (const filePath of filePathsSet) {\n const relativePath = relative(baseDir, filePath);\n\n try {\n const stats = await fsPromises.lstat(filePath);\n\n if (stats.isFile()) {\n await fsPromises.unlink(filePath);\n appLogger(`Deleted file ${relativePath}`, {});\n } else if (stats.isDirectory()) {\n appLogger(`Path is a directory ${relativePath}, skipping.`, {});\n } else {\n appLogger(`Unknown file type for ${relativePath}, skipping.`, {});\n }\n } catch (err) {\n appLogger(`Error deleting ${relativePath}: ${err}`, {\n level: 'error',\n });\n }\n }\n};\n\nconst getStatusIcon = (status: string): string => {\n const statusIcons: Record<string, string> = {\n pending: '⏲',\n pushing: '', // Spinner handled separately\n modified: '✔',\n pushed: '✔',\n error: '✖',\n };\n return statusIcons[status] || '';\n};\n\nconst getStatusLine = (statusObj: DictionariesStatus): string => {\n let icon = getStatusIcon(statusObj.status);\n let colorStart = '';\n let colorEnd = '';\n\n if (statusObj.status === 'pushing') {\n // Use spinner frame\n icon = spinnerFrames[statusObj.spinnerFrameIndex! % spinnerFrames.length];\n colorStart = BLUE;\n colorEnd = RESET;\n } else if (statusObj.status === 'error') {\n colorStart = RED;\n colorEnd = RESET;\n } else if (statusObj.status === 'pushed' || statusObj.status === 'modified') {\n colorStart = GREEN;\n colorEnd = RESET;\n } else {\n colorStart = GREY;\n colorEnd = RESET;\n }\n\n return `- ${statusObj.dictionary.key} ${GREY_DARK}[${colorStart}${icon}${statusObj.status}${GREY_DARK}]${colorEnd}`;\n};\n\nconst updateAllStatusLines = (dictionariesStatuses: DictionariesStatus[]) => {\n // Move cursor up to the first status line\n readline.moveCursor(process.stdout, 0, -dictionariesStatuses.length);\n for (const statusObj of dictionariesStatuses) {\n // Clear the line\n readline.clearLine(process.stdout, 0);\n\n if (statusObj.status === 'pushing') {\n // Update spinner frame\n statusObj.spinnerFrameIndex =\n (statusObj.spinnerFrameIndex! + 1) % spinnerFrames.length;\n }\n\n // Write the status line\n process.stdout.write(getStatusLine(statusObj) + '\\n');\n }\n};\n"],"mappings":"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","names":["dictionariesRecord","pLimit"]}
|
|
1
|
+
{"version":3,"sources":["../../src/push.ts"],"sourcesContent":["import { getDictionaryAPI, getOAuthAPI } from '@intlayer/api';\nimport {\n formatPath,\n listGitFiles,\n ListGitFilesOptions,\n} from '@intlayer/chokidar';\nimport {\n ANSIColors,\n getAppLogger,\n getConfiguration,\n GetConfigurationOptions,\n spinnerFrames,\n} from '@intlayer/config';\nimport type { Dictionary } from '@intlayer/core';\nimport dictionariesRecord from '@intlayer/dictionaries-entry';\nimport * as fsPromises from 'fs/promises';\nimport pLimit from 'p-limit';\nimport * as readline from 'readline';\n\ntype PushOptions = {\n deleteLocaleDictionary?: boolean;\n keepLocaleDictionary?: boolean;\n dictionaries?: string[];\n gitOptions?: ListGitFilesOptions;\n configOptions?: GetConfigurationOptions;\n};\n\ntype DictionariesStatus = {\n dictionary: Dictionary;\n status: 'pending' | 'pushing' | 'modified' | 'pushed' | 'unknown' | 'error';\n icon: string;\n index: number;\n error?: Error;\n errorMessage?: string;\n spinnerFrameIndex?: number;\n};\n\n/**\n * Get all local dictionaries and push them simultaneously.\n */\nexport const push = async (options?: PushOptions): Promise<void> => {\n const config = getConfiguration(options?.configOptions);\n const appLogger = getAppLogger(config, {\n config: {\n prefix: '',\n },\n });\n const { clientId, clientSecret } = config.editor;\n try {\n if (!clientId || !clientSecret) {\n throw new Error(\n 'Missing OAuth2 client ID or client secret. To get access token go to https://intlayer.org/dashboard/project.'\n );\n }\n\n const intlayerAuthAPI = getOAuthAPI(config);\n const oAuth2TokenResult = await intlayerAuthAPI.getOAuth2AccessToken();\n\n const oAuth2AccessToken = oAuth2TokenResult.data?.accessToken;\n\n let dictionaries: Dictionary[] = Object.values(dictionariesRecord);\n const existingDictionariesKeys: string[] = Object.keys(dictionariesRecord);\n\n if (options?.dictionaries) {\n // Check if the provided dictionaries exist\n const noneExistingDictionariesOption = options.dictionaries.filter(\n (dictionaryId) => !existingDictionariesKeys.includes(dictionaryId)\n );\n\n if (noneExistingDictionariesOption.length > 0) {\n appLogger(\n `The following dictionaries do not exist: ${noneExistingDictionariesOption.join(\n ', '\n )} and have been ignored.`,\n {\n level: 'error',\n }\n );\n }\n\n // Filter the dictionaries from the provided list of IDs\n dictionaries = dictionaries.filter((dictionary) =>\n options.dictionaries!.includes(dictionary.key)\n );\n }\n\n if (options?.gitOptions) {\n const gitFiles = await listGitFiles(options.gitOptions);\n }\n\n // Check if the dictionaries list is empty\n if (dictionaries.length === 0) {\n appLogger('No local dictionaries found', {\n level: 'error',\n });\n return;\n }\n\n appLogger('Pushing dictionaries:', {});\n\n // Prepare dictionaries statuses\n const dictionariesStatuses: DictionariesStatus[] = dictionaries.map(\n (dictionary, index) => ({\n dictionary,\n icon: getStatusIcon('pending'),\n status: 'pending',\n index,\n spinnerFrameIndex: 0,\n })\n );\n\n // Output initial statuses\n for (const statusObj of dictionariesStatuses) {\n process.stdout.write(getStatusLine(statusObj) + '\\n');\n }\n\n const successfullyPushedDictionaries: Dictionary[] = [];\n\n // Start spinner timer\n const spinnerTimer = setInterval(() => {\n updateAllStatusLines(dictionariesStatuses);\n }, 100); // Update every 100ms\n\n const processDictionary = async (\n statusObj: DictionariesStatus\n ): Promise<void> => {\n statusObj.status = 'pushing';\n\n try {\n const intlayerDictionaryAPI = getDictionaryAPI(undefined, config);\n const pushResult = await intlayerDictionaryAPI.pushDictionaries(\n [statusObj.dictionary],\n {\n headers: {\n Authorization: `Bearer ${oAuth2AccessToken}`,\n },\n }\n );\n\n const updatedDictionaries = pushResult.data?.updatedDictionaries || [];\n const newDictionaries = pushResult.data?.newDictionaries || [];\n\n if (updatedDictionaries.includes(statusObj.dictionary.key)) {\n statusObj.status = 'modified';\n successfullyPushedDictionaries.push(statusObj.dictionary);\n } else if (newDictionaries.includes(statusObj.dictionary.key)) {\n statusObj.status = 'pushed';\n successfullyPushedDictionaries.push(statusObj.dictionary);\n } else {\n statusObj.status = 'unknown';\n }\n } catch (error) {\n statusObj.status = 'error';\n statusObj.error = error as Error;\n statusObj.errorMessage = `Error pushing dictionary ${statusObj.dictionary.key}: ${error}`;\n }\n };\n\n // Process dictionaries in parallel with a concurrency limit\n const limit = pLimit(5); // Limit the number of concurrent requests\n const pushPromises = dictionariesStatuses.map((statusObj) =>\n limit(() => processDictionary(statusObj))\n );\n await Promise.all(pushPromises);\n\n // Stop the spinner timer\n clearInterval(spinnerTimer);\n\n // Update statuses one last time\n updateAllStatusLines(dictionariesStatuses);\n\n // Output any error messages\n for (const statusObj of dictionariesStatuses) {\n if (statusObj.errorMessage) {\n appLogger(statusObj.errorMessage, {\n level: 'error',\n });\n }\n }\n\n // Handle delete or keep options\n const deleteOption = options?.deleteLocaleDictionary;\n const keepOption = options?.keepLocaleDictionary;\n\n if (deleteOption && keepOption) {\n throw new Error(\n 'Cannot specify both --deleteLocaleDictionary and --keepLocaleDictionary options.'\n );\n }\n\n if (deleteOption) {\n // Delete only the successfully pushed dictionaries\n await deleteLocalDictionaries(successfullyPushedDictionaries, options);\n } else if (keepOption) {\n // Do nothing, keep the local dictionaries\n } else {\n // Ask the user\n const answer = await askUser(\n 'Do you want to delete the local dictionaries that were successfully pushed? (yes/no): '\n );\n if (answer.toLowerCase() === 'yes' || answer.toLowerCase() === 'y') {\n await deleteLocalDictionaries(successfullyPushedDictionaries, options);\n }\n }\n } catch (error) {\n appLogger(error, {\n level: 'error',\n });\n }\n};\n\nconst askUser = (question: string): Promise<string> => {\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n return new Promise((resolve) => {\n rl.question(question, (answer: string) => {\n rl.close();\n resolve(answer);\n });\n });\n};\n\nconst deleteLocalDictionaries = async (\n dictionariesToDelete: Dictionary[],\n options?: PushOptions\n): Promise<void> => {\n const config = getConfiguration(options?.configOptions);\n const appLogger = getAppLogger(config, {\n config: {\n prefix: '',\n },\n });\n\n // Use a Set to collect all unique file paths\n const filePathsSet: Set<string> = new Set();\n\n for (const dictionary of dictionariesToDelete) {\n const { filePath } = dictionary;\n\n if (!filePath) {\n appLogger(`Dictionary ${dictionary.key} does not have a file path`, {\n level: 'error',\n });\n continue;\n }\n\n filePathsSet.add(filePath);\n }\n\n for (const filePath of filePathsSet) {\n try {\n const stats = await fsPromises.lstat(filePath);\n\n if (stats.isFile()) {\n await fsPromises.unlink(filePath);\n appLogger(`Deleted file ${formatPath(filePath)}`, {});\n } else if (stats.isDirectory()) {\n appLogger(`Path is a directory ${formatPath(filePath)}, skipping.`, {});\n } else {\n appLogger(\n `Unknown file type for ${formatPath(filePath)}, skipping.`,\n {}\n );\n }\n } catch (err) {\n appLogger(`Error deleting ${formatPath(filePath)}: ${err}`, {\n level: 'error',\n });\n }\n }\n};\n\nconst getStatusIcon = (status: string): string => {\n const statusIcons: Record<string, string> = {\n pending: '⏲',\n pushing: '', // Spinner handled separately\n modified: '✔',\n pushed: '✔',\n error: '✖',\n };\n return statusIcons[status] || '';\n};\n\nconst getStatusLine = (statusObj: DictionariesStatus): string => {\n let icon = getStatusIcon(statusObj.status);\n let colorStart = '';\n let colorEnd = '';\n\n if (statusObj.status === 'pushing') {\n // Use spinner frame\n icon = spinnerFrames[statusObj.spinnerFrameIndex! % spinnerFrames.length];\n colorStart = ANSIColors.BLUE;\n colorEnd = ANSIColors.RESET;\n } else if (statusObj.status === 'error') {\n colorStart = ANSIColors.RED;\n colorEnd = ANSIColors.RESET;\n } else if (statusObj.status === 'pushed' || statusObj.status === 'modified') {\n colorStart = ANSIColors.GREEN;\n colorEnd = ANSIColors.RESET;\n } else {\n colorStart = ANSIColors.GREY;\n colorEnd = ANSIColors.RESET;\n }\n\n return `- ${statusObj.dictionary.key} ${ANSIColors.GREY_DARK}[${colorStart}${icon}${statusObj.status}${ANSIColors.GREY_DARK}]${colorEnd}`;\n};\n\nconst updateAllStatusLines = (dictionariesStatuses: DictionariesStatus[]) => {\n // Move cursor up to the first status line\n readline.moveCursor(process.stdout, 0, -dictionariesStatuses.length);\n for (const statusObj of dictionariesStatuses) {\n // Clear the line\n readline.clearLine(process.stdout, 0);\n\n if (statusObj.status === 'pushing') {\n // Update spinner frame\n statusObj.spinnerFrameIndex =\n (statusObj.spinnerFrameIndex! + 1) % spinnerFrames.length;\n }\n\n // Write the status line\n process.stdout.write(getStatusLine(statusObj) + '\\n');\n }\n};\n"],"mappings":"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","names":["dictionariesRecord","pLimit"]}
|
package/dist/cjs/pushConfig.cjs
CHANGED
|
@@ -25,16 +25,17 @@ var import_api = require("@intlayer/api");
|
|
|
25
25
|
var import_config = require("@intlayer/config");
|
|
26
26
|
const pushConfig = async (options) => {
|
|
27
27
|
const config = (0, import_config.getConfiguration)(options?.configOptions);
|
|
28
|
-
const appLogger = (0, import_config.getAppLogger)(config
|
|
28
|
+
const appLogger = (0, import_config.getAppLogger)(config, {
|
|
29
|
+
config: {
|
|
30
|
+
prefix: ""
|
|
31
|
+
}
|
|
32
|
+
});
|
|
29
33
|
const { clientId, clientSecret } = config.editor;
|
|
30
34
|
if (!clientId || !clientSecret) {
|
|
31
35
|
appLogger(
|
|
32
36
|
"Missing OAuth2 client ID or client secret. To get access token go to https://intlayer.org/dashboard/project.",
|
|
33
37
|
{
|
|
34
|
-
level: "error"
|
|
35
|
-
config: {
|
|
36
|
-
prefix: options?.logPrefix
|
|
37
|
-
}
|
|
38
|
+
level: "error"
|
|
38
39
|
}
|
|
39
40
|
);
|
|
40
41
|
return;
|
|
@@ -52,16 +53,8 @@ const pushConfig = async (options) => {
|
|
|
52
53
|
if (!getDictionariesKeysResult.data) {
|
|
53
54
|
throw new Error("Error pushing project configuration");
|
|
54
55
|
}
|
|
55
|
-
appLogger("Project configuration pushed successfully"
|
|
56
|
-
|
|
57
|
-
prefix: options?.logPrefix
|
|
58
|
-
}
|
|
59
|
-
});
|
|
60
|
-
appLogger(JSON.stringify(getDictionariesKeysResult.data, null, 2), {
|
|
61
|
-
config: {
|
|
62
|
-
prefix: options?.logPrefix
|
|
63
|
-
}
|
|
64
|
-
});
|
|
56
|
+
appLogger("Project configuration pushed successfully");
|
|
57
|
+
appLogger(JSON.stringify(getDictionariesKeysResult.data, null, 2));
|
|
65
58
|
};
|
|
66
59
|
// Annotate the CommonJS export names for ESM import in node:
|
|
67
60
|
0 && (module.exports = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/pushConfig.ts"],"sourcesContent":["import { getIntlayerAPI } from '@intlayer/api';\nimport {\n getAppLogger,\n getConfiguration,\n type GetConfigurationOptions,\n} from '@intlayer/config';\n\ntype PushOptions = {\n
|
|
1
|
+
{"version":3,"sources":["../../src/pushConfig.ts"],"sourcesContent":["import { getIntlayerAPI } from '@intlayer/api';\nimport {\n getAppLogger,\n getConfiguration,\n type GetConfigurationOptions,\n} from '@intlayer/config';\n\ntype PushOptions = {\n configOptions?: GetConfigurationOptions;\n};\n\nexport const pushConfig = async (options?: PushOptions) => {\n const config = getConfiguration(options?.configOptions);\n const appLogger = getAppLogger(config, {\n config: {\n prefix: '',\n },\n });\n\n const { clientId, clientSecret } = config.editor;\n\n if (!clientId || !clientSecret) {\n appLogger(\n 'Missing OAuth2 client ID or client secret. To get access token go to https://intlayer.org/dashboard/project.',\n {\n level: 'error',\n }\n );\n return;\n }\n\n const intlayerAPI = getIntlayerAPI(undefined, config);\n\n const oAuth2TokenResult = await intlayerAPI.oAuth.getOAuth2AccessToken();\n\n const oAuth2AccessToken = oAuth2TokenResult.data?.accessToken;\n\n // Get the list of dictionary keys\n const getDictionariesKeysResult =\n await intlayerAPI.project.pushProjectConfiguration(config, {\n ...(oAuth2AccessToken && {\n headers: {\n Authorization: `Bearer ${oAuth2AccessToken}`,\n },\n }),\n });\n\n if (!getDictionariesKeysResult.data) {\n throw new Error('Error pushing project configuration');\n }\n\n appLogger('Project configuration pushed successfully');\n\n appLogger(JSON.stringify(getDictionariesKeysResult.data, null, 2));\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iBAA+B;AAC/B,oBAIO;AAMA,MAAM,aAAa,OAAO,YAA0B;AACzD,QAAM,aAAS,gCAAiB,SAAS,aAAa;AACtD,QAAM,gBAAY,4BAAa,QAAQ;AAAA,IACrC,QAAQ;AAAA,MACN,QAAQ;AAAA,IACV;AAAA,EACF,CAAC;AAED,QAAM,EAAE,UAAU,aAAa,IAAI,OAAO;AAE1C,MAAI,CAAC,YAAY,CAAC,cAAc;AAC9B;AAAA,MACE;AAAA,MACA;AAAA,QACE,OAAO;AAAA,MACT;AAAA,IACF;AACA;AAAA,EACF;AAEA,QAAM,kBAAc,2BAAe,QAAW,MAAM;AAEpD,QAAM,oBAAoB,MAAM,YAAY,MAAM,qBAAqB;AAEvE,QAAM,oBAAoB,kBAAkB,MAAM;AAGlD,QAAM,4BACJ,MAAM,YAAY,QAAQ,yBAAyB,QAAQ;AAAA,IACzD,GAAI,qBAAqB;AAAA,MACvB,SAAS;AAAA,QACP,eAAe,UAAU,iBAAiB;AAAA,MAC5C;AAAA,IACF;AAAA,EACF,CAAC;AAEH,MAAI,CAAC,0BAA0B,MAAM;AACnC,UAAM,IAAI,MAAM,qCAAqC;AAAA,EACvD;AAEA,YAAU,2CAA2C;AAErD,YAAU,KAAK,UAAU,0BAA0B,MAAM,MAAM,CAAC,CAAC;AACnE;","names":[]}
|
package/dist/cjs/reviewDoc.cjs
CHANGED
|
@@ -55,20 +55,30 @@ const dir = isESModule ? (0, import_path.dirname)((0, import_url.fileURLToPath)(
|
|
|
55
55
|
const reviewFile = async (baseFilePath, outputFilePath, locale, baseLocale, aiOptions, configOptions, oAuth2AccessToken, customInstructions, changedLines) => {
|
|
56
56
|
try {
|
|
57
57
|
const configuration = (0, import_config.getConfiguration)(configOptions);
|
|
58
|
-
const appLogger = (0, import_config.getAppLogger)(configuration
|
|
58
|
+
const appLogger = (0, import_config.getAppLogger)(configuration, {
|
|
59
|
+
config: {
|
|
60
|
+
prefix: ""
|
|
61
|
+
}
|
|
62
|
+
});
|
|
59
63
|
const basedFileContent = await (0, import_promises.readFile)(baseFilePath, "utf-8");
|
|
60
64
|
const fileToReviewContent = await (0, import_promises.readFile)(outputFilePath, "utf-8");
|
|
61
65
|
let updatedFileContent = fileToReviewContent;
|
|
62
66
|
let fileResultContent = "";
|
|
63
|
-
const basePrompt = (await (0, import_promises.readFile)((0, import_path.join)(dir, "./prompts/REVIEW_PROMPT.md"), "utf-8")).replaceAll(
|
|
64
|
-
"{{localeName}}",
|
|
65
|
-
`${(0, import_core.getLocaleName)(locale, import_config.Locales.ENGLISH)} (${locale})`
|
|
66
|
-
).replaceAll(
|
|
67
|
-
"{{baseLocaleName}}",
|
|
68
|
-
`${(0, import_core.getLocaleName)(baseLocale, import_config.Locales.ENGLISH)} (${baseLocale})`
|
|
69
|
-
).replace("{{applicationContext}}", aiOptions?.applicationContext ?? "-").replace("{{customInstructions}}", customInstructions ?? "-");
|
|
67
|
+
const basePrompt = (await (0, import_promises.readFile)((0, import_path.join)(dir, "./prompts/REVIEW_PROMPT.md"), "utf-8")).replaceAll("{{localeName}}", `${(0, import_chokidar.formatLocale)(locale, false)}`).replaceAll("{{baseLocaleName}}", `${(0, import_chokidar.formatLocale)(baseLocale, false)}`).replace("{{applicationContext}}", aiOptions?.applicationContext ?? "-").replace("{{customInstructions}}", customInstructions ?? "-");
|
|
70
68
|
const baseChunks = (0, import_calculateChunks.chunkText)(basedFileContent, 800, 0);
|
|
71
|
-
|
|
69
|
+
const filePrexixText = `${import_config.ANSIColors.GREY_DARK}[${(0, import_chokidar.formatPath)(baseFilePath)}${import_config.ANSIColors.GREY_DARK}] `;
|
|
70
|
+
const filePrefix = [
|
|
71
|
+
(0, import_config.colon)(filePrexixText, { colSize: 40 }),
|
|
72
|
+
`\u2192 ${import_config.ANSIColors.RESET}`
|
|
73
|
+
].join("");
|
|
74
|
+
const prefixText = `${import_config.ANSIColors.GREY_DARK}[${(0, import_chokidar.formatPath)(baseFilePath)}${import_config.ANSIColors.GREY_DARK}][${(0, import_chokidar.formatLocale)(locale)}${import_config.ANSIColors.GREY_DARK}] `;
|
|
75
|
+
const prefix = [
|
|
76
|
+
(0, import_config.colon)(prefixText, { colSize: 40 }),
|
|
77
|
+
`\u2192 ${import_config.ANSIColors.RESET}`
|
|
78
|
+
].join("");
|
|
79
|
+
appLogger(
|
|
80
|
+
`${filePrefix}Base file splitted into ${(0, import_config.colorizeNumber)(baseChunks.length)} chunks`
|
|
81
|
+
);
|
|
72
82
|
for await (const [i, baseChunk] of baseChunks.entries()) {
|
|
73
83
|
const baseChunkContext = baseChunk;
|
|
74
84
|
if (changedLines) {
|
|
@@ -76,7 +86,9 @@ const reviewFile = async (baseFilePath, outputFilePath, locale, baseLocale, aiOp
|
|
|
76
86
|
(line) => line > baseChunkContext.lineStart && line < baseChunkContext.lineStart + baseChunkContext.lineLength
|
|
77
87
|
);
|
|
78
88
|
if (!hasChangedLinesInChunk) {
|
|
79
|
-
appLogger(
|
|
89
|
+
appLogger(
|
|
90
|
+
`No git changed lines found for chunk ${(0, import_config.colorizeNumber)(i + 1)}`
|
|
91
|
+
);
|
|
80
92
|
const chunkWithNoChange = (0, import_getChunk.getChunk)(updatedFileContent, {
|
|
81
93
|
lineStart: baseChunkContext.lineStart,
|
|
82
94
|
lineLength: baseChunkContext.lineLength
|
|
@@ -85,9 +97,9 @@ const reviewFile = async (baseFilePath, outputFilePath, locale, baseLocale, aiOp
|
|
|
85
97
|
continue;
|
|
86
98
|
}
|
|
87
99
|
}
|
|
88
|
-
const getBaseChunkContextPrompt = () => `**CHUNK ${i + 1} to ${Math.min(i + 3, baseChunks.length)} of ${baseChunks.length}** is the base chunk in ${(0,
|
|
100
|
+
const getBaseChunkContextPrompt = () => `**CHUNK ${i + 1} to ${Math.min(i + 3, baseChunks.length)} of ${baseChunks.length}** is the base chunk in ${(0, import_chokidar.formatLocale)(baseLocale, false)} as reference.
|
|
89
101
|
///chunksStart///` + (baseChunks[i - 1]?.content ?? "") + baseChunkContext.content + (baseChunks[i + 1]?.content ?? "") + `///chunksEnd///`;
|
|
90
|
-
const getChunkToReviewPrompt = () => `**CHUNK ${i + 1} to ${Math.min(i + 3, baseChunks.length)} of ${baseChunks.length}** is the current chunk to review in ${(0,
|
|
102
|
+
const getChunkToReviewPrompt = () => `**CHUNK ${i + 1} to ${Math.min(i + 3, baseChunks.length)} of ${baseChunks.length}** is the current chunk to review in ${(0, import_chokidar.formatLocale)(locale, false)} as reference.
|
|
91
103
|
///chunksStart///` + (0, import_getChunk.getChunk)(updatedFileContent, {
|
|
92
104
|
lineStart: baseChunks[i - 1]?.lineStart ?? 0,
|
|
93
105
|
lineLength: (baseChunks[i - 1]?.lineLength ?? 0) + baseChunkContext.lineLength + (baseChunks[i + 1]?.lineLength ?? 0)
|
|
@@ -100,7 +112,7 @@ const reviewFile = async (baseFilePath, outputFilePath, locale, baseLocale, aiOp
|
|
|
100
112
|
{ role: "system", content: getChunkToReviewPrompt() },
|
|
101
113
|
{
|
|
102
114
|
role: "system",
|
|
103
|
-
content: `The next user message will be the **CHUNK ${i + 1} of ${baseChunks.length}** that should be translated in ${(0, import_core.getLocaleName)(locale, import_config.Locales.ENGLISH)} (${locale}).`
|
|
115
|
+
content: `The next user message will be the **CHUNK ${(0, import_config.colorizeNumber)(i + 1)} of ${(0, import_config.colorizeNumber)(baseChunks.length)}** that should be translated in ${(0, import_core.getLocaleName)(locale, import_config.Locales.ENGLISH)} (${locale}).`
|
|
104
116
|
},
|
|
105
117
|
{ role: "user", content: baseChunkContext.content }
|
|
106
118
|
],
|
|
@@ -108,7 +120,7 @@ const reviewFile = async (baseFilePath, outputFilePath, locale, baseLocale, aiOp
|
|
|
108
120
|
oAuth2AccessToken
|
|
109
121
|
);
|
|
110
122
|
appLogger(
|
|
111
|
-
|
|
123
|
+
`${prefix}${(0, import_config.colorizeNumber)(result.tokenUsed)} tokens used - Chunk ${(0, import_config.colorizeNumber)(i + 1)} of ${(0, import_config.colorizeNumber)(baseChunks.length)}`
|
|
112
124
|
);
|
|
113
125
|
const fixedReviewedChunkResult = (0, import_fixChunkStartEndChars.fixChunkStartEndChars)(
|
|
114
126
|
result?.fileContent,
|
|
@@ -124,7 +136,13 @@ const reviewFile = async (baseFilePath, outputFilePath, locale, baseLocale, aiOp
|
|
|
124
136
|
}
|
|
125
137
|
(0, import_fs.mkdirSync)((0, import_path.dirname)(outputFilePath), { recursive: true });
|
|
126
138
|
(0, import_fs.writeFileSync)(outputFilePath, fileResultContent);
|
|
127
|
-
|
|
139
|
+
const relativePath = (0, import_path.relative)(
|
|
140
|
+
configuration.content.baseDir,
|
|
141
|
+
outputFilePath
|
|
142
|
+
);
|
|
143
|
+
appLogger(
|
|
144
|
+
`${(0, import_config.colorize)("\u2714", import_config.ANSIColors.GREEN)} File ${(0, import_chokidar.formatPath)(relativePath)} created/updated successfully.`
|
|
145
|
+
);
|
|
128
146
|
} catch (error) {
|
|
129
147
|
console.error(error);
|
|
130
148
|
}
|
|
@@ -143,7 +161,11 @@ const reviewDoc = async ({
|
|
|
143
161
|
gitOptions
|
|
144
162
|
}) => {
|
|
145
163
|
const configuration = (0, import_config.getConfiguration)(configOptions);
|
|
146
|
-
const appLogger = (0, import_config.getAppLogger)(configuration
|
|
164
|
+
const appLogger = (0, import_config.getAppLogger)(configuration, {
|
|
165
|
+
config: {
|
|
166
|
+
prefix: ""
|
|
167
|
+
}
|
|
168
|
+
});
|
|
147
169
|
if (nbSimultaneousFileProcessed && nbSimultaneousFileProcessed > 10) {
|
|
148
170
|
appLogger(
|
|
149
171
|
`Warning: nbSimultaneousFileProcessed is set to ${nbSimultaneousFileProcessed}, which is greater than 10. Setting it to 10.`
|
|
@@ -169,23 +191,18 @@ const reviewDoc = async ({
|
|
|
169
191
|
const oAuth2TokenResult = await intlayerAuthAPI.getOAuth2AccessToken();
|
|
170
192
|
oAuth2AccessToken = oAuth2TokenResult.data?.accessToken;
|
|
171
193
|
}
|
|
194
|
+
appLogger(`Base locale is ${(0, import_chokidar.formatLocale)(baseLocale)}`);
|
|
172
195
|
appLogger(
|
|
173
|
-
`
|
|
174
|
-
);
|
|
175
|
-
appLogger(
|
|
176
|
-
`Reviewing ${locales.length} locales: [ ${locales.map((locale) => `${(0, import_core.getLocaleName)(locale, import_config.Locales.ENGLISH)} (${locale})`).join(", ")} ]`
|
|
196
|
+
`Reviewing ${(0, import_config.colorizeNumber)(locales.length)} locales: [ ${(0, import_chokidar.formatLocale)(locales)} ]`
|
|
177
197
|
);
|
|
178
|
-
appLogger(`Reviewing ${docList.length} files:`);
|
|
179
|
-
appLogger(docList.map((path) => ` - ${path}
|
|
198
|
+
appLogger(`Reviewing ${(0, import_config.colorizeNumber)(docList.length)} files:`);
|
|
199
|
+
appLogger(docList.map((path) => ` - ${(0, import_chokidar.formatPath)(path)}
|
|
180
200
|
`));
|
|
181
201
|
const tasks = docList.map(
|
|
182
202
|
(docPath) => locales.flatMap(
|
|
183
203
|
(locale) => limit(async () => {
|
|
184
204
|
appLogger(
|
|
185
|
-
`Reviewing file: ${docPath} to ${(0,
|
|
186
|
-
locale,
|
|
187
|
-
import_config.Locales.ENGLISH
|
|
188
|
-
)} (${locale})`
|
|
205
|
+
`Reviewing file: ${(0, import_chokidar.formatPath)(docPath)} to ${(0, import_chokidar.formatLocale)(locale)}`
|
|
189
206
|
);
|
|
190
207
|
const absoluteBaseFilePath = (0, import_path.join)(
|
|
191
208
|
configuration.content.baseDir,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/reviewDoc.ts"],"sourcesContent":["import { AIOptions, getOAuthAPI } from '@intlayer/api'; // Importing only getAiAPI for now\nimport { listGitFiles, ListGitFilesOptions } from '@intlayer/chokidar';\nimport {\n getAppLogger,\n getConfiguration,\n GetConfigurationOptions,\n Locales,\n retryManager,\n} from '@intlayer/config';\nimport { getLocaleName } from '@intlayer/core';\nimport fg from 'fast-glob';\nimport { mkdirSync, writeFileSync } from 'fs';\nimport { readFile } from 'fs/promises';\nimport pLimit from 'p-limit';\nimport { dirname, join } from 'path';\nimport { fileURLToPath } from 'url';\nimport { chunkText } from './utils/calculateChunks';\nimport { checkAIAccess } from './utils/checkAIAccess';\nimport { checkFileModifiedRange } from './utils/checkFileModifiedRange';\nimport { chunkInference } from './utils/chunkInference';\nimport { fixChunkStartEndChars } from './utils/fixChunkStartEndChars';\nimport { getChunk } from './utils/getChunk';\nimport { getOutputFilePath } from './utils/getOutputFilePath';\n\nconst isESModule = typeof import.meta.url === 'string';\n\nconst dir = isESModule ? dirname(fileURLToPath(import.meta.url)) : __dirname;\n\n/**\n * Translate a single file for a given locale\n */\nexport const reviewFile = async (\n baseFilePath: string,\n outputFilePath: string,\n locale: Locales,\n baseLocale: Locales,\n aiOptions?: AIOptions,\n configOptions?: GetConfigurationOptions,\n oAuth2AccessToken?: string,\n customInstructions?: string,\n changedLines?: number[]\n) => {\n try {\n const configuration = getConfiguration(configOptions);\n const appLogger = getAppLogger(configuration);\n\n const basedFileContent = await readFile(baseFilePath, 'utf-8');\n const fileToReviewContent = await readFile(outputFilePath, 'utf-8');\n\n let updatedFileContent = fileToReviewContent;\n let fileResultContent = '';\n\n // Prepare the base prompt for ChatGPT\n const basePrompt = (\n await readFile(join(dir, './prompts/REVIEW_PROMPT.md'), 'utf-8')\n )\n .replaceAll(\n '{{localeName}}',\n `${getLocaleName(locale, Locales.ENGLISH)} (${locale})`\n )\n .replaceAll(\n '{{baseLocaleName}}',\n `${getLocaleName(baseLocale, Locales.ENGLISH)} (${baseLocale})`\n )\n .replace('{{applicationContext}}', aiOptions?.applicationContext ?? '-')\n .replace('{{customInstructions}}', customInstructions ?? '-');\n\n const baseChunks = chunkText(basedFileContent, 800, 0);\n\n appLogger(` Base file splitted into ${baseChunks.length} chunks`);\n\n for await (const [i, baseChunk] of baseChunks.entries()) {\n const baseChunkContext = baseChunk;\n\n if (changedLines) {\n const hasChangedLinesInChunk = changedLines.some(\n (line) =>\n line > baseChunkContext.lineStart &&\n line < baseChunkContext.lineStart + baseChunkContext.lineLength\n );\n\n if (!hasChangedLinesInChunk) {\n appLogger(`No git changed lines found for chunk ${i + 1}`);\n\n const chunkWithNoChange = getChunk(updatedFileContent, {\n lineStart: baseChunkContext.lineStart,\n lineLength: baseChunkContext.lineLength,\n });\n\n fileResultContent += chunkWithNoChange;\n\n continue;\n }\n }\n\n const getBaseChunkContextPrompt = () =>\n `**CHUNK ${i + 1} to ${Math.min(i + 3, baseChunks.length)} of ${baseChunks.length}** is the base chunk in ${getLocaleName(baseLocale, Locales.ENGLISH)} (${baseLocale}) as reference.\\n` +\n `///chunksStart///` +\n (baseChunks[i - 1]?.content ?? '') +\n baseChunkContext.content +\n (baseChunks[i + 1]?.content ?? '') +\n `///chunksEnd///`;\n\n const getChunkToReviewPrompt = () =>\n `**CHUNK ${i + 1} to ${Math.min(i + 3, baseChunks.length)} of ${baseChunks.length}** is the current chunk to review in ${getLocaleName(locale, Locales.ENGLISH)} (${locale}) as reference.\\n` +\n `///chunksStart///` +\n getChunk(updatedFileContent, {\n lineStart: baseChunks[i - 1]?.lineStart ?? 0,\n lineLength:\n (baseChunks[i - 1]?.lineLength ?? 0) +\n baseChunkContext.lineLength +\n (baseChunks[i + 1]?.lineLength ?? 0),\n }) +\n `///chunksEnd///`;\n\n // Make the actual translation call\n let reviewedChunkResult = await retryManager(async () => {\n const result = await chunkInference(\n [\n { role: 'system', content: basePrompt },\n { role: 'system', content: getBaseChunkContextPrompt() },\n { role: 'system', content: getChunkToReviewPrompt() },\n {\n role: 'system',\n content: `The next user message will be the **CHUNK ${i + 1} of ${baseChunks.length}** that should be translated in ${getLocaleName(locale, Locales.ENGLISH)} (${locale}).`,\n },\n { role: 'user', content: baseChunkContext.content },\n ],\n aiOptions,\n oAuth2AccessToken\n );\n\n appLogger(\n ` -> ${result.tokenUsed} tokens used - CHUNK ${i + 1} of ${baseChunks.length}`\n );\n\n const fixedReviewedChunkResult = fixChunkStartEndChars(\n result?.fileContent,\n baseChunkContext.content\n );\n\n return fixedReviewedChunkResult;\n })();\n\n updatedFileContent = updatedFileContent.replace(\n baseChunkContext.content,\n reviewedChunkResult\n );\n\n fileResultContent += reviewedChunkResult;\n }\n\n mkdirSync(dirname(outputFilePath), { recursive: true });\n writeFileSync(outputFilePath, fileResultContent);\n\n appLogger(` File ${outputFilePath} created/updated successfully.`);\n } catch (error) {\n console.error(error);\n }\n};\n\ntype ReviewDocOptions = {\n docPattern: string[];\n locales: Locales[];\n excludedGlobPattern: string[];\n baseLocale: Locales;\n aiOptions?: AIOptions;\n nbSimultaneousFileProcessed?: number;\n configOptions?: GetConfigurationOptions;\n customInstructions?: string;\n skipIfModifiedBefore?: number | string | Date;\n skipIfModifiedAfter?: number | string | Date;\n gitOptions?: ListGitFilesOptions;\n};\n\n/**\n * Main audit function: scans all .md files in \"en/\" (unless you specified DOC_LIST),\n * then audits them to each locale in LOCALE_LIST.\n */\nexport const reviewDoc = async ({\n docPattern,\n locales,\n excludedGlobPattern,\n baseLocale,\n aiOptions,\n nbSimultaneousFileProcessed,\n configOptions,\n customInstructions,\n skipIfModifiedBefore,\n skipIfModifiedAfter,\n gitOptions,\n}: ReviewDocOptions) => {\n const configuration = getConfiguration(configOptions);\n const appLogger = getAppLogger(configuration);\n\n if (nbSimultaneousFileProcessed && nbSimultaneousFileProcessed > 10) {\n appLogger(\n `Warning: nbSimultaneousFileProcessed is set to ${nbSimultaneousFileProcessed}, which is greater than 10. Setting it to 10.`\n );\n nbSimultaneousFileProcessed = 10; // Limit the number of simultaneous file processed to 10\n }\n\n const limit = pLimit(nbSimultaneousFileProcessed ?? 3);\n\n let docList: string[] = fg.sync(docPattern, {\n ignore: excludedGlobPattern,\n });\n\n if (gitOptions) {\n const gitChangedFiles = await listGitFiles(gitOptions);\n\n if (gitChangedFiles) {\n // Convert dictionary file paths to be relative to git root for comparison\n\n // Filter dictionaries based on git changed files\n docList = docList.filter((path) =>\n gitChangedFiles.some((gitFile) => join(process.cwd(), path) === gitFile)\n );\n }\n }\n\n checkAIAccess(configuration, aiOptions);\n\n let oAuth2AccessToken: string | undefined;\n if (configuration.editor.clientId) {\n const intlayerAuthAPI = getOAuthAPI(configuration);\n const oAuth2TokenResult = await intlayerAuthAPI.getOAuth2AccessToken();\n\n oAuth2AccessToken = oAuth2TokenResult.data?.accessToken;\n }\n\n appLogger(\n `Base locale is ${getLocaleName(baseLocale, Locales.ENGLISH)} (${baseLocale})`\n );\n appLogger(\n `Reviewing ${locales.length} locales: [ ${locales\n .map((locale) => `${getLocaleName(locale, Locales.ENGLISH)} (${locale})`)\n .join(', ')} ]`\n );\n\n appLogger(`Reviewing ${docList.length} files:`);\n appLogger(docList.map((path) => ` - ${path}\\n`));\n\n const tasks = docList.map((docPath) =>\n locales.flatMap((locale) =>\n limit(async () => {\n appLogger(\n `Reviewing file: ${docPath} to ${getLocaleName(\n locale,\n Locales.ENGLISH\n )} (${locale})`\n );\n\n const absoluteBaseFilePath = join(\n configuration.content.baseDir,\n docPath\n );\n const outputFilePath = getOutputFilePath(\n absoluteBaseFilePath,\n locale,\n baseLocale\n );\n\n const fileModificationData = checkFileModifiedRange(outputFilePath, {\n skipIfModifiedBefore,\n skipIfModifiedAfter,\n });\n\n if (fileModificationData.isSkipped) {\n appLogger(fileModificationData.message);\n return;\n }\n\n let changedLines: number[] | undefined = undefined;\n // Disabled for now because it's leading to file format issues\n // if (gitOptions) {\n // const gitChangedLines = await listGitLines(\n // absoluteBaseFilePath,\n // gitOptions\n // );\n\n // appLogger(`Git changed lines: ${gitChangedLines.join(', ')}`);\n\n // changedLines = gitChangedLines;\n // }\n\n await reviewFile(\n absoluteBaseFilePath,\n outputFilePath,\n locale as Locales,\n baseLocale,\n aiOptions,\n configOptions,\n oAuth2AccessToken,\n customInstructions,\n changedLines\n );\n })\n )\n );\n\n await Promise.all(tasks);\n};\n"],"mappings":"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","names":["pLimit","fg"]}
|
|
1
|
+
{"version":3,"sources":["../../src/reviewDoc.ts"],"sourcesContent":["import { AIOptions, getOAuthAPI } from '@intlayer/api'; // Importing only getAiAPI for now\nimport {\n formatLocale,\n formatPath,\n listGitFiles,\n ListGitFilesOptions,\n} from '@intlayer/chokidar';\nimport {\n ANSIColors,\n colon,\n colorize,\n colorizeNumber,\n getAppLogger,\n getConfiguration,\n GetConfigurationOptions,\n Locales,\n retryManager,\n} from '@intlayer/config';\nimport { getLocaleName } from '@intlayer/core';\nimport fg from 'fast-glob';\nimport { mkdirSync, writeFileSync } from 'fs';\nimport { readFile } from 'fs/promises';\nimport pLimit from 'p-limit';\nimport { dirname, join, relative } from 'path';\nimport { fileURLToPath } from 'url';\nimport { chunkText } from './utils/calculateChunks';\nimport { checkAIAccess } from './utils/checkAIAccess';\nimport { checkFileModifiedRange } from './utils/checkFileModifiedRange';\nimport { chunkInference } from './utils/chunkInference';\nimport { fixChunkStartEndChars } from './utils/fixChunkStartEndChars';\nimport { getChunk } from './utils/getChunk';\nimport { getOutputFilePath } from './utils/getOutputFilePath';\n\nconst isESModule = typeof import.meta.url === 'string';\n\nconst dir = isESModule ? dirname(fileURLToPath(import.meta.url)) : __dirname;\n\n/**\n * Translate a single file for a given locale\n */\nexport const reviewFile = async (\n baseFilePath: string,\n outputFilePath: string,\n locale: Locales,\n baseLocale: Locales,\n aiOptions?: AIOptions,\n configOptions?: GetConfigurationOptions,\n oAuth2AccessToken?: string,\n customInstructions?: string,\n changedLines?: number[]\n) => {\n try {\n const configuration = getConfiguration(configOptions);\n const appLogger = getAppLogger(configuration, {\n config: {\n prefix: '',\n },\n });\n\n const basedFileContent = await readFile(baseFilePath, 'utf-8');\n const fileToReviewContent = await readFile(outputFilePath, 'utf-8');\n\n let updatedFileContent = fileToReviewContent;\n let fileResultContent = '';\n\n // Prepare the base prompt for ChatGPT\n const basePrompt = (\n await readFile(join(dir, './prompts/REVIEW_PROMPT.md'), 'utf-8')\n )\n .replaceAll('{{localeName}}', `${formatLocale(locale, false)}`)\n .replaceAll('{{baseLocaleName}}', `${formatLocale(baseLocale, false)}`)\n .replace('{{applicationContext}}', aiOptions?.applicationContext ?? '-')\n .replace('{{customInstructions}}', customInstructions ?? '-');\n\n const baseChunks = chunkText(basedFileContent, 800, 0);\n\n const filePrexixText = `${ANSIColors.GREY_DARK}[${formatPath(baseFilePath)}${ANSIColors.GREY_DARK}] `;\n const filePrefix = [\n colon(filePrexixText, { colSize: 40 }),\n `→ ${ANSIColors.RESET}`,\n ].join('');\n\n const prefixText = `${ANSIColors.GREY_DARK}[${formatPath(baseFilePath)}${ANSIColors.GREY_DARK}][${formatLocale(locale)}${ANSIColors.GREY_DARK}] `;\n const prefix = [\n colon(prefixText, { colSize: 40 }),\n `→ ${ANSIColors.RESET}`,\n ].join('');\n\n appLogger(\n `${filePrefix}Base file splitted into ${colorizeNumber(baseChunks.length)} chunks`\n );\n\n for await (const [i, baseChunk] of baseChunks.entries()) {\n const baseChunkContext = baseChunk;\n\n if (changedLines) {\n const hasChangedLinesInChunk = changedLines.some(\n (line) =>\n line > baseChunkContext.lineStart &&\n line < baseChunkContext.lineStart + baseChunkContext.lineLength\n );\n\n if (!hasChangedLinesInChunk) {\n appLogger(\n `No git changed lines found for chunk ${colorizeNumber(i + 1)}`\n );\n\n const chunkWithNoChange = getChunk(updatedFileContent, {\n lineStart: baseChunkContext.lineStart,\n lineLength: baseChunkContext.lineLength,\n });\n\n fileResultContent += chunkWithNoChange;\n\n continue;\n }\n }\n\n const getBaseChunkContextPrompt = () =>\n `**CHUNK ${i + 1} to ${Math.min(i + 3, baseChunks.length)} of ${baseChunks.length}** is the base chunk in ${formatLocale(baseLocale, false)} as reference.\\n` +\n `///chunksStart///` +\n (baseChunks[i - 1]?.content ?? '') +\n baseChunkContext.content +\n (baseChunks[i + 1]?.content ?? '') +\n `///chunksEnd///`;\n\n const getChunkToReviewPrompt = () =>\n `**CHUNK ${i + 1} to ${Math.min(i + 3, baseChunks.length)} of ${baseChunks.length}** is the current chunk to review in ${formatLocale(locale, false)} as reference.\\n` +\n `///chunksStart///` +\n getChunk(updatedFileContent, {\n lineStart: baseChunks[i - 1]?.lineStart ?? 0,\n lineLength:\n (baseChunks[i - 1]?.lineLength ?? 0) +\n baseChunkContext.lineLength +\n (baseChunks[i + 1]?.lineLength ?? 0),\n }) +\n `///chunksEnd///`;\n\n // Make the actual translation call\n let reviewedChunkResult = await retryManager(async () => {\n const result = await chunkInference(\n [\n { role: 'system', content: basePrompt },\n { role: 'system', content: getBaseChunkContextPrompt() },\n { role: 'system', content: getChunkToReviewPrompt() },\n {\n role: 'system',\n content: `The next user message will be the **CHUNK ${colorizeNumber(i + 1)} of ${colorizeNumber(baseChunks.length)}** that should be translated in ${getLocaleName(locale, Locales.ENGLISH)} (${locale}).`,\n },\n { role: 'user', content: baseChunkContext.content },\n ],\n aiOptions,\n oAuth2AccessToken\n );\n\n appLogger(\n `${prefix}${colorizeNumber(result.tokenUsed)} tokens used - Chunk ${colorizeNumber(i + 1)} of ${colorizeNumber(baseChunks.length)}`\n );\n\n const fixedReviewedChunkResult = fixChunkStartEndChars(\n result?.fileContent,\n baseChunkContext.content\n );\n\n return fixedReviewedChunkResult;\n })();\n\n updatedFileContent = updatedFileContent.replace(\n baseChunkContext.content,\n reviewedChunkResult\n );\n\n fileResultContent += reviewedChunkResult;\n }\n\n mkdirSync(dirname(outputFilePath), { recursive: true });\n writeFileSync(outputFilePath, fileResultContent);\n\n const relativePath = relative(\n configuration.content.baseDir,\n outputFilePath\n );\n\n appLogger(\n `${colorize('✔', ANSIColors.GREEN)} File ${formatPath(relativePath)} created/updated successfully.`\n );\n } catch (error) {\n console.error(error);\n }\n};\n\ntype ReviewDocOptions = {\n docPattern: string[];\n locales: Locales[];\n excludedGlobPattern: string[];\n baseLocale: Locales;\n aiOptions?: AIOptions;\n nbSimultaneousFileProcessed?: number;\n configOptions?: GetConfigurationOptions;\n customInstructions?: string;\n skipIfModifiedBefore?: number | string | Date;\n skipIfModifiedAfter?: number | string | Date;\n gitOptions?: ListGitFilesOptions;\n};\n\n/**\n * Main audit function: scans all .md files in \"en/\" (unless you specified DOC_LIST),\n * then audits them to each locale in LOCALE_LIST.\n */\nexport const reviewDoc = async ({\n docPattern,\n locales,\n excludedGlobPattern,\n baseLocale,\n aiOptions,\n nbSimultaneousFileProcessed,\n configOptions,\n customInstructions,\n skipIfModifiedBefore,\n skipIfModifiedAfter,\n gitOptions,\n}: ReviewDocOptions) => {\n const configuration = getConfiguration(configOptions);\n const appLogger = getAppLogger(configuration, {\n config: {\n prefix: '',\n },\n });\n\n if (nbSimultaneousFileProcessed && nbSimultaneousFileProcessed > 10) {\n appLogger(\n `Warning: nbSimultaneousFileProcessed is set to ${nbSimultaneousFileProcessed}, which is greater than 10. Setting it to 10.`\n );\n nbSimultaneousFileProcessed = 10; // Limit the number of simultaneous file processed to 10\n }\n\n const limit = pLimit(nbSimultaneousFileProcessed ?? 3);\n\n let docList: string[] = fg.sync(docPattern, {\n ignore: excludedGlobPattern,\n });\n\n if (gitOptions) {\n const gitChangedFiles = await listGitFiles(gitOptions);\n\n if (gitChangedFiles) {\n // Convert dictionary file paths to be relative to git root for comparison\n\n // Filter dictionaries based on git changed files\n docList = docList.filter((path) =>\n gitChangedFiles.some((gitFile) => join(process.cwd(), path) === gitFile)\n );\n }\n }\n\n checkAIAccess(configuration, aiOptions);\n\n let oAuth2AccessToken: string | undefined;\n if (configuration.editor.clientId) {\n const intlayerAuthAPI = getOAuthAPI(configuration);\n const oAuth2TokenResult = await intlayerAuthAPI.getOAuth2AccessToken();\n\n oAuth2AccessToken = oAuth2TokenResult.data?.accessToken;\n }\n\n appLogger(`Base locale is ${formatLocale(baseLocale)}`);\n appLogger(\n `Reviewing ${colorizeNumber(locales.length)} locales: [ ${formatLocale(locales)} ]`\n );\n\n appLogger(`Reviewing ${colorizeNumber(docList.length)} files:`);\n appLogger(docList.map((path) => ` - ${formatPath(path)}\\n`));\n\n const tasks = docList.map((docPath) =>\n locales.flatMap((locale) =>\n limit(async () => {\n appLogger(\n `Reviewing file: ${formatPath(docPath)} to ${formatLocale(locale)}`\n );\n\n const absoluteBaseFilePath = join(\n configuration.content.baseDir,\n docPath\n );\n const outputFilePath = getOutputFilePath(\n absoluteBaseFilePath,\n locale,\n baseLocale\n );\n\n const fileModificationData = checkFileModifiedRange(outputFilePath, {\n skipIfModifiedBefore,\n skipIfModifiedAfter,\n });\n\n if (fileModificationData.isSkipped) {\n appLogger(fileModificationData.message);\n return;\n }\n\n let changedLines: number[] | undefined = undefined;\n // Disabled for now because it's leading to file format issues\n // if (gitOptions) {\n // const gitChangedLines = await listGitLines(\n // absoluteBaseFilePath,\n // gitOptions\n // );\n\n // appLogger(`Git changed lines: ${gitChangedLines.join(', ')}`);\n\n // changedLines = gitChangedLines;\n // }\n\n await reviewFile(\n absoluteBaseFilePath,\n outputFilePath,\n locale as Locales,\n baseLocale,\n aiOptions,\n configOptions,\n oAuth2AccessToken,\n customInstructions,\n changedLines\n );\n })\n )\n );\n\n await Promise.all(tasks);\n};\n"],"mappings":"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","names":["pLimit","fg"]}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var test_exports = {};
|
|
20
|
+
__export(test_exports, {
|
|
21
|
+
listMissingTranslations: () => import_listMissingTranslations.listMissingTranslations,
|
|
22
|
+
testMissingTranslations: () => testMissingTranslations
|
|
23
|
+
});
|
|
24
|
+
module.exports = __toCommonJS(test_exports);
|
|
25
|
+
var import_chokidar = require("@intlayer/chokidar");
|
|
26
|
+
var import_config = require("@intlayer/config");
|
|
27
|
+
var import_listMissingTranslations = require('./listMissingTranslations.cjs');
|
|
28
|
+
const testMissingTranslations = (options) => {
|
|
29
|
+
const config = (0, import_config.getConfiguration)(options?.configOptions);
|
|
30
|
+
const { locales, requiredLocales } = config.internationalization;
|
|
31
|
+
const appLogger = (0, import_config.getAppLogger)(config, {
|
|
32
|
+
config: {
|
|
33
|
+
prefix: ""
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
const result = (0, import_listMissingTranslations.listMissingTranslations)();
|
|
37
|
+
const maxKeyColSize = result.missingTranslations.map((t) => ` - ${t.key}`).reduce((max, t) => Math.max(max, t.length), 0);
|
|
38
|
+
const maxLocalesColSize = result.missingTranslations.map((t) => (0, import_chokidar.formatLocale)(t.locales, false)).reduce((max, t) => Math.max(max, t.length), 0);
|
|
39
|
+
const formattedMissingTranslations = result.missingTranslations.map(
|
|
40
|
+
(translation) => [
|
|
41
|
+
(0, import_config.colon)(` - ${(0, import_config.colorizeKey)(translation.key)}`, {
|
|
42
|
+
colSize: maxKeyColSize,
|
|
43
|
+
maxSize: 40
|
|
44
|
+
}),
|
|
45
|
+
" - ",
|
|
46
|
+
(0, import_config.colon)((0, import_chokidar.formatLocale)(translation.locales, import_config.ANSIColors.RED), {
|
|
47
|
+
colSize: maxLocalesColSize,
|
|
48
|
+
maxSize: 40
|
|
49
|
+
}),
|
|
50
|
+
" - ",
|
|
51
|
+
translation.filePath ? (0, import_chokidar.formatPath)(translation.filePath) : "Remote"
|
|
52
|
+
].join("")
|
|
53
|
+
);
|
|
54
|
+
appLogger(`Missing translations:`, {
|
|
55
|
+
level: "info"
|
|
56
|
+
});
|
|
57
|
+
formattedMissingTranslations.forEach((t) => {
|
|
58
|
+
appLogger(t, {
|
|
59
|
+
level: "info"
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
appLogger(`Locales: ${(0, import_chokidar.formatLocale)(locales)}`);
|
|
63
|
+
appLogger(`Required locales: ${(0, import_chokidar.formatLocale)(requiredLocales ?? locales)}`);
|
|
64
|
+
appLogger(
|
|
65
|
+
`Missing locales: ${result.missingLocales.length === 0 ? (0, import_config.colorize)("-", import_config.ANSIColors.GREEN) : (0, import_chokidar.formatLocale)(result.missingLocales, import_config.ANSIColors.RED)}`
|
|
66
|
+
);
|
|
67
|
+
appLogger(
|
|
68
|
+
`Missing required locales: ${result.missingRequiredLocales.length === 0 ? (0, import_config.colorize)("-", import_config.ANSIColors.GREEN) : (0, import_chokidar.formatLocale)(result.missingRequiredLocales, import_config.ANSIColors.RED)}`
|
|
69
|
+
);
|
|
70
|
+
appLogger(
|
|
71
|
+
`Total missing locales: ${(0, import_config.colorizeNumber)(result.missingLocales.length, {
|
|
72
|
+
other: import_config.ANSIColors.RED,
|
|
73
|
+
zero: import_config.ANSIColors.GREEN
|
|
74
|
+
})}`
|
|
75
|
+
);
|
|
76
|
+
appLogger(
|
|
77
|
+
`Total missing required locales: ${(0, import_config.colorizeNumber)(
|
|
78
|
+
result.missingRequiredLocales.length,
|
|
79
|
+
{
|
|
80
|
+
other: import_config.ANSIColors.RED,
|
|
81
|
+
zero: import_config.ANSIColors.GREEN
|
|
82
|
+
}
|
|
83
|
+
)}`
|
|
84
|
+
);
|
|
85
|
+
};
|
|
86
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
87
|
+
0 && (module.exports = {
|
|
88
|
+
listMissingTranslations,
|
|
89
|
+
testMissingTranslations
|
|
90
|
+
});
|
|
91
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/test/index.ts"],"sourcesContent":["import { formatLocale, formatPath } from '@intlayer/chokidar';\nimport {\n ANSIColors,\n colon,\n colorize,\n colorizeKey,\n colorizeNumber,\n getAppLogger,\n getConfiguration,\n GetConfigurationOptions,\n} from '@intlayer/config';\nimport { listMissingTranslations } from './listMissingTranslations';\n\nexport { listMissingTranslations };\n\ntype ListMissingTranslationsOptions = {\n configOptions?: GetConfigurationOptions;\n};\n\nexport const testMissingTranslations = (\n options?: ListMissingTranslationsOptions\n) => {\n const config = getConfiguration(options?.configOptions);\n const { locales, requiredLocales } = config.internationalization;\n\n const appLogger = getAppLogger(config, {\n config: {\n prefix: '',\n },\n });\n\n const result = listMissingTranslations();\n\n const maxKeyColSize = result.missingTranslations\n .map((t) => ` - ${t.key}`)\n .reduce((max, t) => Math.max(max, t.length), 0);\n const maxLocalesColSize = result.missingTranslations\n .map((t) => formatLocale(t.locales, false))\n .reduce((max, t) => Math.max(max, t.length), 0);\n\n const formattedMissingTranslations = result.missingTranslations.map(\n (translation) =>\n [\n colon(` - ${colorizeKey(translation.key)}`, {\n colSize: maxKeyColSize,\n maxSize: 40,\n }),\n ' - ',\n colon(formatLocale(translation.locales, ANSIColors.RED), {\n colSize: maxLocalesColSize,\n maxSize: 40,\n }),\n ' - ',\n translation.filePath ? formatPath(translation.filePath) : 'Remote',\n ].join('')\n );\n\n appLogger(`Missing translations:`, {\n level: 'info',\n });\n\n formattedMissingTranslations.forEach((t) => {\n appLogger(t, {\n level: 'info',\n });\n });\n\n appLogger(`Locales: ${formatLocale(locales)}`);\n appLogger(`Required locales: ${formatLocale(requiredLocales ?? locales)}`);\n appLogger(\n `Missing locales: ${result.missingLocales.length === 0 ? colorize('-', ANSIColors.GREEN) : formatLocale(result.missingLocales, ANSIColors.RED)}`\n );\n\n appLogger(\n `Missing required locales: ${result.missingRequiredLocales.length === 0 ? colorize('-', ANSIColors.GREEN) : formatLocale(result.missingRequiredLocales, ANSIColors.RED)}`\n );\n appLogger(\n `Total missing locales: ${colorizeNumber(result.missingLocales.length, {\n other: ANSIColors.RED,\n zero: ANSIColors.GREEN,\n })}`\n );\n appLogger(\n `Total missing required locales: ${colorizeNumber(\n result.missingRequiredLocales.length,\n {\n other: ANSIColors.RED,\n zero: ANSIColors.GREEN,\n }\n )}`\n );\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,sBAAyC;AACzC,oBASO;AACP,qCAAwC;AAQjC,MAAM,0BAA0B,CACrC,YACG;AACH,QAAM,aAAS,gCAAiB,SAAS,aAAa;AACtD,QAAM,EAAE,SAAS,gBAAgB,IAAI,OAAO;AAE5C,QAAM,gBAAY,4BAAa,QAAQ;AAAA,IACrC,QAAQ;AAAA,MACN,QAAQ;AAAA,IACV;AAAA,EACF,CAAC;AAED,QAAM,aAAS,wDAAwB;AAEvC,QAAM,gBAAgB,OAAO,oBAC1B,IAAI,CAAC,MAAM,MAAM,EAAE,GAAG,EAAE,EACxB,OAAO,CAAC,KAAK,MAAM,KAAK,IAAI,KAAK,EAAE,MAAM,GAAG,CAAC;AAChD,QAAM,oBAAoB,OAAO,oBAC9B,IAAI,CAAC,UAAM,8BAAa,EAAE,SAAS,KAAK,CAAC,EACzC,OAAO,CAAC,KAAK,MAAM,KAAK,IAAI,KAAK,EAAE,MAAM,GAAG,CAAC;AAEhD,QAAM,+BAA+B,OAAO,oBAAoB;AAAA,IAC9D,CAAC,gBACC;AAAA,UACE,qBAAM,UAAM,2BAAY,YAAY,GAAG,CAAC,IAAI;AAAA,QAC1C,SAAS;AAAA,QACT,SAAS;AAAA,MACX,CAAC;AAAA,MACD;AAAA,UACA,yBAAM,8BAAa,YAAY,SAAS,yBAAW,GAAG,GAAG;AAAA,QACvD,SAAS;AAAA,QACT,SAAS;AAAA,MACX,CAAC;AAAA,MACD;AAAA,MACA,YAAY,eAAW,4BAAW,YAAY,QAAQ,IAAI;AAAA,IAC5D,EAAE,KAAK,EAAE;AAAA,EACb;AAEA,YAAU,yBAAyB;AAAA,IACjC,OAAO;AAAA,EACT,CAAC;AAED,+BAA6B,QAAQ,CAAC,MAAM;AAC1C,cAAU,GAAG;AAAA,MACX,OAAO;AAAA,IACT,CAAC;AAAA,EACH,CAAC;AAED,YAAU,gBAAY,8BAAa,OAAO,CAAC,EAAE;AAC7C,YAAU,yBAAqB,8BAAa,mBAAmB,OAAO,CAAC,EAAE;AACzE;AAAA,IACE,oBAAoB,OAAO,eAAe,WAAW,QAAI,wBAAS,KAAK,yBAAW,KAAK,QAAI,8BAAa,OAAO,gBAAgB,yBAAW,GAAG,CAAC;AAAA,EAChJ;AAEA;AAAA,IACE,6BAA6B,OAAO,uBAAuB,WAAW,QAAI,wBAAS,KAAK,yBAAW,KAAK,QAAI,8BAAa,OAAO,wBAAwB,yBAAW,GAAG,CAAC;AAAA,EACzK;AACA;AAAA,IACE,8BAA0B,8BAAe,OAAO,eAAe,QAAQ;AAAA,MACrE,OAAO,yBAAW;AAAA,MAClB,MAAM,yBAAW;AAAA,IACnB,CAAC,CAAC;AAAA,EACJ;AACA;AAAA,IACE,uCAAmC;AAAA,MACjC,OAAO,uBAAuB;AAAA,MAC9B;AAAA,QACE,OAAO,yBAAW;AAAA,QAClB,MAAM,yBAAW;AAAA,MACnB;AAAA,IACF,CAAC;AAAA,EACH;AACF;","names":[]}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
var listMissingTranslations_exports = {};
|
|
30
|
+
__export(listMissingTranslations_exports, {
|
|
31
|
+
listMissingTranslations: () => listMissingTranslations
|
|
32
|
+
});
|
|
33
|
+
module.exports = __toCommonJS(listMissingTranslations_exports);
|
|
34
|
+
var import_built = __toESM(require("@intlayer/config/built"));
|
|
35
|
+
var import_core = require("@intlayer/core");
|
|
36
|
+
var import_unmerged_dictionaries_entry = __toESM(require("@intlayer/unmerged-dictionaries-entry"));
|
|
37
|
+
const listMissingTranslations = (dictionariesRecord = import_unmerged_dictionaries_entry.default) => {
|
|
38
|
+
const missingTranslations = [];
|
|
39
|
+
const { locales, requiredLocales } = import_built.default.internationalization;
|
|
40
|
+
for (const dictionaries of Object.values(dictionariesRecord)) {
|
|
41
|
+
for (const dictionary of dictionaries) {
|
|
42
|
+
const missingLocales2 = (0, import_core.getMissingLocalesContent)(
|
|
43
|
+
dictionary,
|
|
44
|
+
import_built.default.internationalization.locales,
|
|
45
|
+
{
|
|
46
|
+
dictionaryKey: dictionary.key,
|
|
47
|
+
keyPath: [],
|
|
48
|
+
plugins: []
|
|
49
|
+
}
|
|
50
|
+
);
|
|
51
|
+
if (missingLocales2.length > 0) {
|
|
52
|
+
missingTranslations.push({
|
|
53
|
+
key: dictionary.key,
|
|
54
|
+
filePath: dictionary.filePath,
|
|
55
|
+
locales: missingLocales2
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
const missingLocalesSet = new Set(
|
|
61
|
+
missingTranslations.flatMap((t) => t.locales)
|
|
62
|
+
);
|
|
63
|
+
const missingLocales = Array.from(missingLocalesSet);
|
|
64
|
+
const missingRequiredLocales = missingLocales.filter(
|
|
65
|
+
(locale) => (requiredLocales ?? locales).includes(locale)
|
|
66
|
+
);
|
|
67
|
+
return { missingTranslations, missingLocales, missingRequiredLocales };
|
|
68
|
+
};
|
|
69
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
70
|
+
0 && (module.exports = {
|
|
71
|
+
listMissingTranslations
|
|
72
|
+
});
|
|
73
|
+
//# sourceMappingURL=listMissingTranslations.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/test/listMissingTranslations.ts"],"sourcesContent":["import type { Locales } from '@intlayer/config';\nimport configuration from '@intlayer/config/built';\nimport {\n type ContentNode,\n type Dictionary,\n getMissingLocalesContent,\n} from '@intlayer/core';\nimport unmergedDictionariesRecord from '@intlayer/unmerged-dictionaries-entry';\n\nexport const listMissingTranslations = (\n dictionariesRecord: keyof typeof unmergedDictionariesRecord = unmergedDictionariesRecord\n) => {\n const missingTranslations: {\n key: keyof typeof unmergedDictionariesRecord;\n filePath?: string;\n locales: Locales[];\n }[] = [];\n\n const { locales, requiredLocales } = configuration.internationalization;\n\n for (const dictionaries of Object.values(dictionariesRecord)) {\n for (const dictionary of dictionaries as unknown as Dictionary[]) {\n const missingLocales = getMissingLocalesContent(\n dictionary as unknown as ContentNode,\n configuration.internationalization.locales,\n {\n dictionaryKey: dictionary.key,\n keyPath: [],\n plugins: [],\n }\n );\n\n if (missingLocales.length > 0) {\n missingTranslations.push({\n key: dictionary.key,\n filePath: dictionary.filePath,\n locales: missingLocales,\n });\n }\n }\n }\n\n const missingLocalesSet = new Set(\n missingTranslations.flatMap((t) => t.locales)\n );\n const missingLocales = Array.from(missingLocalesSet);\n\n const missingRequiredLocales = missingLocales.filter((locale) =>\n (requiredLocales ?? locales).includes(locale)\n );\n\n return { missingTranslations, missingLocales, missingRequiredLocales };\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,mBAA0B;AAC1B,kBAIO;AACP,yCAAuC;AAEhC,MAAM,0BAA0B,CACrC,qBAA8D,mCAAAA,YAC3D;AACH,QAAM,sBAIA,CAAC;AAEP,QAAM,EAAE,SAAS,gBAAgB,IAAI,aAAAC,QAAc;AAEnD,aAAW,gBAAgB,OAAO,OAAO,kBAAkB,GAAG;AAC5D,eAAW,cAAc,cAAyC;AAChE,YAAMC,sBAAiB;AAAA,QACrB;AAAA,QACA,aAAAD,QAAc,qBAAqB;AAAA,QACnC;AAAA,UACE,eAAe,WAAW;AAAA,UAC1B,SAAS,CAAC;AAAA,UACV,SAAS,CAAC;AAAA,QACZ;AAAA,MACF;AAEA,UAAIC,gBAAe,SAAS,GAAG;AAC7B,4BAAoB,KAAK;AAAA,UACvB,KAAK,WAAW;AAAA,UAChB,UAAU,WAAW;AAAA,UACrB,SAASA;AAAA,QACX,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAEA,QAAM,oBAAoB,IAAI;AAAA,IAC5B,oBAAoB,QAAQ,CAAC,MAAM,EAAE,OAAO;AAAA,EAC9C;AACA,QAAM,iBAAiB,MAAM,KAAK,iBAAiB;AAEnD,QAAM,yBAAyB,eAAe;AAAA,IAAO,CAAC,YACnD,mBAAmB,SAAS,SAAS,MAAM;AAAA,EAC9C;AAEA,SAAO,EAAE,qBAAqB,gBAAgB,uBAAuB;AACvE;","names":["unmergedDictionariesRecord","configuration","missingLocales"]}
|