@intlayer/cli 6.0.1 → 6.0.2-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/cli.cjs +15 -1
- package/dist/cjs/cli.cjs.map +1 -1
- package/dist/cjs/reviewDoc.cjs +13 -9
- package/dist/cjs/reviewDoc.cjs.map +1 -1
- package/dist/cjs/translateDoc.cjs +12 -5
- package/dist/cjs/translateDoc.cjs.map +1 -1
- package/dist/cjs/utils/checkAccess.cjs +6 -8
- package/dist/cjs/utils/checkAccess.cjs.map +1 -1
- package/dist/cjs/utils/chunkInference.cjs +1 -2
- package/dist/cjs/utils/chunkInference.cjs.map +1 -1
- package/dist/esm/cli.mjs +15 -1
- package/dist/esm/cli.mjs.map +1 -1
- package/dist/esm/reviewDoc.mjs +13 -9
- package/dist/esm/reviewDoc.mjs.map +1 -1
- package/dist/esm/translateDoc.mjs +12 -5
- package/dist/esm/translateDoc.mjs.map +1 -1
- package/dist/esm/utils/checkAccess.mjs +6 -8
- package/dist/esm/utils/checkAccess.mjs.map +1 -1
- package/dist/esm/utils/chunkInference.mjs +2 -6
- package/dist/esm/utils/chunkInference.mjs.map +1 -1
- package/dist/types/cli.d.ts.map +1 -1
- package/dist/types/reviewDoc.d.ts +2 -2
- package/dist/types/reviewDoc.d.ts.map +1 -1
- package/dist/types/translateDoc.d.ts +2 -2
- package/dist/types/translateDoc.d.ts.map +1 -1
- package/dist/types/utils/checkAccess.d.ts.map +1 -1
- package/dist/types/utils/chunkInference.d.ts +2 -2
- package/dist/types/utils/chunkInference.d.ts.map +1 -1
- package/package.json +15 -15
package/dist/cjs/cli.cjs
CHANGED
|
@@ -203,7 +203,12 @@ const setAPI = () => {
|
|
|
203
203
|
description: "Pull dictionaries from the server",
|
|
204
204
|
options: [
|
|
205
205
|
["-d, --dictionaries [ids...]", "List of dictionary IDs to pull"],
|
|
206
|
-
["--new-dictionaries-path [path]", "Path to save the new dictionaries"]
|
|
206
|
+
["--new-dictionaries-path [path]", "Path to save the new dictionaries"],
|
|
207
|
+
// Backward-compatibility for older tests/flags (camelCase)
|
|
208
|
+
[
|
|
209
|
+
"--newDictionariesPath [path]",
|
|
210
|
+
"[alias] Path to save the new dictionaries"
|
|
211
|
+
]
|
|
207
212
|
]
|
|
208
213
|
};
|
|
209
214
|
const dictionariesPullCmd = dictionariesProgram.command("pull").description(pullOptions.description);
|
|
@@ -238,6 +243,15 @@ const setAPI = () => {
|
|
|
238
243
|
[
|
|
239
244
|
"-k, --keep-locale-dictionary",
|
|
240
245
|
"Keep the local dictionaries after pushing"
|
|
246
|
+
],
|
|
247
|
+
// Backward-compatibility for older tests/flags (camelCase)
|
|
248
|
+
[
|
|
249
|
+
"--deleteLocaleDictionary",
|
|
250
|
+
"[alias] Delete the local dictionaries after pushing"
|
|
251
|
+
],
|
|
252
|
+
[
|
|
253
|
+
"--keepLocaleDictionary",
|
|
254
|
+
"[alias] Keep the local dictionaries after pushing"
|
|
241
255
|
]
|
|
242
256
|
]
|
|
243
257
|
};
|
package/dist/cjs/cli.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/cli.ts"],"sourcesContent":["import type { AIOptions as BaseAIOptions } from '@intlayer/api';\nimport type { GetConfigurationOptions } from '@intlayer/config';\nimport configuration from '@intlayer/config/built';\nimport { Command } from 'commander';\nimport { dirname as pathDirname } from 'path';\nimport { fileURLToPath } from 'url';\nimport {\n DiffMode,\n ListGitFilesOptions,\n} from '../../chokidar/dist/types/listGitFiles';\nimport { build } from './build';\nimport { getConfig } from './config';\nimport { startEditor } from './editor';\nimport { fill, FillOptions } from './fill';\nimport { listContentDeclaration } from './listContentDeclaration';\nimport { liveSync } from './liveSync';\nimport { pull } from './pull';\nimport { push } from './push';\nimport { pushConfig } from './pushConfig';\nimport { reviewDoc } from './reviewDoc';\nimport { testMissingTranslations } from './test';\nimport { translateDoc } from './translateDoc';\nimport { getParentPackageJSON } from './utils/getParentPackageJSON';\n\n// Extended AI options to include customPrompt\ntype AIOptions = BaseAIOptions & {\n customPrompt?: string;\n};\n\nconst isESModule = typeof import.meta.url === 'string';\n\nexport const dirname = isESModule\n ? pathDirname(fileURLToPath(import.meta.url))\n : __dirname;\n\nconst packageJson = getParentPackageJSON(dirname);\n\nconst logOptions = [\n ['--verbose', 'Verbose'],\n ['--prefix [prefix]', 'Prefix'],\n];\n\nconst configurationOptions = [\n ['--env-file [envFile]', 'Environment file'],\n ['-e, --env [env]', 'Environment'],\n ['--base-dir [baseDir]', 'Base directory'],\n ...logOptions,\n];\n\nconst aiOptions = [\n ['--provider [provider]', 'Provider'],\n ['--temperature [temperature]', 'Temperature'],\n ['--model [model]', 'Model'],\n ['--api-key [apiKey]', 'Provider API key'],\n ['--custom-prompt [prompt]', 'Custom prompt'],\n ['--application-context [applicationContext]', 'Application context'],\n];\n\nconst gitOptions = [\n ['--git-diff [gitDiff]', 'Git diff mode - Check git diff between two refs'],\n ['--git-diff-base [gitDiffBase]', 'Git diff base ref'],\n ['--git-diff-current [gitDiffCurrent]', 'Git diff current ref'],\n ['--uncommitted [uncommitted]', 'Uncommitted'],\n ['--unpushed [unpushed]', 'Unpushed'],\n ['--untracked [untracked]', 'Untracked'],\n];\n\nconst extractKeysFromOptions = (options: object, keys: string[]) =>\n keys.filter((key) => options[key as keyof typeof options]);\n\n/**\n * Helper functions to apply common options to commands\n */\nconst applyOptions = (command: Command, options: string[][]) => {\n options.forEach(([flag, description]) => command.option(flag, description));\n return command;\n};\n\nconst removeUndefined = <T extends Record<string, any>>(obj: T): T =>\n Object.fromEntries(\n Object.entries(obj).filter(([_, value]) => value !== undefined)\n ) as T;\n\nconst applyConfigOptions = (command: Command) =>\n applyOptions(command, configurationOptions);\nconst applyAIOptions = (command: Command) => applyOptions(command, aiOptions);\nconst applyGitOptions = (command: Command) => applyOptions(command, gitOptions);\n\nconst extractAiOptions = (options: AIOptions): AIOptions | undefined => {\n const {\n apiKey,\n provider,\n model,\n temperature,\n applicationContext,\n customPrompt,\n } = options;\n\n return removeUndefined({\n apiKey: apiKey ?? configuration.ai?.apiKey,\n provider: provider ?? (configuration.ai?.provider as AIOptions['provider']),\n model: model ?? configuration.ai?.model,\n temperature: temperature ?? configuration.ai?.temperature,\n applicationContext:\n applicationContext ?? configuration.ai?.applicationContext,\n customPrompt: customPrompt ?? (configuration.ai as any)?.customPrompt,\n });\n};\n\ntype GitOptions = {\n gitDiff?: boolean;\n gitDiffBase?: string;\n gitDiffCurrent?: string;\n uncommitted?: boolean;\n unpushed?: boolean;\n untracked?: boolean;\n};\n\nconst gitOptionKeys: (keyof GitOptions)[] = [\n 'gitDiff',\n 'gitDiffBase',\n 'gitDiffCurrent',\n 'uncommitted',\n 'unpushed',\n 'untracked',\n];\n\nconst extractGitOptions = (\n options: GitOptions\n): ListGitFilesOptions | undefined => {\n const filteredOptions = extractKeysFromOptions(options, gitOptionKeys);\n\n const isOptionEmpty = !Object.values(filteredOptions).some(Boolean);\n\n if (isOptionEmpty) return undefined;\n\n const {\n gitDiff,\n gitDiffBase,\n gitDiffCurrent,\n uncommitted,\n unpushed,\n untracked,\n } = options;\n\n const mode = [\n gitDiff && 'gitDiff',\n uncommitted && 'uncommitted',\n unpushed && 'unpushed',\n untracked && 'untracked',\n ].filter(Boolean) as DiffMode[];\n\n return removeUndefined({\n mode,\n baseRef: gitDiffBase,\n currentRef: gitDiffCurrent,\n absolute: true,\n });\n};\n\ntype LogOptions = {\n prefix?: string;\n verbose?: boolean;\n};\n\nexport type ConfigurationOptions = {\n baseDir?: string;\n env?: string;\n envFile?: string;\n} & LogOptions;\n\nconst configurationOptionKeys: (keyof ConfigurationOptions)[] = [\n 'baseDir',\n 'env',\n 'envFile',\n 'verbose',\n 'prefix',\n];\n\nconst extractConfigOptions = (\n options: ConfigurationOptions\n): GetConfigurationOptions | undefined => {\n const filteredOptions = extractKeysFromOptions(\n options,\n configurationOptionKeys\n );\n\n const isOptionEmpty = !Object.values(filteredOptions).some(Boolean);\n\n if (isOptionEmpty) {\n return undefined;\n }\n\n const { baseDir, env, envFile, verbose, prefix } = options;\n\n const log = {\n prefix: prefix ?? '', // Should not consider the prefix set in the intlayer configuration file\n verbose,\n };\n\n const override = {\n log,\n };\n\n return removeUndefined({\n baseDir,\n env,\n envFile,\n override,\n });\n};\n\n/**\n * Set the API for the CLI\n *\n * Example of commands:\n *\n * npm run intlayer build --watch\n * npm run intlayer push --dictionaries id1 id2 id3 --deleteLocaleDir\n */\nexport const setAPI = (): Command => {\n const program = new Command();\n\n program.version(packageJson.version!).description('Intlayer CLI');\n\n /**\n * DICTIONARIES\n */\n\n const dictionariesProgram = program\n .command('dictionary')\n .alias('dictionaries')\n .alias('dic')\n .description('Dictionaries operations');\n\n // Dictionary build command\n const buildOptions = {\n description: 'Build the dictionaries',\n options: [['-w, --watch', 'Watch for changes']],\n };\n\n // Add build command to dictionaries program\n const dictionariesBuildCmd = dictionariesProgram\n .command('build')\n .description(buildOptions.description);\n\n applyOptions(dictionariesBuildCmd, buildOptions.options);\n applyConfigOptions(dictionariesBuildCmd);\n dictionariesBuildCmd.action((options) => {\n build({\n ...options,\n configOptions: extractConfigOptions(options),\n });\n });\n\n // Add build command to root program as well\n const rootBuildCmd = program\n .command('build')\n .description(buildOptions.description);\n\n applyOptions(rootBuildCmd, buildOptions.options);\n applyConfigOptions(rootBuildCmd);\n rootBuildCmd.action((options) => {\n build({\n ...options,\n configOptions: extractConfigOptions(options),\n });\n });\n\n // Dictionary pull command\n const pullOptions = {\n description: 'Pull dictionaries from the server',\n options: [\n ['-d, --dictionaries [ids...]', 'List of dictionary IDs to pull'],\n ['--new-dictionaries-path [path]', 'Path to save the new dictionaries'],\n ],\n };\n\n // Add pull command to dictionaries program\n const dictionariesPullCmd = dictionariesProgram\n .command('pull')\n .description(pullOptions.description);\n\n applyOptions(dictionariesPullCmd, pullOptions.options);\n applyConfigOptions(dictionariesPullCmd);\n dictionariesPullCmd.action((options) => {\n pull({\n ...options,\n configOptions: {\n ...options.configOptions,\n baseDir: options.baseDir,\n },\n });\n });\n\n // Add pull command to root program as well\n const rootPullCmd = program\n .command('pull')\n .description(pullOptions.description);\n\n applyOptions(rootPullCmd, pullOptions.options);\n applyConfigOptions(rootPullCmd);\n rootPullCmd.action((options) => {\n pull({\n ...options,\n configOptions: extractConfigOptions(options),\n });\n });\n\n // Dictionary push command\n const pushOptions = {\n description:\n 'Push all dictionaries. Create or update the pushed dictionaries',\n options: [\n ['-d, --dictionaries [ids...]', 'List of dictionary IDs to push'],\n [\n '-r, --delete-locale-dictionary',\n 'Delete the local dictionaries after pushing',\n ],\n [\n '-k, --keep-locale-dictionary',\n 'Keep the local dictionaries after pushing',\n ],\n ],\n };\n\n // Add push command to dictionaries program\n const dictionariesPushCmd = dictionariesProgram\n .command('push')\n .description(pushOptions.description);\n\n applyOptions(dictionariesPushCmd, pushOptions.options);\n applyConfigOptions(dictionariesPushCmd);\n applyGitOptions(dictionariesPushCmd);\n\n dictionariesPushCmd.action((options) =>\n push({\n ...options,\n gitOptions: extractGitOptions(options),\n configOptions: extractConfigOptions(options),\n } as FillOptions)\n );\n\n // Add push command to root program as well\n const rootPushCmd = program\n .command('push')\n .description(pushOptions.description);\n\n applyOptions(rootPushCmd, pushOptions.options);\n applyConfigOptions(rootPushCmd);\n applyGitOptions(rootPushCmd);\n\n rootPushCmd.action((options) =>\n push({\n ...options,\n gitOptions: extractGitOptions(options),\n configOptions: extractConfigOptions(options),\n } as FillOptions)\n );\n\n /**\n * CONFIGURATION\n */\n\n // Define the parent command\n const configurationProgram = program\n .command('configuration')\n .alias('config')\n .alias('conf')\n .description('Configuration operations');\n\n const configGetCmd = configurationProgram\n .command('get')\n .description('Get the configuration');\n\n applyConfigOptions(configGetCmd);\n configGetCmd.action((options) => {\n getConfig({\n ...options,\n configOptions: extractConfigOptions(options),\n });\n });\n\n // Define the `push config` subcommand and add it to the `push` command\n const configPushCmd = configurationProgram\n .command('push')\n .description('Push the configuration');\n\n applyConfigOptions(configPushCmd);\n configPushCmd.action((options) => {\n pushConfig({\n ...options,\n configOptions: extractConfigOptions(options),\n });\n });\n\n /**\n * CONTENT DECLARATION\n */\n\n const contentProgram = program\n .command('content')\n .description('Content declaration operations');\n\n contentProgram\n .command('list')\n .description('List the content declaration files')\n .action(listContentDeclaration);\n\n const testProgram = contentProgram\n .command('test')\n .description('Test if there are missing translations');\n\n applyConfigOptions(testProgram);\n testProgram.action((options) => {\n testMissingTranslations({\n ...options,\n configOptions: extractConfigOptions(options),\n });\n });\n\n const fillProgram = program\n .command('fill')\n .description('Fill the dictionaries')\n .option('-f, --file [files...]', 'List of Dictionary files to fill')\n .option('--source-locale [sourceLocale]', 'Source locale to translate from')\n .option(\n '--output-locales [outputLocales...]',\n 'Target locales to translate to'\n )\n .option(\n '--mode [mode]',\n 'Fill mode: complete, review. Complete will fill all missing content, review will fill missing content and review existing keys',\n 'complete'\n )\n .option('-k, --keys [keys...]', 'Filter dictionaries based on keys')\n .option(\n '--excluded-keys [excludedKeys...]',\n 'Filter out dictionaries based on keys'\n )\n .option(\n '--path-filter [pathFilters...]',\n 'Filter dictionaries based on glob pattern'\n )\n .option(\n '--build [build]',\n 'Build the dictionaries before filling to ensure the content is up to date'\n );\n\n applyConfigOptions(fillProgram);\n applyAIOptions(fillProgram);\n applyGitOptions(fillProgram);\n\n fillProgram.action((options) =>\n fill({\n ...options,\n aiOptions: extractAiOptions(options),\n gitOptions: extractGitOptions(options),\n configOptions: extractConfigOptions(options),\n } as FillOptions)\n );\n\n /**\n * DOCS\n */\n\n const docParams = [\n ['--doc-pattern [docPattern...]', 'Documentation pattern'],\n [\n '--excluded-glob-pattern [excludedGlobPattern...]',\n 'Excluded glob pattern',\n ],\n [\n '--nb-simultaneous-file-processed [nbSimultaneousFileProcessed]',\n 'Number of simultaneous file processed',\n ],\n ['--locales [locales...]', 'Locales'],\n ['--base-locale [baseLocale]', 'Base locale'],\n [\n '--custom-instructions [customInstructions]',\n 'Custom instructions added to the prompt. Usefull to apply specific rules regarding formatting, urls translation, etc.',\n ],\n [\n '--skip-if-modified-before [skipIfModifiedBefore]',\n 'Skip the file if it has been modified before the given time. Can be an absolute time as \"2025-12-05\" (string or Date) or a relative time in ms `1 * 60 * 60 * 1000` (1 hour). This option check update time of the file using the `fs.stat` method. So it could be impacted by Git or other tools that modify the file.',\n ],\n [\n '--skip-if-modified-after [skipIfModifiedAfter]',\n 'Skip the file if it has been modified within the given time. Can be an absolute time as \"2025-12-05\" (string or Date) or a relative time in ms `1 * 60 * 60 * 1000` (1 hour). This option check update time of the file using the `fs.stat` method. So it could be impacted by Git or other tools that modify the file.',\n ],\n ];\n\n const docProgram = program\n .command('doc')\n .description('Documentation operations');\n\n const translateProgram = docProgram\n .command('translate')\n .description('Translate the documentation');\n\n applyConfigOptions(translateProgram);\n applyAIOptions(translateProgram);\n applyGitOptions(translateProgram);\n applyOptions(translateProgram, docParams);\n\n translateProgram.action((options) =>\n translateDoc({\n docPattern: options.docPattern,\n excludedGlobPattern: options.excludedGlobPattern,\n locales: options.locales,\n baseLocale: options.baseLocale,\n aiOptions: extractAiOptions(options),\n gitOptions: extractGitOptions(options),\n nbSimultaneousFileProcessed: options.nbSimultaneousFileProcessed,\n configOptions: extractConfigOptions(options),\n customInstructions: options.customInstructions,\n skipIfModifiedBefore: options.skipIfModifiedBefore,\n skipIfModifiedAfter: options.skipIfModifiedAfter,\n })\n );\n\n const reviewProgram = docProgram\n .command('review')\n .description('Review the documentation');\n\n applyConfigOptions(reviewProgram);\n applyAIOptions(reviewProgram);\n applyGitOptions(reviewProgram);\n applyOptions(reviewProgram, docParams);\n\n reviewProgram.action((options) =>\n reviewDoc({\n docPattern: options.docPattern,\n excludedGlobPattern: options.excludedGlobPattern,\n locales: options.locales,\n baseLocale: options.baseLocale,\n aiOptions: extractAiOptions(options),\n gitOptions: extractGitOptions(options),\n nbSimultaneousFileProcessed: options.nbSimultaneousFileProcessed,\n configOptions: extractConfigOptions(options),\n customInstructions: options.customInstructions,\n skipIfModifiedBefore: options.skipIfModifiedBefore,\n skipIfModifiedAfter: options.skipIfModifiedAfter,\n })\n );\n\n /**\n * LIVE SYNC\n */\n\n const liveOptions = [\n ['--process [process]', 'Start command in parallel with the live sync'],\n ];\n\n const liveCmd = program\n .command('live')\n .description(\n 'Live sync - Watch for changes made on the CMS and update the application content accordingly'\n );\n\n applyOptions(liveCmd, liveOptions);\n\n liveCmd.action((options) => liveSync(options));\n\n /**\n * EDITOR\n */\n\n const editorProgram = program\n .command('editor')\n .description('Visual editor operations');\n\n const editorStartCmd = editorProgram\n .command('start')\n .description('Start the Intlayer visual editor');\n\n applyConfigOptions(editorStartCmd);\n\n editorStartCmd.action((options) => {\n startEditor({\n env: options.env,\n envFile: options.envFile,\n });\n });\n\n program.parse(process.argv);\n\n return program;\n};\n"],"mappings":"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","names":["pathDirname","configuration"]}
|
|
1
|
+
{"version":3,"sources":["../../src/cli.ts"],"sourcesContent":["import type { AIOptions as BaseAIOptions } from '@intlayer/api';\nimport type { GetConfigurationOptions } from '@intlayer/config';\nimport configuration from '@intlayer/config/built';\nimport { Command } from 'commander';\nimport { dirname as pathDirname } from 'path';\nimport { fileURLToPath } from 'url';\nimport {\n DiffMode,\n ListGitFilesOptions,\n} from '../../chokidar/dist/types/listGitFiles';\nimport { build } from './build';\nimport { getConfig } from './config';\nimport { startEditor } from './editor';\nimport { fill, FillOptions } from './fill';\nimport { listContentDeclaration } from './listContentDeclaration';\nimport { liveSync } from './liveSync';\nimport { pull } from './pull';\nimport { push } from './push';\nimport { pushConfig } from './pushConfig';\nimport { reviewDoc } from './reviewDoc';\nimport { testMissingTranslations } from './test';\nimport { translateDoc } from './translateDoc';\nimport { getParentPackageJSON } from './utils/getParentPackageJSON';\n\n// Extended AI options to include customPrompt\ntype AIOptions = BaseAIOptions & {\n customPrompt?: string;\n};\n\nconst isESModule = typeof import.meta.url === 'string';\n\nexport const dirname = isESModule\n ? pathDirname(fileURLToPath(import.meta.url))\n : __dirname;\n\nconst packageJson = getParentPackageJSON(dirname);\n\nconst logOptions = [\n ['--verbose', 'Verbose'],\n ['--prefix [prefix]', 'Prefix'],\n];\n\nconst configurationOptions = [\n ['--env-file [envFile]', 'Environment file'],\n ['-e, --env [env]', 'Environment'],\n ['--base-dir [baseDir]', 'Base directory'],\n ...logOptions,\n];\n\nconst aiOptions = [\n ['--provider [provider]', 'Provider'],\n ['--temperature [temperature]', 'Temperature'],\n ['--model [model]', 'Model'],\n ['--api-key [apiKey]', 'Provider API key'],\n ['--custom-prompt [prompt]', 'Custom prompt'],\n ['--application-context [applicationContext]', 'Application context'],\n];\n\nconst gitOptions = [\n ['--git-diff [gitDiff]', 'Git diff mode - Check git diff between two refs'],\n ['--git-diff-base [gitDiffBase]', 'Git diff base ref'],\n ['--git-diff-current [gitDiffCurrent]', 'Git diff current ref'],\n ['--uncommitted [uncommitted]', 'Uncommitted'],\n ['--unpushed [unpushed]', 'Unpushed'],\n ['--untracked [untracked]', 'Untracked'],\n];\n\nconst extractKeysFromOptions = (options: object, keys: string[]) =>\n keys.filter((key) => options[key as keyof typeof options]);\n\n/**\n * Helper functions to apply common options to commands\n */\nconst applyOptions = (command: Command, options: string[][]) => {\n options.forEach(([flag, description]) => command.option(flag, description));\n return command;\n};\n\nconst removeUndefined = <T extends Record<string, any>>(obj: T): T =>\n Object.fromEntries(\n Object.entries(obj).filter(([_, value]) => value !== undefined)\n ) as T;\n\nconst applyConfigOptions = (command: Command) =>\n applyOptions(command, configurationOptions);\nconst applyAIOptions = (command: Command) => applyOptions(command, aiOptions);\nconst applyGitOptions = (command: Command) => applyOptions(command, gitOptions);\n\nconst extractAiOptions = (options: AIOptions): AIOptions | undefined => {\n const {\n apiKey,\n provider,\n model,\n temperature,\n applicationContext,\n customPrompt,\n } = options;\n\n return removeUndefined({\n apiKey: apiKey ?? configuration.ai?.apiKey,\n provider: provider ?? (configuration.ai?.provider as AIOptions['provider']),\n model: model ?? configuration.ai?.model,\n temperature: temperature ?? configuration.ai?.temperature,\n applicationContext:\n applicationContext ?? configuration.ai?.applicationContext,\n customPrompt: customPrompt ?? (configuration.ai as any)?.customPrompt,\n });\n};\n\ntype GitOptions = {\n gitDiff?: boolean;\n gitDiffBase?: string;\n gitDiffCurrent?: string;\n uncommitted?: boolean;\n unpushed?: boolean;\n untracked?: boolean;\n};\n\nconst gitOptionKeys: (keyof GitOptions)[] = [\n 'gitDiff',\n 'gitDiffBase',\n 'gitDiffCurrent',\n 'uncommitted',\n 'unpushed',\n 'untracked',\n];\n\nconst extractGitOptions = (\n options: GitOptions\n): ListGitFilesOptions | undefined => {\n const filteredOptions = extractKeysFromOptions(options, gitOptionKeys);\n\n const isOptionEmpty = !Object.values(filteredOptions).some(Boolean);\n\n if (isOptionEmpty) return undefined;\n\n const {\n gitDiff,\n gitDiffBase,\n gitDiffCurrent,\n uncommitted,\n unpushed,\n untracked,\n } = options;\n\n const mode = [\n gitDiff && 'gitDiff',\n uncommitted && 'uncommitted',\n unpushed && 'unpushed',\n untracked && 'untracked',\n ].filter(Boolean) as DiffMode[];\n\n return removeUndefined({\n mode,\n baseRef: gitDiffBase,\n currentRef: gitDiffCurrent,\n absolute: true,\n });\n};\n\ntype LogOptions = {\n prefix?: string;\n verbose?: boolean;\n};\n\nexport type ConfigurationOptions = {\n baseDir?: string;\n env?: string;\n envFile?: string;\n} & LogOptions;\n\nconst configurationOptionKeys: (keyof ConfigurationOptions)[] = [\n 'baseDir',\n 'env',\n 'envFile',\n 'verbose',\n 'prefix',\n];\n\nconst extractConfigOptions = (\n options: ConfigurationOptions\n): GetConfigurationOptions | undefined => {\n const filteredOptions = extractKeysFromOptions(\n options,\n configurationOptionKeys\n );\n\n const isOptionEmpty = !Object.values(filteredOptions).some(Boolean);\n\n if (isOptionEmpty) {\n return undefined;\n }\n\n const { baseDir, env, envFile, verbose, prefix } = options;\n\n const log = {\n prefix: prefix ?? '', // Should not consider the prefix set in the intlayer configuration file\n verbose,\n };\n\n const override = {\n log,\n };\n\n return removeUndefined({\n baseDir,\n env,\n envFile,\n override,\n });\n};\n\n/**\n * Set the API for the CLI\n *\n * Example of commands:\n *\n * npm run intlayer build --watch\n * npm run intlayer push --dictionaries id1 id2 id3 --deleteLocaleDir\n */\nexport const setAPI = (): Command => {\n const program = new Command();\n\n program.version(packageJson.version!).description('Intlayer CLI');\n\n /**\n * DICTIONARIES\n */\n\n const dictionariesProgram = program\n .command('dictionary')\n .alias('dictionaries')\n .alias('dic')\n .description('Dictionaries operations');\n\n // Dictionary build command\n const buildOptions = {\n description: 'Build the dictionaries',\n options: [['-w, --watch', 'Watch for changes']],\n };\n\n // Add build command to dictionaries program\n const dictionariesBuildCmd = dictionariesProgram\n .command('build')\n .description(buildOptions.description);\n\n applyOptions(dictionariesBuildCmd, buildOptions.options);\n applyConfigOptions(dictionariesBuildCmd);\n dictionariesBuildCmd.action((options) => {\n build({\n ...options,\n configOptions: extractConfigOptions(options),\n });\n });\n\n // Add build command to root program as well\n const rootBuildCmd = program\n .command('build')\n .description(buildOptions.description);\n\n applyOptions(rootBuildCmd, buildOptions.options);\n applyConfigOptions(rootBuildCmd);\n rootBuildCmd.action((options) => {\n build({\n ...options,\n configOptions: extractConfigOptions(options),\n });\n });\n\n // Dictionary pull command\n const pullOptions = {\n description: 'Pull dictionaries from the server',\n options: [\n ['-d, --dictionaries [ids...]', 'List of dictionary IDs to pull'],\n ['--new-dictionaries-path [path]', 'Path to save the new dictionaries'],\n // Backward-compatibility for older tests/flags (camelCase)\n [\n '--newDictionariesPath [path]',\n '[alias] Path to save the new dictionaries',\n ],\n ],\n };\n\n // Add pull command to dictionaries program\n const dictionariesPullCmd = dictionariesProgram\n .command('pull')\n .description(pullOptions.description);\n\n applyOptions(dictionariesPullCmd, pullOptions.options);\n applyConfigOptions(dictionariesPullCmd);\n dictionariesPullCmd.action((options) => {\n pull({\n ...options,\n configOptions: {\n ...options.configOptions,\n baseDir: options.baseDir,\n },\n });\n });\n\n // Add pull command to root program as well\n const rootPullCmd = program\n .command('pull')\n .description(pullOptions.description);\n\n applyOptions(rootPullCmd, pullOptions.options);\n applyConfigOptions(rootPullCmd);\n rootPullCmd.action((options) => {\n pull({\n ...options,\n configOptions: extractConfigOptions(options),\n });\n });\n\n // Dictionary push command\n const pushOptions = {\n description:\n 'Push all dictionaries. Create or update the pushed dictionaries',\n options: [\n ['-d, --dictionaries [ids...]', 'List of dictionary IDs to push'],\n [\n '-r, --delete-locale-dictionary',\n 'Delete the local dictionaries after pushing',\n ],\n [\n '-k, --keep-locale-dictionary',\n 'Keep the local dictionaries after pushing',\n ],\n // Backward-compatibility for older tests/flags (camelCase)\n [\n '--deleteLocaleDictionary',\n '[alias] Delete the local dictionaries after pushing',\n ],\n [\n '--keepLocaleDictionary',\n '[alias] Keep the local dictionaries after pushing',\n ],\n ],\n };\n\n // Add push command to dictionaries program\n const dictionariesPushCmd = dictionariesProgram\n .command('push')\n .description(pushOptions.description);\n\n applyOptions(dictionariesPushCmd, pushOptions.options);\n applyConfigOptions(dictionariesPushCmd);\n applyGitOptions(dictionariesPushCmd);\n\n dictionariesPushCmd.action((options) =>\n push({\n ...options,\n gitOptions: extractGitOptions(options),\n configOptions: extractConfigOptions(options),\n } as FillOptions)\n );\n\n // Add push command to root program as well\n const rootPushCmd = program\n .command('push')\n .description(pushOptions.description);\n\n applyOptions(rootPushCmd, pushOptions.options);\n applyConfigOptions(rootPushCmd);\n applyGitOptions(rootPushCmd);\n\n rootPushCmd.action((options) =>\n push({\n ...options,\n gitOptions: extractGitOptions(options),\n configOptions: extractConfigOptions(options),\n } as FillOptions)\n );\n\n /**\n * CONFIGURATION\n */\n\n // Define the parent command\n const configurationProgram = program\n .command('configuration')\n .alias('config')\n .alias('conf')\n .description('Configuration operations');\n\n const configGetCmd = configurationProgram\n .command('get')\n .description('Get the configuration');\n\n applyConfigOptions(configGetCmd);\n configGetCmd.action((options) => {\n getConfig({\n ...options,\n configOptions: extractConfigOptions(options),\n });\n });\n\n // Define the `push config` subcommand and add it to the `push` command\n const configPushCmd = configurationProgram\n .command('push')\n .description('Push the configuration');\n\n applyConfigOptions(configPushCmd);\n configPushCmd.action((options) => {\n pushConfig({\n ...options,\n configOptions: extractConfigOptions(options),\n });\n });\n\n /**\n * CONTENT DECLARATION\n */\n\n const contentProgram = program\n .command('content')\n .description('Content declaration operations');\n\n contentProgram\n .command('list')\n .description('List the content declaration files')\n .action(listContentDeclaration);\n\n const testProgram = contentProgram\n .command('test')\n .description('Test if there are missing translations');\n\n applyConfigOptions(testProgram);\n testProgram.action((options) => {\n testMissingTranslations({\n ...options,\n configOptions: extractConfigOptions(options),\n });\n });\n\n const fillProgram = program\n .command('fill')\n .description('Fill the dictionaries')\n .option('-f, --file [files...]', 'List of Dictionary files to fill')\n .option('--source-locale [sourceLocale]', 'Source locale to translate from')\n .option(\n '--output-locales [outputLocales...]',\n 'Target locales to translate to'\n )\n .option(\n '--mode [mode]',\n 'Fill mode: complete, review. Complete will fill all missing content, review will fill missing content and review existing keys',\n 'complete'\n )\n .option('-k, --keys [keys...]', 'Filter dictionaries based on keys')\n .option(\n '--excluded-keys [excludedKeys...]',\n 'Filter out dictionaries based on keys'\n )\n .option(\n '--path-filter [pathFilters...]',\n 'Filter dictionaries based on glob pattern'\n )\n .option(\n '--build [build]',\n 'Build the dictionaries before filling to ensure the content is up to date'\n );\n\n applyConfigOptions(fillProgram);\n applyAIOptions(fillProgram);\n applyGitOptions(fillProgram);\n\n fillProgram.action((options) =>\n fill({\n ...options,\n aiOptions: extractAiOptions(options),\n gitOptions: extractGitOptions(options),\n configOptions: extractConfigOptions(options),\n } as FillOptions)\n );\n\n /**\n * DOCS\n */\n\n const docParams = [\n ['--doc-pattern [docPattern...]', 'Documentation pattern'],\n [\n '--excluded-glob-pattern [excludedGlobPattern...]',\n 'Excluded glob pattern',\n ],\n [\n '--nb-simultaneous-file-processed [nbSimultaneousFileProcessed]',\n 'Number of simultaneous file processed',\n ],\n ['--locales [locales...]', 'Locales'],\n ['--base-locale [baseLocale]', 'Base locale'],\n [\n '--custom-instructions [customInstructions]',\n 'Custom instructions added to the prompt. Usefull to apply specific rules regarding formatting, urls translation, etc.',\n ],\n [\n '--skip-if-modified-before [skipIfModifiedBefore]',\n 'Skip the file if it has been modified before the given time. Can be an absolute time as \"2025-12-05\" (string or Date) or a relative time in ms `1 * 60 * 60 * 1000` (1 hour). This option check update time of the file using the `fs.stat` method. So it could be impacted by Git or other tools that modify the file.',\n ],\n [\n '--skip-if-modified-after [skipIfModifiedAfter]',\n 'Skip the file if it has been modified within the given time. Can be an absolute time as \"2025-12-05\" (string or Date) or a relative time in ms `1 * 60 * 60 * 1000` (1 hour). This option check update time of the file using the `fs.stat` method. So it could be impacted by Git or other tools that modify the file.',\n ],\n ];\n\n const docProgram = program\n .command('doc')\n .description('Documentation operations');\n\n const translateProgram = docProgram\n .command('translate')\n .description('Translate the documentation');\n\n applyConfigOptions(translateProgram);\n applyAIOptions(translateProgram);\n applyGitOptions(translateProgram);\n applyOptions(translateProgram, docParams);\n\n translateProgram.action((options) =>\n translateDoc({\n docPattern: options.docPattern,\n excludedGlobPattern: options.excludedGlobPattern,\n locales: options.locales,\n baseLocale: options.baseLocale,\n aiOptions: extractAiOptions(options),\n gitOptions: extractGitOptions(options),\n nbSimultaneousFileProcessed: options.nbSimultaneousFileProcessed,\n configOptions: extractConfigOptions(options),\n customInstructions: options.customInstructions,\n skipIfModifiedBefore: options.skipIfModifiedBefore,\n skipIfModifiedAfter: options.skipIfModifiedAfter,\n })\n );\n\n const reviewProgram = docProgram\n .command('review')\n .description('Review the documentation');\n\n applyConfigOptions(reviewProgram);\n applyAIOptions(reviewProgram);\n applyGitOptions(reviewProgram);\n applyOptions(reviewProgram, docParams);\n\n reviewProgram.action((options) =>\n reviewDoc({\n docPattern: options.docPattern,\n excludedGlobPattern: options.excludedGlobPattern,\n locales: options.locales,\n baseLocale: options.baseLocale,\n aiOptions: extractAiOptions(options),\n gitOptions: extractGitOptions(options),\n nbSimultaneousFileProcessed: options.nbSimultaneousFileProcessed,\n configOptions: extractConfigOptions(options),\n customInstructions: options.customInstructions,\n skipIfModifiedBefore: options.skipIfModifiedBefore,\n skipIfModifiedAfter: options.skipIfModifiedAfter,\n })\n );\n\n /**\n * LIVE SYNC\n */\n\n const liveOptions = [\n ['--process [process]', 'Start command in parallel with the live sync'],\n ];\n\n const liveCmd = program\n .command('live')\n .description(\n 'Live sync - Watch for changes made on the CMS and update the application content accordingly'\n );\n\n applyOptions(liveCmd, liveOptions);\n\n liveCmd.action((options) => liveSync(options));\n\n /**\n * EDITOR\n */\n\n const editorProgram = program\n .command('editor')\n .description('Visual editor operations');\n\n const editorStartCmd = editorProgram\n .command('start')\n .description('Start the Intlayer visual editor');\n\n applyConfigOptions(editorStartCmd);\n\n editorStartCmd.action((options) => {\n startEditor({\n env: options.env,\n envFile: options.envFile,\n });\n });\n\n program.parse(process.argv);\n\n return program;\n};\n"],"mappings":"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","names":["pathDirname","configuration"]}
|
package/dist/cjs/reviewDoc.cjs
CHANGED
|
@@ -51,9 +51,8 @@ var import_getOutputFilePath = require('./utils/getOutputFilePath.cjs');
|
|
|
51
51
|
const import_meta = {};
|
|
52
52
|
const isESModule = typeof import_meta.url === "string";
|
|
53
53
|
const dir = isESModule ? (0, import_path.dirname)((0, import_url.fileURLToPath)(import_meta.url)) : __dirname;
|
|
54
|
-
const reviewFile = async (baseFilePath, outputFilePath, locale, baseLocale, aiOptions,
|
|
54
|
+
const reviewFile = async (baseFilePath, outputFilePath, locale, baseLocale, aiOptions, configuration = (0, import_config.getConfiguration)(), customInstructions, changedLines) => {
|
|
55
55
|
try {
|
|
56
|
-
const configuration = (0, import_config.getConfiguration)(configOptions);
|
|
57
56
|
const appLogger = (0, import_config.getAppLogger)(configuration, {
|
|
58
57
|
config: {
|
|
59
58
|
prefix: ""
|
|
@@ -71,10 +70,7 @@ const reviewFile = async (baseFilePath, outputFilePath, locale, baseLocale, aiOp
|
|
|
71
70
|
`\u2192 ${import_config.ANSIColors.RESET}`
|
|
72
71
|
].join("");
|
|
73
72
|
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}] `;
|
|
74
|
-
const prefix = [
|
|
75
|
-
(0, import_config.colon)(prefixText, { colSize: 40 }),
|
|
76
|
-
`\u2192 ${import_config.ANSIColors.RESET}`
|
|
77
|
-
].join("");
|
|
73
|
+
const prefix = [(0, import_config.colon)(prefixText, { colSize: 40 })].join("");
|
|
78
74
|
appLogger(
|
|
79
75
|
`${filePrefix}Base file splitted into ${(0, import_config.colorizeNumber)(baseChunks.length)} chunks`
|
|
80
76
|
);
|
|
@@ -116,10 +112,18 @@ const reviewFile = async (baseFilePath, outputFilePath, locale, baseLocale, aiOp
|
|
|
116
112
|
{ role: "user", content: baseChunkContext.content }
|
|
117
113
|
],
|
|
118
114
|
aiOptions,
|
|
119
|
-
|
|
115
|
+
configuration
|
|
120
116
|
);
|
|
121
117
|
appLogger(
|
|
122
|
-
|
|
118
|
+
[
|
|
119
|
+
`${prefix}`,
|
|
120
|
+
`${import_config.ANSIColors.GREY_DARK}[Chunk `,
|
|
121
|
+
(0, import_config.colorizeNumber)(i + 1),
|
|
122
|
+
`${import_config.ANSIColors.GREY_DARK} of `,
|
|
123
|
+
(0, import_config.colorizeNumber)(baseChunks.length),
|
|
124
|
+
`${import_config.ANSIColors.GREY_DARK}] \u2192${import_config.ANSIColors.RESET} `,
|
|
125
|
+
`${(0, import_config.colorizeNumber)(result.tokenUsed)} tokens used`
|
|
126
|
+
].join("")
|
|
123
127
|
);
|
|
124
128
|
const fixedReviewedChunkResult = (0, import_fixChunkStartEndChars.fixChunkStartEndChars)(
|
|
125
129
|
result?.fileContent,
|
|
@@ -222,7 +226,7 @@ const reviewDoc = async ({
|
|
|
222
226
|
locale,
|
|
223
227
|
baseLocale,
|
|
224
228
|
aiOptions,
|
|
225
|
-
|
|
229
|
+
configuration,
|
|
226
230
|
customInstructions,
|
|
227
231
|
changedLines
|
|
228
232
|
);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/reviewDoc.ts"],"sourcesContent":["import { AIOptions } from '@intlayer/api'; // OAuth handled by API proxy\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/checkAccess';\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 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 configOptions\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 const hasCMSAuth = await checkAIAccess(configuration, aiOptions);\n\n if (!hasCMSAuth) return;\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 // OAuth handled by API proxy internally\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 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 } from '@intlayer/api'; // OAuth handled by API proxy\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 IntlayerConfig,\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/checkAccess';\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 configuration: IntlayerConfig = getConfiguration(),\n customInstructions?: string,\n changedLines?: number[]\n) => {\n try {\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 = [colon(prefixText, { colSize: 40 })].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 configuration\n );\n\n appLogger(\n [\n `${prefix}`,\n `${ANSIColors.GREY_DARK}[Chunk `,\n colorizeNumber(i + 1),\n `${ANSIColors.GREY_DARK} of `,\n colorizeNumber(baseChunks.length),\n `${ANSIColors.GREY_DARK}] →${ANSIColors.RESET} `,\n `${colorizeNumber(result.tokenUsed)} tokens used`,\n ].join('')\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 const hasCMSAuth = await checkAIAccess(configuration, aiOptions);\n\n if (!hasCMSAuth) return;\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 // OAuth handled by API proxy internally\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 configuration,\n customInstructions,\n changedLines\n );\n })\n )\n );\n\n await Promise.all(tasks);\n};\n"],"mappings":"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","names":["pLimit","fg"]}
|
|
@@ -50,9 +50,8 @@ var import_getOutputFilePath = require('./utils/getOutputFilePath.cjs');
|
|
|
50
50
|
const import_meta = {};
|
|
51
51
|
const isESModule = typeof import_meta.url === "string";
|
|
52
52
|
const dir = isESModule ? (0, import_path.dirname)((0, import_url.fileURLToPath)(import_meta.url)) : __dirname;
|
|
53
|
-
const translateFile = async (baseFilePath, outputFilePath, locale, baseLocale, aiOptions,
|
|
53
|
+
const translateFile = async (baseFilePath, outputFilePath, locale, baseLocale, aiOptions, configuration = (0, import_config.getConfiguration)(), customInstructions) => {
|
|
54
54
|
try {
|
|
55
|
-
const configuration = (0, import_config.getConfiguration)(configOptions);
|
|
56
55
|
const appLogger = (0, import_config.getAppLogger)(configuration, {
|
|
57
56
|
config: {
|
|
58
57
|
prefix: ""
|
|
@@ -95,10 +94,18 @@ const translateFile = async (baseFilePath, outputFilePath, locale, baseLocale, a
|
|
|
95
94
|
{ role: "user", content: fileToTranslateCurrentChunk }
|
|
96
95
|
],
|
|
97
96
|
aiOptions,
|
|
98
|
-
|
|
97
|
+
configuration
|
|
99
98
|
);
|
|
100
99
|
appLogger(
|
|
101
|
-
|
|
100
|
+
[
|
|
101
|
+
`${prefix}`,
|
|
102
|
+
`${import_config.ANSIColors.GREY_DARK}[Chunk `,
|
|
103
|
+
(0, import_config.colorizeNumber)(i + 1),
|
|
104
|
+
`${import_config.ANSIColors.GREY_DARK} of `,
|
|
105
|
+
(0, import_config.colorizeNumber)(chunks.length),
|
|
106
|
+
`${import_config.ANSIColors.GREY_DARK}] \u2192${import_config.ANSIColors.RESET} `,
|
|
107
|
+
`${(0, import_config.colorizeNumber)(result.tokenUsed)} tokens used`
|
|
108
|
+
].join("")
|
|
102
109
|
);
|
|
103
110
|
const fixedTranslatedChunkResult = (0, import_fixChunkStartEndChars.fixChunkStartEndChars)(
|
|
104
111
|
result?.fileContent,
|
|
@@ -204,7 +211,7 @@ const translateDoc = async ({
|
|
|
204
211
|
locale,
|
|
205
212
|
baseLocale,
|
|
206
213
|
aiOptions,
|
|
207
|
-
|
|
214
|
+
configuration,
|
|
208
215
|
customInstructions
|
|
209
216
|
);
|
|
210
217
|
})
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/translateDoc.ts"],"sourcesContent":["import { AIOptions } from '@intlayer/api';\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 fg from 'fast-glob';\nimport { existsSync, 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/checkAccess';\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 translateFile = async (\n baseFilePath: string,\n outputFilePath: string,\n locale: Locales,\n baseLocale: Locales,\n aiOptions?: AIOptions,\n configOptions?: GetConfigurationOptions,\n customInstructions?: string\n) => {\n try {\n const configuration = getConfiguration(configOptions);\n const appLogger = getAppLogger(configuration, {\n config: {\n prefix: '',\n },\n });\n\n // Determine the target locale file path\n const fileContent = await readFile(baseFilePath, 'utf-8');\n let fileResultContent = fileContent;\n\n // Prepare the base prompt for ChatGPT\n const basePrompt = (\n await readFile(join(dir, './prompts/TRANSLATE_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 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 // 1. Chunk the file by number of lines instead of characters\n const chunks = chunkText(fileContent);\n appLogger(\n `${filePrefix}Base file splitted into ${colorizeNumber(chunks.length)} chunks`\n );\n\n for await (const [i, chunk] of chunks.entries()) {\n const isFirstChunk = i === 0;\n\n // Build the chunk-specific prompt\n const getPrevChunkPrompt = () =>\n `**CHUNK ${i} of ${chunks.length}** that has been translated in ${formatLocale(locale)}:\\n` +\n `///chunkStart///` +\n getChunk(fileResultContent, chunks[i - 1]) +\n `///chunkEnd///`;\n\n const getBaseChunkContextPrompt = () =>\n `**CHUNK ${i + 1} to ${Math.min(i + 3, chunks.length)} of ${chunks.length}** is the base chunk in ${formatLocale(baseLocale, false)} as reference.\\n` +\n `///chunksStart///` +\n (chunks[i - 1]?.content ?? '') +\n chunks[i].content +\n (chunks[i + 1]?.content ?? '') +\n `///chunksEnd///`;\n\n const fileToTranslateCurrentChunk = chunk.content;\n\n // Make the actual translation call\n let chunkTranslation = await retryManager(async () => {\n const result = await chunkInference(\n [\n { role: 'system', content: basePrompt },\n\n { role: 'system', content: getBaseChunkContextPrompt() },\n ...(isFirstChunk\n ? []\n : [{ role: 'system', content: getPrevChunkPrompt() } as const]),\n {\n role: 'system',\n content: `The next user message will be the **CHUNK ${colorizeNumber(i + 1)} of ${colorizeNumber(chunks.length)}** in ${formatLocale(baseLocale, false)} to translate in ${formatLocale(locale, false)}:`,\n },\n { role: 'user', content: fileToTranslateCurrentChunk },\n ],\n aiOptions,\n configOptions\n );\n\n appLogger(\n `${prefix}${colorizeNumber(result.tokenUsed)} tokens used - Chunk ${colorizeNumber(i + 1)} of ${colorizeNumber(chunks.length)}`\n );\n\n const fixedTranslatedChunkResult = fixChunkStartEndChars(\n result?.fileContent,\n fileToTranslateCurrentChunk\n );\n\n return fixedTranslatedChunkResult;\n })();\n\n // Replace the chunk in the file content\n fileResultContent = fileResultContent.replace(\n fileToTranslateCurrentChunk,\n chunkTranslation\n );\n }\n\n // 4. Write the final translation to the appropriate file path\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 TranslateDocOptions = {\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 translate function: scans all .md files in \"en/\" (unless you specified DOC_LIST),\n * then translates them to each locale in LOCALE_LIST.\n */\nexport const translateDoc = async ({\n docPattern,\n locales,\n excludedGlobPattern,\n baseLocale,\n aiOptions,\n nbSimultaneousFileProcessed,\n configOptions,\n customInstructions,\n skipIfModifiedBefore,\n skipIfModifiedAfter,\n gitOptions,\n}: TranslateDocOptions) => {\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 const hasCMSAuth = await checkAIAccess(configuration, aiOptions);\n\n if (!hasCMSAuth) return;\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 // OAuth handled by API proxy internally\n\n appLogger(`Base locale is ${formatLocale(baseLocale)}`);\n appLogger(\n `Translating ${colorizeNumber(locales.length)} locales: [ ${formatLocale(locales)} ]`\n );\n\n appLogger(`Translating ${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 `Translating 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 // check if the file exist, otherwise create it\n if (!existsSync(outputFilePath)) {\n appLogger(`File ${outputFilePath} does not exist, creating it...`);\n mkdirSync(dirname(outputFilePath), { recursive: true });\n writeFileSync(outputFilePath, '');\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 await translateFile(\n absoluteBaseFilePath,\n outputFilePath,\n locale as Locales,\n baseLocale,\n aiOptions,\n configOptions,\n customInstructions\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/translateDoc.ts"],"sourcesContent":["import { AIOptions } from '@intlayer/api';\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 IntlayerConfig,\n Locales,\n retryManager,\n} from '@intlayer/config';\nimport fg from 'fast-glob';\nimport { existsSync, 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/checkAccess';\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 translateFile = async (\n baseFilePath: string,\n outputFilePath: string,\n locale: Locales,\n baseLocale: Locales,\n aiOptions?: AIOptions,\n configuration: IntlayerConfig = getConfiguration(),\n customInstructions?: string\n) => {\n try {\n const appLogger = getAppLogger(configuration, {\n config: {\n prefix: '',\n },\n });\n\n // Determine the target locale file path\n const fileContent = await readFile(baseFilePath, 'utf-8');\n let fileResultContent = fileContent;\n\n // Prepare the base prompt for ChatGPT\n const basePrompt = (\n await readFile(join(dir, './prompts/TRANSLATE_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 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 // 1. Chunk the file by number of lines instead of characters\n const chunks = chunkText(fileContent);\n appLogger(\n `${filePrefix}Base file splitted into ${colorizeNumber(chunks.length)} chunks`\n );\n\n for await (const [i, chunk] of chunks.entries()) {\n const isFirstChunk = i === 0;\n\n // Build the chunk-specific prompt\n const getPrevChunkPrompt = () =>\n `**CHUNK ${i} of ${chunks.length}** that has been translated in ${formatLocale(locale)}:\\n` +\n `///chunkStart///` +\n getChunk(fileResultContent, chunks[i - 1]) +\n `///chunkEnd///`;\n\n const getBaseChunkContextPrompt = () =>\n `**CHUNK ${i + 1} to ${Math.min(i + 3, chunks.length)} of ${chunks.length}** is the base chunk in ${formatLocale(baseLocale, false)} as reference.\\n` +\n `///chunksStart///` +\n (chunks[i - 1]?.content ?? '') +\n chunks[i].content +\n (chunks[i + 1]?.content ?? '') +\n `///chunksEnd///`;\n\n const fileToTranslateCurrentChunk = chunk.content;\n\n // Make the actual translation call\n let chunkTranslation = await retryManager(async () => {\n const result = await chunkInference(\n [\n { role: 'system', content: basePrompt },\n\n { role: 'system', content: getBaseChunkContextPrompt() },\n ...(isFirstChunk\n ? []\n : [{ role: 'system', content: getPrevChunkPrompt() } as const]),\n {\n role: 'system',\n content: `The next user message will be the **CHUNK ${colorizeNumber(i + 1)} of ${colorizeNumber(chunks.length)}** in ${formatLocale(baseLocale, false)} to translate in ${formatLocale(locale, false)}:`,\n },\n { role: 'user', content: fileToTranslateCurrentChunk },\n ],\n aiOptions,\n configuration\n );\n\n appLogger(\n [\n `${prefix}`,\n `${ANSIColors.GREY_DARK}[Chunk `,\n colorizeNumber(i + 1),\n `${ANSIColors.GREY_DARK} of `,\n colorizeNumber(chunks.length),\n `${ANSIColors.GREY_DARK}] →${ANSIColors.RESET} `,\n `${colorizeNumber(result.tokenUsed)} tokens used`,\n ].join('')\n );\n\n const fixedTranslatedChunkResult = fixChunkStartEndChars(\n result?.fileContent,\n fileToTranslateCurrentChunk\n );\n\n return fixedTranslatedChunkResult;\n })();\n\n // Replace the chunk in the file content\n fileResultContent = fileResultContent.replace(\n fileToTranslateCurrentChunk,\n chunkTranslation\n );\n }\n\n // 4. Write the final translation to the appropriate file path\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 TranslateDocOptions = {\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 translate function: scans all .md files in \"en/\" (unless you specified DOC_LIST),\n * then translates them to each locale in LOCALE_LIST.\n */\nexport const translateDoc = async ({\n docPattern,\n locales,\n excludedGlobPattern,\n baseLocale,\n aiOptions,\n nbSimultaneousFileProcessed,\n configOptions,\n customInstructions,\n skipIfModifiedBefore,\n skipIfModifiedAfter,\n gitOptions,\n}: TranslateDocOptions) => {\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 const hasCMSAuth = await checkAIAccess(configuration, aiOptions);\n\n if (!hasCMSAuth) return;\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 // OAuth handled by API proxy internally\n\n appLogger(`Base locale is ${formatLocale(baseLocale)}`);\n appLogger(\n `Translating ${colorizeNumber(locales.length)} locales: [ ${formatLocale(locales)} ]`\n );\n\n appLogger(`Translating ${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 `Translating 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 // check if the file exist, otherwise create it\n if (!existsSync(outputFilePath)) {\n appLogger(`File ${outputFilePath} does not exist, creating it...`);\n mkdirSync(dirname(outputFilePath), { recursive: true });\n writeFileSync(outputFilePath, '');\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 await translateFile(\n absoluteBaseFilePath,\n outputFilePath,\n locale as Locales,\n baseLocale,\n aiOptions,\n configuration,\n customInstructions\n );\n })\n )\n );\n\n await Promise.all(tasks);\n};\n"],"mappings":"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","names":["pLimit","fg"]}
|
|
@@ -23,6 +23,7 @@ __export(checkAccess_exports, {
|
|
|
23
23
|
});
|
|
24
24
|
module.exports = __toCommonJS(checkAccess_exports);
|
|
25
25
|
var import_api = require("@intlayer/api");
|
|
26
|
+
var import_chokidar = require("@intlayer/chokidar");
|
|
26
27
|
var import_config = require("@intlayer/config");
|
|
27
28
|
const checkCMSAuth = async (configuration) => {
|
|
28
29
|
const appLogger = (0, import_config.getAppLogger)(configuration, {
|
|
@@ -41,13 +42,7 @@ const checkCMSAuth = async (configuration) => {
|
|
|
41
42
|
try {
|
|
42
43
|
await intlayerAPI.oAuth.getOAuth2AccessToken();
|
|
43
44
|
} catch (error) {
|
|
44
|
-
|
|
45
|
-
try {
|
|
46
|
-
const jsonError = JSON.parse(error.message);
|
|
47
|
-
message = jsonError?.message ?? jsonError;
|
|
48
|
-
} catch (error2) {
|
|
49
|
-
message = `${error2.message} Error getting OAuth2 access token. Your token might be expired.`;
|
|
50
|
-
}
|
|
45
|
+
const message = (0, import_chokidar.extractErrorMessage)(error);
|
|
51
46
|
appLogger(message, {
|
|
52
47
|
level: "error"
|
|
53
48
|
});
|
|
@@ -69,7 +64,10 @@ const checkAIAccess = async (configuration, aiOptions) => {
|
|
|
69
64
|
});
|
|
70
65
|
return false;
|
|
71
66
|
}
|
|
72
|
-
|
|
67
|
+
if (!hasHisOwnAIAPIKey) {
|
|
68
|
+
return await checkCMSAuth(configuration);
|
|
69
|
+
}
|
|
70
|
+
return true;
|
|
73
71
|
};
|
|
74
72
|
// Annotate the CommonJS export names for ESM import in node:
|
|
75
73
|
0 && (module.exports = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/utils/checkAccess.ts"],"sourcesContent":["import type { AIOptions } from '@intlayer/api';\nimport { getIntlayerAPIProxy } from '@intlayer/api';\nimport { getAppLogger, type IntlayerConfig } from '@intlayer/config';\n\nexport const checkCMSAuth = async (\n configuration: IntlayerConfig\n): Promise<boolean> => {\n const appLogger = getAppLogger(configuration, {\n config: {\n prefix: '',\n },\n });\n\n const hasCMSAuth =\n configuration.editor.clientId && configuration.editor.clientSecret;\n if (!hasCMSAuth) {\n appLogger('CMS auth not provided.', {\n level: 'error',\n });\n\n return false;\n }\n const intlayerAPI = getIntlayerAPIProxy(undefined, configuration);\n\n try {\n await intlayerAPI.oAuth.getOAuth2AccessToken();\n } catch (error) {\n
|
|
1
|
+
{"version":3,"sources":["../../../src/utils/checkAccess.ts"],"sourcesContent":["import type { AIOptions } from '@intlayer/api';\nimport { getIntlayerAPIProxy } from '@intlayer/api';\nimport { extractErrorMessage } from '@intlayer/chokidar';\nimport { getAppLogger, type IntlayerConfig } from '@intlayer/config';\n\nexport const checkCMSAuth = async (\n configuration: IntlayerConfig\n): Promise<boolean> => {\n const appLogger = getAppLogger(configuration, {\n config: {\n prefix: '',\n },\n });\n\n const hasCMSAuth =\n configuration.editor.clientId && configuration.editor.clientSecret;\n if (!hasCMSAuth) {\n appLogger('CMS auth not provided.', {\n level: 'error',\n });\n\n return false;\n }\n const intlayerAPI = getIntlayerAPIProxy(undefined, configuration);\n\n try {\n await intlayerAPI.oAuth.getOAuth2AccessToken();\n } catch (error) {\n const message = extractErrorMessage(error);\n\n appLogger(message, {\n level: 'error',\n });\n return false;\n }\n\n return true;\n};\n\nexport const checkAIAccess = async (\n configuration: IntlayerConfig,\n aiOptions?: AIOptions\n): Promise<boolean> => {\n const appLogger = getAppLogger(configuration, {\n config: {\n prefix: '',\n },\n });\n\n const hasCMSAuth =\n configuration.editor.clientId && configuration.editor.clientSecret;\n const hasHisOwnAIAPIKey = configuration.ai?.apiKey || aiOptions?.apiKey;\n\n // User need to provide either his own AI API key or the CMS auth\n if (!hasCMSAuth && !hasHisOwnAIAPIKey) {\n appLogger('AI options or API key not provided.', {\n level: 'error',\n });\n\n return false;\n }\n\n // If the user do not have his own AI API key, we need to check the CMS auth\n if (!hasHisOwnAIAPIKey) {\n return await checkCMSAuth(configuration);\n }\n\n return true;\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,iBAAoC;AACpC,sBAAoC;AACpC,oBAAkD;AAE3C,MAAM,eAAe,OAC1B,kBACqB;AACrB,QAAM,gBAAY,4BAAa,eAAe;AAAA,IAC5C,QAAQ;AAAA,MACN,QAAQ;AAAA,IACV;AAAA,EACF,CAAC;AAED,QAAM,aACJ,cAAc,OAAO,YAAY,cAAc,OAAO;AACxD,MAAI,CAAC,YAAY;AACf,cAAU,0BAA0B;AAAA,MAClC,OAAO;AAAA,IACT,CAAC;AAED,WAAO;AAAA,EACT;AACA,QAAM,kBAAc,gCAAoB,QAAW,aAAa;AAEhE,MAAI;AACF,UAAM,YAAY,MAAM,qBAAqB;AAAA,EAC/C,SAAS,OAAO;AACd,UAAM,cAAU,qCAAoB,KAAK;AAEzC,cAAU,SAAS;AAAA,MACjB,OAAO;AAAA,IACT,CAAC;AACD,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAEO,MAAM,gBAAgB,OAC3B,eACA,cACqB;AACrB,QAAM,gBAAY,4BAAa,eAAe;AAAA,IAC5C,QAAQ;AAAA,MACN,QAAQ;AAAA,IACV;AAAA,EACF,CAAC;AAED,QAAM,aACJ,cAAc,OAAO,YAAY,cAAc,OAAO;AACxD,QAAM,oBAAoB,cAAc,IAAI,UAAU,WAAW;AAGjE,MAAI,CAAC,cAAc,CAAC,mBAAmB;AACrC,cAAU,uCAAuC;AAAA,MAC/C,OAAO;AAAA,IACT,CAAC;AAED,WAAO;AAAA,EACT;AAGA,MAAI,CAAC,mBAAmB;AACtB,WAAO,MAAM,aAAa,aAAa;AAAA,EACzC;AAEA,SAAO;AACT;","names":[]}
|
|
@@ -23,10 +23,9 @@ __export(chunkInference_exports, {
|
|
|
23
23
|
module.exports = __toCommonJS(chunkInference_exports);
|
|
24
24
|
var import_api = require("@intlayer/api");
|
|
25
25
|
var import_config = require("@intlayer/config");
|
|
26
|
-
const chunkInference = async (messages, aiOptions,
|
|
26
|
+
const chunkInference = async (messages, aiOptions, configuration) => {
|
|
27
27
|
let lastResult;
|
|
28
28
|
await (0, import_config.retryManager)(async () => {
|
|
29
|
-
const configuration = (0, import_config.getConfiguration)(configOptions);
|
|
30
29
|
const api = (0, import_api.getIntlayerAPIProxy)(void 0, configuration);
|
|
31
30
|
const response = await api.ai.customQuery({
|
|
32
31
|
aiOptions,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/utils/chunkInference.ts"],"sourcesContent":["import {\n type AIOptions,\n getIntlayerAPIProxy,\n type Messages,\n} from '@intlayer/api';\nimport {
|
|
1
|
+
{"version":3,"sources":["../../../src/utils/chunkInference.ts"],"sourcesContent":["import {\n type AIOptions,\n getIntlayerAPIProxy,\n type Messages,\n} from '@intlayer/api';\nimport { type IntlayerConfig, retryManager } from '@intlayer/config';\n\ntype ChunkInferenceResult = {\n fileContent: string;\n tokenUsed: number;\n};\n\n/**\n * Translates a single chunk via the OpenAI API.\n * Includes retry logic if the call fails.\n */\nexport const chunkInference = async (\n messages: Messages,\n aiOptions?: AIOptions,\n configuration?: IntlayerConfig\n): Promise<ChunkInferenceResult> => {\n let lastResult: ChunkInferenceResult;\n\n await retryManager(async () => {\n const api = getIntlayerAPIProxy(undefined, configuration);\n\n const response = await api.ai.customQuery({\n aiOptions,\n messages,\n });\n\n if (!response.data) {\n throw new Error('No response from AI API');\n }\n\n const { fileContent, tokenUsed } = response.data;\n\n const newContent = fileContent\n .replaceAll('///chunksStart///', '')\n .replaceAll('///chunkStart///', '')\n .replaceAll('///chunksEnd///', '')\n .replaceAll('///chunkEnd///', '')\n .replaceAll('///chunksStart///', '')\n .replaceAll('chunkStart///', '')\n .replaceAll('chunksEnd///', '')\n .replaceAll('chunkEnd///', '')\n .replaceAll('///chunksStart', '')\n .replaceAll('///chunkStart', '')\n .replaceAll('///chunksEnd', '')\n .replaceAll('///chunkEnd', '')\n .replaceAll('chunksStart', '')\n .replaceAll('chunkStart', '')\n .replaceAll('chunksEnd', '')\n .replaceAll('chunkEnd', '');\n\n lastResult = {\n fileContent: newContent,\n tokenUsed,\n };\n })();\n\n return lastResult!;\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iBAIO;AACP,oBAAkD;AAW3C,MAAM,iBAAiB,OAC5B,UACA,WACA,kBACkC;AAClC,MAAI;AAEJ,YAAM,4BAAa,YAAY;AAC7B,UAAM,UAAM,gCAAoB,QAAW,aAAa;AAExD,UAAM,WAAW,MAAM,IAAI,GAAG,YAAY;AAAA,MACxC;AAAA,MACA;AAAA,IACF,CAAC;AAED,QAAI,CAAC,SAAS,MAAM;AAClB,YAAM,IAAI,MAAM,yBAAyB;AAAA,IAC3C;AAEA,UAAM,EAAE,aAAa,UAAU,IAAI,SAAS;AAE5C,UAAM,aAAa,YAChB,WAAW,qBAAqB,EAAE,EAClC,WAAW,oBAAoB,EAAE,EACjC,WAAW,mBAAmB,EAAE,EAChC,WAAW,kBAAkB,EAAE,EAC/B,WAAW,qBAAqB,EAAE,EAClC,WAAW,iBAAiB,EAAE,EAC9B,WAAW,gBAAgB,EAAE,EAC7B,WAAW,eAAe,EAAE,EAC5B,WAAW,kBAAkB,EAAE,EAC/B,WAAW,iBAAiB,EAAE,EAC9B,WAAW,gBAAgB,EAAE,EAC7B,WAAW,eAAe,EAAE,EAC5B,WAAW,eAAe,EAAE,EAC5B,WAAW,cAAc,EAAE,EAC3B,WAAW,aAAa,EAAE,EAC1B,WAAW,YAAY,EAAE;AAE5B,iBAAa;AAAA,MACX,aAAa;AAAA,MACb;AAAA,IACF;AAAA,EACF,CAAC,EAAE;AAEH,SAAO;AACT;","names":[]}
|
package/dist/esm/cli.mjs
CHANGED
|
@@ -168,7 +168,12 @@ const setAPI = () => {
|
|
|
168
168
|
description: "Pull dictionaries from the server",
|
|
169
169
|
options: [
|
|
170
170
|
["-d, --dictionaries [ids...]", "List of dictionary IDs to pull"],
|
|
171
|
-
["--new-dictionaries-path [path]", "Path to save the new dictionaries"]
|
|
171
|
+
["--new-dictionaries-path [path]", "Path to save the new dictionaries"],
|
|
172
|
+
// Backward-compatibility for older tests/flags (camelCase)
|
|
173
|
+
[
|
|
174
|
+
"--newDictionariesPath [path]",
|
|
175
|
+
"[alias] Path to save the new dictionaries"
|
|
176
|
+
]
|
|
172
177
|
]
|
|
173
178
|
};
|
|
174
179
|
const dictionariesPullCmd = dictionariesProgram.command("pull").description(pullOptions.description);
|
|
@@ -203,6 +208,15 @@ const setAPI = () => {
|
|
|
203
208
|
[
|
|
204
209
|
"-k, --keep-locale-dictionary",
|
|
205
210
|
"Keep the local dictionaries after pushing"
|
|
211
|
+
],
|
|
212
|
+
// Backward-compatibility for older tests/flags (camelCase)
|
|
213
|
+
[
|
|
214
|
+
"--deleteLocaleDictionary",
|
|
215
|
+
"[alias] Delete the local dictionaries after pushing"
|
|
216
|
+
],
|
|
217
|
+
[
|
|
218
|
+
"--keepLocaleDictionary",
|
|
219
|
+
"[alias] Keep the local dictionaries after pushing"
|
|
206
220
|
]
|
|
207
221
|
]
|
|
208
222
|
};
|
package/dist/esm/cli.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/cli.ts"],"sourcesContent":["import type { AIOptions as BaseAIOptions } from '@intlayer/api';\nimport type { GetConfigurationOptions } from '@intlayer/config';\nimport configuration from '@intlayer/config/built';\nimport { Command } from 'commander';\nimport { dirname as pathDirname } from 'path';\nimport { fileURLToPath } from 'url';\nimport {\n DiffMode,\n ListGitFilesOptions,\n} from '../../chokidar/dist/types/listGitFiles';\nimport { build } from './build';\nimport { getConfig } from './config';\nimport { startEditor } from './editor';\nimport { fill, FillOptions } from './fill';\nimport { listContentDeclaration } from './listContentDeclaration';\nimport { liveSync } from './liveSync';\nimport { pull } from './pull';\nimport { push } from './push';\nimport { pushConfig } from './pushConfig';\nimport { reviewDoc } from './reviewDoc';\nimport { testMissingTranslations } from './test';\nimport { translateDoc } from './translateDoc';\nimport { getParentPackageJSON } from './utils/getParentPackageJSON';\n\n// Extended AI options to include customPrompt\ntype AIOptions = BaseAIOptions & {\n customPrompt?: string;\n};\n\nconst isESModule = typeof import.meta.url === 'string';\n\nexport const dirname = isESModule\n ? pathDirname(fileURLToPath(import.meta.url))\n : __dirname;\n\nconst packageJson = getParentPackageJSON(dirname);\n\nconst logOptions = [\n ['--verbose', 'Verbose'],\n ['--prefix [prefix]', 'Prefix'],\n];\n\nconst configurationOptions = [\n ['--env-file [envFile]', 'Environment file'],\n ['-e, --env [env]', 'Environment'],\n ['--base-dir [baseDir]', 'Base directory'],\n ...logOptions,\n];\n\nconst aiOptions = [\n ['--provider [provider]', 'Provider'],\n ['--temperature [temperature]', 'Temperature'],\n ['--model [model]', 'Model'],\n ['--api-key [apiKey]', 'Provider API key'],\n ['--custom-prompt [prompt]', 'Custom prompt'],\n ['--application-context [applicationContext]', 'Application context'],\n];\n\nconst gitOptions = [\n ['--git-diff [gitDiff]', 'Git diff mode - Check git diff between two refs'],\n ['--git-diff-base [gitDiffBase]', 'Git diff base ref'],\n ['--git-diff-current [gitDiffCurrent]', 'Git diff current ref'],\n ['--uncommitted [uncommitted]', 'Uncommitted'],\n ['--unpushed [unpushed]', 'Unpushed'],\n ['--untracked [untracked]', 'Untracked'],\n];\n\nconst extractKeysFromOptions = (options: object, keys: string[]) =>\n keys.filter((key) => options[key as keyof typeof options]);\n\n/**\n * Helper functions to apply common options to commands\n */\nconst applyOptions = (command: Command, options: string[][]) => {\n options.forEach(([flag, description]) => command.option(flag, description));\n return command;\n};\n\nconst removeUndefined = <T extends Record<string, any>>(obj: T): T =>\n Object.fromEntries(\n Object.entries(obj).filter(([_, value]) => value !== undefined)\n ) as T;\n\nconst applyConfigOptions = (command: Command) =>\n applyOptions(command, configurationOptions);\nconst applyAIOptions = (command: Command) => applyOptions(command, aiOptions);\nconst applyGitOptions = (command: Command) => applyOptions(command, gitOptions);\n\nconst extractAiOptions = (options: AIOptions): AIOptions | undefined => {\n const {\n apiKey,\n provider,\n model,\n temperature,\n applicationContext,\n customPrompt,\n } = options;\n\n return removeUndefined({\n apiKey: apiKey ?? configuration.ai?.apiKey,\n provider: provider ?? (configuration.ai?.provider as AIOptions['provider']),\n model: model ?? configuration.ai?.model,\n temperature: temperature ?? configuration.ai?.temperature,\n applicationContext:\n applicationContext ?? configuration.ai?.applicationContext,\n customPrompt: customPrompt ?? (configuration.ai as any)?.customPrompt,\n });\n};\n\ntype GitOptions = {\n gitDiff?: boolean;\n gitDiffBase?: string;\n gitDiffCurrent?: string;\n uncommitted?: boolean;\n unpushed?: boolean;\n untracked?: boolean;\n};\n\nconst gitOptionKeys: (keyof GitOptions)[] = [\n 'gitDiff',\n 'gitDiffBase',\n 'gitDiffCurrent',\n 'uncommitted',\n 'unpushed',\n 'untracked',\n];\n\nconst extractGitOptions = (\n options: GitOptions\n): ListGitFilesOptions | undefined => {\n const filteredOptions = extractKeysFromOptions(options, gitOptionKeys);\n\n const isOptionEmpty = !Object.values(filteredOptions).some(Boolean);\n\n if (isOptionEmpty) return undefined;\n\n const {\n gitDiff,\n gitDiffBase,\n gitDiffCurrent,\n uncommitted,\n unpushed,\n untracked,\n } = options;\n\n const mode = [\n gitDiff && 'gitDiff',\n uncommitted && 'uncommitted',\n unpushed && 'unpushed',\n untracked && 'untracked',\n ].filter(Boolean) as DiffMode[];\n\n return removeUndefined({\n mode,\n baseRef: gitDiffBase,\n currentRef: gitDiffCurrent,\n absolute: true,\n });\n};\n\ntype LogOptions = {\n prefix?: string;\n verbose?: boolean;\n};\n\nexport type ConfigurationOptions = {\n baseDir?: string;\n env?: string;\n envFile?: string;\n} & LogOptions;\n\nconst configurationOptionKeys: (keyof ConfigurationOptions)[] = [\n 'baseDir',\n 'env',\n 'envFile',\n 'verbose',\n 'prefix',\n];\n\nconst extractConfigOptions = (\n options: ConfigurationOptions\n): GetConfigurationOptions | undefined => {\n const filteredOptions = extractKeysFromOptions(\n options,\n configurationOptionKeys\n );\n\n const isOptionEmpty = !Object.values(filteredOptions).some(Boolean);\n\n if (isOptionEmpty) {\n return undefined;\n }\n\n const { baseDir, env, envFile, verbose, prefix } = options;\n\n const log = {\n prefix: prefix ?? '', // Should not consider the prefix set in the intlayer configuration file\n verbose,\n };\n\n const override = {\n log,\n };\n\n return removeUndefined({\n baseDir,\n env,\n envFile,\n override,\n });\n};\n\n/**\n * Set the API for the CLI\n *\n * Example of commands:\n *\n * npm run intlayer build --watch\n * npm run intlayer push --dictionaries id1 id2 id3 --deleteLocaleDir\n */\nexport const setAPI = (): Command => {\n const program = new Command();\n\n program.version(packageJson.version!).description('Intlayer CLI');\n\n /**\n * DICTIONARIES\n */\n\n const dictionariesProgram = program\n .command('dictionary')\n .alias('dictionaries')\n .alias('dic')\n .description('Dictionaries operations');\n\n // Dictionary build command\n const buildOptions = {\n description: 'Build the dictionaries',\n options: [['-w, --watch', 'Watch for changes']],\n };\n\n // Add build command to dictionaries program\n const dictionariesBuildCmd = dictionariesProgram\n .command('build')\n .description(buildOptions.description);\n\n applyOptions(dictionariesBuildCmd, buildOptions.options);\n applyConfigOptions(dictionariesBuildCmd);\n dictionariesBuildCmd.action((options) => {\n build({\n ...options,\n configOptions: extractConfigOptions(options),\n });\n });\n\n // Add build command to root program as well\n const rootBuildCmd = program\n .command('build')\n .description(buildOptions.description);\n\n applyOptions(rootBuildCmd, buildOptions.options);\n applyConfigOptions(rootBuildCmd);\n rootBuildCmd.action((options) => {\n build({\n ...options,\n configOptions: extractConfigOptions(options),\n });\n });\n\n // Dictionary pull command\n const pullOptions = {\n description: 'Pull dictionaries from the server',\n options: [\n ['-d, --dictionaries [ids...]', 'List of dictionary IDs to pull'],\n ['--new-dictionaries-path [path]', 'Path to save the new dictionaries'],\n ],\n };\n\n // Add pull command to dictionaries program\n const dictionariesPullCmd = dictionariesProgram\n .command('pull')\n .description(pullOptions.description);\n\n applyOptions(dictionariesPullCmd, pullOptions.options);\n applyConfigOptions(dictionariesPullCmd);\n dictionariesPullCmd.action((options) => {\n pull({\n ...options,\n configOptions: {\n ...options.configOptions,\n baseDir: options.baseDir,\n },\n });\n });\n\n // Add pull command to root program as well\n const rootPullCmd = program\n .command('pull')\n .description(pullOptions.description);\n\n applyOptions(rootPullCmd, pullOptions.options);\n applyConfigOptions(rootPullCmd);\n rootPullCmd.action((options) => {\n pull({\n ...options,\n configOptions: extractConfigOptions(options),\n });\n });\n\n // Dictionary push command\n const pushOptions = {\n description:\n 'Push all dictionaries. Create or update the pushed dictionaries',\n options: [\n ['-d, --dictionaries [ids...]', 'List of dictionary IDs to push'],\n [\n '-r, --delete-locale-dictionary',\n 'Delete the local dictionaries after pushing',\n ],\n [\n '-k, --keep-locale-dictionary',\n 'Keep the local dictionaries after pushing',\n ],\n ],\n };\n\n // Add push command to dictionaries program\n const dictionariesPushCmd = dictionariesProgram\n .command('push')\n .description(pushOptions.description);\n\n applyOptions(dictionariesPushCmd, pushOptions.options);\n applyConfigOptions(dictionariesPushCmd);\n applyGitOptions(dictionariesPushCmd);\n\n dictionariesPushCmd.action((options) =>\n push({\n ...options,\n gitOptions: extractGitOptions(options),\n configOptions: extractConfigOptions(options),\n } as FillOptions)\n );\n\n // Add push command to root program as well\n const rootPushCmd = program\n .command('push')\n .description(pushOptions.description);\n\n applyOptions(rootPushCmd, pushOptions.options);\n applyConfigOptions(rootPushCmd);\n applyGitOptions(rootPushCmd);\n\n rootPushCmd.action((options) =>\n push({\n ...options,\n gitOptions: extractGitOptions(options),\n configOptions: extractConfigOptions(options),\n } as FillOptions)\n );\n\n /**\n * CONFIGURATION\n */\n\n // Define the parent command\n const configurationProgram = program\n .command('configuration')\n .alias('config')\n .alias('conf')\n .description('Configuration operations');\n\n const configGetCmd = configurationProgram\n .command('get')\n .description('Get the configuration');\n\n applyConfigOptions(configGetCmd);\n configGetCmd.action((options) => {\n getConfig({\n ...options,\n configOptions: extractConfigOptions(options),\n });\n });\n\n // Define the `push config` subcommand and add it to the `push` command\n const configPushCmd = configurationProgram\n .command('push')\n .description('Push the configuration');\n\n applyConfigOptions(configPushCmd);\n configPushCmd.action((options) => {\n pushConfig({\n ...options,\n configOptions: extractConfigOptions(options),\n });\n });\n\n /**\n * CONTENT DECLARATION\n */\n\n const contentProgram = program\n .command('content')\n .description('Content declaration operations');\n\n contentProgram\n .command('list')\n .description('List the content declaration files')\n .action(listContentDeclaration);\n\n const testProgram = contentProgram\n .command('test')\n .description('Test if there are missing translations');\n\n applyConfigOptions(testProgram);\n testProgram.action((options) => {\n testMissingTranslations({\n ...options,\n configOptions: extractConfigOptions(options),\n });\n });\n\n const fillProgram = program\n .command('fill')\n .description('Fill the dictionaries')\n .option('-f, --file [files...]', 'List of Dictionary files to fill')\n .option('--source-locale [sourceLocale]', 'Source locale to translate from')\n .option(\n '--output-locales [outputLocales...]',\n 'Target locales to translate to'\n )\n .option(\n '--mode [mode]',\n 'Fill mode: complete, review. Complete will fill all missing content, review will fill missing content and review existing keys',\n 'complete'\n )\n .option('-k, --keys [keys...]', 'Filter dictionaries based on keys')\n .option(\n '--excluded-keys [excludedKeys...]',\n 'Filter out dictionaries based on keys'\n )\n .option(\n '--path-filter [pathFilters...]',\n 'Filter dictionaries based on glob pattern'\n )\n .option(\n '--build [build]',\n 'Build the dictionaries before filling to ensure the content is up to date'\n );\n\n applyConfigOptions(fillProgram);\n applyAIOptions(fillProgram);\n applyGitOptions(fillProgram);\n\n fillProgram.action((options) =>\n fill({\n ...options,\n aiOptions: extractAiOptions(options),\n gitOptions: extractGitOptions(options),\n configOptions: extractConfigOptions(options),\n } as FillOptions)\n );\n\n /**\n * DOCS\n */\n\n const docParams = [\n ['--doc-pattern [docPattern...]', 'Documentation pattern'],\n [\n '--excluded-glob-pattern [excludedGlobPattern...]',\n 'Excluded glob pattern',\n ],\n [\n '--nb-simultaneous-file-processed [nbSimultaneousFileProcessed]',\n 'Number of simultaneous file processed',\n ],\n ['--locales [locales...]', 'Locales'],\n ['--base-locale [baseLocale]', 'Base locale'],\n [\n '--custom-instructions [customInstructions]',\n 'Custom instructions added to the prompt. Usefull to apply specific rules regarding formatting, urls translation, etc.',\n ],\n [\n '--skip-if-modified-before [skipIfModifiedBefore]',\n 'Skip the file if it has been modified before the given time. Can be an absolute time as \"2025-12-05\" (string or Date) or a relative time in ms `1 * 60 * 60 * 1000` (1 hour). This option check update time of the file using the `fs.stat` method. So it could be impacted by Git or other tools that modify the file.',\n ],\n [\n '--skip-if-modified-after [skipIfModifiedAfter]',\n 'Skip the file if it has been modified within the given time. Can be an absolute time as \"2025-12-05\" (string or Date) or a relative time in ms `1 * 60 * 60 * 1000` (1 hour). This option check update time of the file using the `fs.stat` method. So it could be impacted by Git or other tools that modify the file.',\n ],\n ];\n\n const docProgram = program\n .command('doc')\n .description('Documentation operations');\n\n const translateProgram = docProgram\n .command('translate')\n .description('Translate the documentation');\n\n applyConfigOptions(translateProgram);\n applyAIOptions(translateProgram);\n applyGitOptions(translateProgram);\n applyOptions(translateProgram, docParams);\n\n translateProgram.action((options) =>\n translateDoc({\n docPattern: options.docPattern,\n excludedGlobPattern: options.excludedGlobPattern,\n locales: options.locales,\n baseLocale: options.baseLocale,\n aiOptions: extractAiOptions(options),\n gitOptions: extractGitOptions(options),\n nbSimultaneousFileProcessed: options.nbSimultaneousFileProcessed,\n configOptions: extractConfigOptions(options),\n customInstructions: options.customInstructions,\n skipIfModifiedBefore: options.skipIfModifiedBefore,\n skipIfModifiedAfter: options.skipIfModifiedAfter,\n })\n );\n\n const reviewProgram = docProgram\n .command('review')\n .description('Review the documentation');\n\n applyConfigOptions(reviewProgram);\n applyAIOptions(reviewProgram);\n applyGitOptions(reviewProgram);\n applyOptions(reviewProgram, docParams);\n\n reviewProgram.action((options) =>\n reviewDoc({\n docPattern: options.docPattern,\n excludedGlobPattern: options.excludedGlobPattern,\n locales: options.locales,\n baseLocale: options.baseLocale,\n aiOptions: extractAiOptions(options),\n gitOptions: extractGitOptions(options),\n nbSimultaneousFileProcessed: options.nbSimultaneousFileProcessed,\n configOptions: extractConfigOptions(options),\n customInstructions: options.customInstructions,\n skipIfModifiedBefore: options.skipIfModifiedBefore,\n skipIfModifiedAfter: options.skipIfModifiedAfter,\n })\n );\n\n /**\n * LIVE SYNC\n */\n\n const liveOptions = [\n ['--process [process]', 'Start command in parallel with the live sync'],\n ];\n\n const liveCmd = program\n .command('live')\n .description(\n 'Live sync - Watch for changes made on the CMS and update the application content accordingly'\n );\n\n applyOptions(liveCmd, liveOptions);\n\n liveCmd.action((options) => liveSync(options));\n\n /**\n * EDITOR\n */\n\n const editorProgram = program\n .command('editor')\n .description('Visual editor operations');\n\n const editorStartCmd = editorProgram\n .command('start')\n .description('Start the Intlayer visual editor');\n\n applyConfigOptions(editorStartCmd);\n\n editorStartCmd.action((options) => {\n startEditor({\n env: options.env,\n envFile: options.envFile,\n });\n });\n\n program.parse(process.argv);\n\n return program;\n};\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/cli.ts"],"sourcesContent":["import type { AIOptions as BaseAIOptions } from '@intlayer/api';\nimport type { GetConfigurationOptions } from '@intlayer/config';\nimport configuration from '@intlayer/config/built';\nimport { Command } from 'commander';\nimport { dirname as pathDirname } from 'path';\nimport { fileURLToPath } from 'url';\nimport {\n DiffMode,\n ListGitFilesOptions,\n} from '../../chokidar/dist/types/listGitFiles';\nimport { build } from './build';\nimport { getConfig } from './config';\nimport { startEditor } from './editor';\nimport { fill, FillOptions } from './fill';\nimport { listContentDeclaration } from './listContentDeclaration';\nimport { liveSync } from './liveSync';\nimport { pull } from './pull';\nimport { push } from './push';\nimport { pushConfig } from './pushConfig';\nimport { reviewDoc } from './reviewDoc';\nimport { testMissingTranslations } from './test';\nimport { translateDoc } from './translateDoc';\nimport { getParentPackageJSON } from './utils/getParentPackageJSON';\n\n// Extended AI options to include customPrompt\ntype AIOptions = BaseAIOptions & {\n customPrompt?: string;\n};\n\nconst isESModule = typeof import.meta.url === 'string';\n\nexport const dirname = isESModule\n ? pathDirname(fileURLToPath(import.meta.url))\n : __dirname;\n\nconst packageJson = getParentPackageJSON(dirname);\n\nconst logOptions = [\n ['--verbose', 'Verbose'],\n ['--prefix [prefix]', 'Prefix'],\n];\n\nconst configurationOptions = [\n ['--env-file [envFile]', 'Environment file'],\n ['-e, --env [env]', 'Environment'],\n ['--base-dir [baseDir]', 'Base directory'],\n ...logOptions,\n];\n\nconst aiOptions = [\n ['--provider [provider]', 'Provider'],\n ['--temperature [temperature]', 'Temperature'],\n ['--model [model]', 'Model'],\n ['--api-key [apiKey]', 'Provider API key'],\n ['--custom-prompt [prompt]', 'Custom prompt'],\n ['--application-context [applicationContext]', 'Application context'],\n];\n\nconst gitOptions = [\n ['--git-diff [gitDiff]', 'Git diff mode - Check git diff between two refs'],\n ['--git-diff-base [gitDiffBase]', 'Git diff base ref'],\n ['--git-diff-current [gitDiffCurrent]', 'Git diff current ref'],\n ['--uncommitted [uncommitted]', 'Uncommitted'],\n ['--unpushed [unpushed]', 'Unpushed'],\n ['--untracked [untracked]', 'Untracked'],\n];\n\nconst extractKeysFromOptions = (options: object, keys: string[]) =>\n keys.filter((key) => options[key as keyof typeof options]);\n\n/**\n * Helper functions to apply common options to commands\n */\nconst applyOptions = (command: Command, options: string[][]) => {\n options.forEach(([flag, description]) => command.option(flag, description));\n return command;\n};\n\nconst removeUndefined = <T extends Record<string, any>>(obj: T): T =>\n Object.fromEntries(\n Object.entries(obj).filter(([_, value]) => value !== undefined)\n ) as T;\n\nconst applyConfigOptions = (command: Command) =>\n applyOptions(command, configurationOptions);\nconst applyAIOptions = (command: Command) => applyOptions(command, aiOptions);\nconst applyGitOptions = (command: Command) => applyOptions(command, gitOptions);\n\nconst extractAiOptions = (options: AIOptions): AIOptions | undefined => {\n const {\n apiKey,\n provider,\n model,\n temperature,\n applicationContext,\n customPrompt,\n } = options;\n\n return removeUndefined({\n apiKey: apiKey ?? configuration.ai?.apiKey,\n provider: provider ?? (configuration.ai?.provider as AIOptions['provider']),\n model: model ?? configuration.ai?.model,\n temperature: temperature ?? configuration.ai?.temperature,\n applicationContext:\n applicationContext ?? configuration.ai?.applicationContext,\n customPrompt: customPrompt ?? (configuration.ai as any)?.customPrompt,\n });\n};\n\ntype GitOptions = {\n gitDiff?: boolean;\n gitDiffBase?: string;\n gitDiffCurrent?: string;\n uncommitted?: boolean;\n unpushed?: boolean;\n untracked?: boolean;\n};\n\nconst gitOptionKeys: (keyof GitOptions)[] = [\n 'gitDiff',\n 'gitDiffBase',\n 'gitDiffCurrent',\n 'uncommitted',\n 'unpushed',\n 'untracked',\n];\n\nconst extractGitOptions = (\n options: GitOptions\n): ListGitFilesOptions | undefined => {\n const filteredOptions = extractKeysFromOptions(options, gitOptionKeys);\n\n const isOptionEmpty = !Object.values(filteredOptions).some(Boolean);\n\n if (isOptionEmpty) return undefined;\n\n const {\n gitDiff,\n gitDiffBase,\n gitDiffCurrent,\n uncommitted,\n unpushed,\n untracked,\n } = options;\n\n const mode = [\n gitDiff && 'gitDiff',\n uncommitted && 'uncommitted',\n unpushed && 'unpushed',\n untracked && 'untracked',\n ].filter(Boolean) as DiffMode[];\n\n return removeUndefined({\n mode,\n baseRef: gitDiffBase,\n currentRef: gitDiffCurrent,\n absolute: true,\n });\n};\n\ntype LogOptions = {\n prefix?: string;\n verbose?: boolean;\n};\n\nexport type ConfigurationOptions = {\n baseDir?: string;\n env?: string;\n envFile?: string;\n} & LogOptions;\n\nconst configurationOptionKeys: (keyof ConfigurationOptions)[] = [\n 'baseDir',\n 'env',\n 'envFile',\n 'verbose',\n 'prefix',\n];\n\nconst extractConfigOptions = (\n options: ConfigurationOptions\n): GetConfigurationOptions | undefined => {\n const filteredOptions = extractKeysFromOptions(\n options,\n configurationOptionKeys\n );\n\n const isOptionEmpty = !Object.values(filteredOptions).some(Boolean);\n\n if (isOptionEmpty) {\n return undefined;\n }\n\n const { baseDir, env, envFile, verbose, prefix } = options;\n\n const log = {\n prefix: prefix ?? '', // Should not consider the prefix set in the intlayer configuration file\n verbose,\n };\n\n const override = {\n log,\n };\n\n return removeUndefined({\n baseDir,\n env,\n envFile,\n override,\n });\n};\n\n/**\n * Set the API for the CLI\n *\n * Example of commands:\n *\n * npm run intlayer build --watch\n * npm run intlayer push --dictionaries id1 id2 id3 --deleteLocaleDir\n */\nexport const setAPI = (): Command => {\n const program = new Command();\n\n program.version(packageJson.version!).description('Intlayer CLI');\n\n /**\n * DICTIONARIES\n */\n\n const dictionariesProgram = program\n .command('dictionary')\n .alias('dictionaries')\n .alias('dic')\n .description('Dictionaries operations');\n\n // Dictionary build command\n const buildOptions = {\n description: 'Build the dictionaries',\n options: [['-w, --watch', 'Watch for changes']],\n };\n\n // Add build command to dictionaries program\n const dictionariesBuildCmd = dictionariesProgram\n .command('build')\n .description(buildOptions.description);\n\n applyOptions(dictionariesBuildCmd, buildOptions.options);\n applyConfigOptions(dictionariesBuildCmd);\n dictionariesBuildCmd.action((options) => {\n build({\n ...options,\n configOptions: extractConfigOptions(options),\n });\n });\n\n // Add build command to root program as well\n const rootBuildCmd = program\n .command('build')\n .description(buildOptions.description);\n\n applyOptions(rootBuildCmd, buildOptions.options);\n applyConfigOptions(rootBuildCmd);\n rootBuildCmd.action((options) => {\n build({\n ...options,\n configOptions: extractConfigOptions(options),\n });\n });\n\n // Dictionary pull command\n const pullOptions = {\n description: 'Pull dictionaries from the server',\n options: [\n ['-d, --dictionaries [ids...]', 'List of dictionary IDs to pull'],\n ['--new-dictionaries-path [path]', 'Path to save the new dictionaries'],\n // Backward-compatibility for older tests/flags (camelCase)\n [\n '--newDictionariesPath [path]',\n '[alias] Path to save the new dictionaries',\n ],\n ],\n };\n\n // Add pull command to dictionaries program\n const dictionariesPullCmd = dictionariesProgram\n .command('pull')\n .description(pullOptions.description);\n\n applyOptions(dictionariesPullCmd, pullOptions.options);\n applyConfigOptions(dictionariesPullCmd);\n dictionariesPullCmd.action((options) => {\n pull({\n ...options,\n configOptions: {\n ...options.configOptions,\n baseDir: options.baseDir,\n },\n });\n });\n\n // Add pull command to root program as well\n const rootPullCmd = program\n .command('pull')\n .description(pullOptions.description);\n\n applyOptions(rootPullCmd, pullOptions.options);\n applyConfigOptions(rootPullCmd);\n rootPullCmd.action((options) => {\n pull({\n ...options,\n configOptions: extractConfigOptions(options),\n });\n });\n\n // Dictionary push command\n const pushOptions = {\n description:\n 'Push all dictionaries. Create or update the pushed dictionaries',\n options: [\n ['-d, --dictionaries [ids...]', 'List of dictionary IDs to push'],\n [\n '-r, --delete-locale-dictionary',\n 'Delete the local dictionaries after pushing',\n ],\n [\n '-k, --keep-locale-dictionary',\n 'Keep the local dictionaries after pushing',\n ],\n // Backward-compatibility for older tests/flags (camelCase)\n [\n '--deleteLocaleDictionary',\n '[alias] Delete the local dictionaries after pushing',\n ],\n [\n '--keepLocaleDictionary',\n '[alias] Keep the local dictionaries after pushing',\n ],\n ],\n };\n\n // Add push command to dictionaries program\n const dictionariesPushCmd = dictionariesProgram\n .command('push')\n .description(pushOptions.description);\n\n applyOptions(dictionariesPushCmd, pushOptions.options);\n applyConfigOptions(dictionariesPushCmd);\n applyGitOptions(dictionariesPushCmd);\n\n dictionariesPushCmd.action((options) =>\n push({\n ...options,\n gitOptions: extractGitOptions(options),\n configOptions: extractConfigOptions(options),\n } as FillOptions)\n );\n\n // Add push command to root program as well\n const rootPushCmd = program\n .command('push')\n .description(pushOptions.description);\n\n applyOptions(rootPushCmd, pushOptions.options);\n applyConfigOptions(rootPushCmd);\n applyGitOptions(rootPushCmd);\n\n rootPushCmd.action((options) =>\n push({\n ...options,\n gitOptions: extractGitOptions(options),\n configOptions: extractConfigOptions(options),\n } as FillOptions)\n );\n\n /**\n * CONFIGURATION\n */\n\n // Define the parent command\n const configurationProgram = program\n .command('configuration')\n .alias('config')\n .alias('conf')\n .description('Configuration operations');\n\n const configGetCmd = configurationProgram\n .command('get')\n .description('Get the configuration');\n\n applyConfigOptions(configGetCmd);\n configGetCmd.action((options) => {\n getConfig({\n ...options,\n configOptions: extractConfigOptions(options),\n });\n });\n\n // Define the `push config` subcommand and add it to the `push` command\n const configPushCmd = configurationProgram\n .command('push')\n .description('Push the configuration');\n\n applyConfigOptions(configPushCmd);\n configPushCmd.action((options) => {\n pushConfig({\n ...options,\n configOptions: extractConfigOptions(options),\n });\n });\n\n /**\n * CONTENT DECLARATION\n */\n\n const contentProgram = program\n .command('content')\n .description('Content declaration operations');\n\n contentProgram\n .command('list')\n .description('List the content declaration files')\n .action(listContentDeclaration);\n\n const testProgram = contentProgram\n .command('test')\n .description('Test if there are missing translations');\n\n applyConfigOptions(testProgram);\n testProgram.action((options) => {\n testMissingTranslations({\n ...options,\n configOptions: extractConfigOptions(options),\n });\n });\n\n const fillProgram = program\n .command('fill')\n .description('Fill the dictionaries')\n .option('-f, --file [files...]', 'List of Dictionary files to fill')\n .option('--source-locale [sourceLocale]', 'Source locale to translate from')\n .option(\n '--output-locales [outputLocales...]',\n 'Target locales to translate to'\n )\n .option(\n '--mode [mode]',\n 'Fill mode: complete, review. Complete will fill all missing content, review will fill missing content and review existing keys',\n 'complete'\n )\n .option('-k, --keys [keys...]', 'Filter dictionaries based on keys')\n .option(\n '--excluded-keys [excludedKeys...]',\n 'Filter out dictionaries based on keys'\n )\n .option(\n '--path-filter [pathFilters...]',\n 'Filter dictionaries based on glob pattern'\n )\n .option(\n '--build [build]',\n 'Build the dictionaries before filling to ensure the content is up to date'\n );\n\n applyConfigOptions(fillProgram);\n applyAIOptions(fillProgram);\n applyGitOptions(fillProgram);\n\n fillProgram.action((options) =>\n fill({\n ...options,\n aiOptions: extractAiOptions(options),\n gitOptions: extractGitOptions(options),\n configOptions: extractConfigOptions(options),\n } as FillOptions)\n );\n\n /**\n * DOCS\n */\n\n const docParams = [\n ['--doc-pattern [docPattern...]', 'Documentation pattern'],\n [\n '--excluded-glob-pattern [excludedGlobPattern...]',\n 'Excluded glob pattern',\n ],\n [\n '--nb-simultaneous-file-processed [nbSimultaneousFileProcessed]',\n 'Number of simultaneous file processed',\n ],\n ['--locales [locales...]', 'Locales'],\n ['--base-locale [baseLocale]', 'Base locale'],\n [\n '--custom-instructions [customInstructions]',\n 'Custom instructions added to the prompt. Usefull to apply specific rules regarding formatting, urls translation, etc.',\n ],\n [\n '--skip-if-modified-before [skipIfModifiedBefore]',\n 'Skip the file if it has been modified before the given time. Can be an absolute time as \"2025-12-05\" (string or Date) or a relative time in ms `1 * 60 * 60 * 1000` (1 hour). This option check update time of the file using the `fs.stat` method. So it could be impacted by Git or other tools that modify the file.',\n ],\n [\n '--skip-if-modified-after [skipIfModifiedAfter]',\n 'Skip the file if it has been modified within the given time. Can be an absolute time as \"2025-12-05\" (string or Date) or a relative time in ms `1 * 60 * 60 * 1000` (1 hour). This option check update time of the file using the `fs.stat` method. So it could be impacted by Git or other tools that modify the file.',\n ],\n ];\n\n const docProgram = program\n .command('doc')\n .description('Documentation operations');\n\n const translateProgram = docProgram\n .command('translate')\n .description('Translate the documentation');\n\n applyConfigOptions(translateProgram);\n applyAIOptions(translateProgram);\n applyGitOptions(translateProgram);\n applyOptions(translateProgram, docParams);\n\n translateProgram.action((options) =>\n translateDoc({\n docPattern: options.docPattern,\n excludedGlobPattern: options.excludedGlobPattern,\n locales: options.locales,\n baseLocale: options.baseLocale,\n aiOptions: extractAiOptions(options),\n gitOptions: extractGitOptions(options),\n nbSimultaneousFileProcessed: options.nbSimultaneousFileProcessed,\n configOptions: extractConfigOptions(options),\n customInstructions: options.customInstructions,\n skipIfModifiedBefore: options.skipIfModifiedBefore,\n skipIfModifiedAfter: options.skipIfModifiedAfter,\n })\n );\n\n const reviewProgram = docProgram\n .command('review')\n .description('Review the documentation');\n\n applyConfigOptions(reviewProgram);\n applyAIOptions(reviewProgram);\n applyGitOptions(reviewProgram);\n applyOptions(reviewProgram, docParams);\n\n reviewProgram.action((options) =>\n reviewDoc({\n docPattern: options.docPattern,\n excludedGlobPattern: options.excludedGlobPattern,\n locales: options.locales,\n baseLocale: options.baseLocale,\n aiOptions: extractAiOptions(options),\n gitOptions: extractGitOptions(options),\n nbSimultaneousFileProcessed: options.nbSimultaneousFileProcessed,\n configOptions: extractConfigOptions(options),\n customInstructions: options.customInstructions,\n skipIfModifiedBefore: options.skipIfModifiedBefore,\n skipIfModifiedAfter: options.skipIfModifiedAfter,\n })\n );\n\n /**\n * LIVE SYNC\n */\n\n const liveOptions = [\n ['--process [process]', 'Start command in parallel with the live sync'],\n ];\n\n const liveCmd = program\n .command('live')\n .description(\n 'Live sync - Watch for changes made on the CMS and update the application content accordingly'\n );\n\n applyOptions(liveCmd, liveOptions);\n\n liveCmd.action((options) => liveSync(options));\n\n /**\n * EDITOR\n */\n\n const editorProgram = program\n .command('editor')\n .description('Visual editor operations');\n\n const editorStartCmd = editorProgram\n .command('start')\n .description('Start the Intlayer visual editor');\n\n applyConfigOptions(editorStartCmd);\n\n editorStartCmd.action((options) => {\n startEditor({\n env: options.env,\n envFile: options.envFile,\n });\n });\n\n program.parse(process.argv);\n\n return program;\n};\n"],"mappings":"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","names":[]}
|
package/dist/esm/reviewDoc.mjs
CHANGED
|
@@ -29,9 +29,8 @@ import { getChunk } from "./utils/getChunk.mjs";
|
|
|
29
29
|
import { getOutputFilePath } from "./utils/getOutputFilePath.mjs";
|
|
30
30
|
const isESModule = typeof import.meta.url === "string";
|
|
31
31
|
const dir = isESModule ? dirname(fileURLToPath(import.meta.url)) : __dirname;
|
|
32
|
-
const reviewFile = async (baseFilePath, outputFilePath, locale, baseLocale, aiOptions,
|
|
32
|
+
const reviewFile = async (baseFilePath, outputFilePath, locale, baseLocale, aiOptions, configuration = getConfiguration(), customInstructions, changedLines) => {
|
|
33
33
|
try {
|
|
34
|
-
const configuration = getConfiguration(configOptions);
|
|
35
34
|
const appLogger = getAppLogger(configuration, {
|
|
36
35
|
config: {
|
|
37
36
|
prefix: ""
|
|
@@ -49,10 +48,7 @@ const reviewFile = async (baseFilePath, outputFilePath, locale, baseLocale, aiOp
|
|
|
49
48
|
`\u2192 ${ANSIColors.RESET}`
|
|
50
49
|
].join("");
|
|
51
50
|
const prefixText = `${ANSIColors.GREY_DARK}[${formatPath(baseFilePath)}${ANSIColors.GREY_DARK}][${formatLocale(locale)}${ANSIColors.GREY_DARK}] `;
|
|
52
|
-
const prefix = [
|
|
53
|
-
colon(prefixText, { colSize: 40 }),
|
|
54
|
-
`\u2192 ${ANSIColors.RESET}`
|
|
55
|
-
].join("");
|
|
51
|
+
const prefix = [colon(prefixText, { colSize: 40 })].join("");
|
|
56
52
|
appLogger(
|
|
57
53
|
`${filePrefix}Base file splitted into ${colorizeNumber(baseChunks.length)} chunks`
|
|
58
54
|
);
|
|
@@ -94,10 +90,18 @@ const reviewFile = async (baseFilePath, outputFilePath, locale, baseLocale, aiOp
|
|
|
94
90
|
{ role: "user", content: baseChunkContext.content }
|
|
95
91
|
],
|
|
96
92
|
aiOptions,
|
|
97
|
-
|
|
93
|
+
configuration
|
|
98
94
|
);
|
|
99
95
|
appLogger(
|
|
100
|
-
|
|
96
|
+
[
|
|
97
|
+
`${prefix}`,
|
|
98
|
+
`${ANSIColors.GREY_DARK}[Chunk `,
|
|
99
|
+
colorizeNumber(i + 1),
|
|
100
|
+
`${ANSIColors.GREY_DARK} of `,
|
|
101
|
+
colorizeNumber(baseChunks.length),
|
|
102
|
+
`${ANSIColors.GREY_DARK}] \u2192${ANSIColors.RESET} `,
|
|
103
|
+
`${colorizeNumber(result.tokenUsed)} tokens used`
|
|
104
|
+
].join("")
|
|
101
105
|
);
|
|
102
106
|
const fixedReviewedChunkResult = fixChunkStartEndChars(
|
|
103
107
|
result?.fileContent,
|
|
@@ -200,7 +204,7 @@ const reviewDoc = async ({
|
|
|
200
204
|
locale,
|
|
201
205
|
baseLocale,
|
|
202
206
|
aiOptions,
|
|
203
|
-
|
|
207
|
+
configuration,
|
|
204
208
|
customInstructions,
|
|
205
209
|
changedLines
|
|
206
210
|
);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/reviewDoc.ts"],"sourcesContent":["import { AIOptions } from '@intlayer/api'; // OAuth handled by API proxy\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/checkAccess';\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 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 configOptions\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 const hasCMSAuth = await checkAIAccess(configuration, aiOptions);\n\n if (!hasCMSAuth) return;\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 // OAuth handled by API proxy internally\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 customInstructions,\n changedLines\n );\n })\n )\n );\n\n await Promise.all(tasks);\n};\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/reviewDoc.ts"],"sourcesContent":["import { AIOptions } from '@intlayer/api'; // OAuth handled by API proxy\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 IntlayerConfig,\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/checkAccess';\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 configuration: IntlayerConfig = getConfiguration(),\n customInstructions?: string,\n changedLines?: number[]\n) => {\n try {\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 = [colon(prefixText, { colSize: 40 })].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 configuration\n );\n\n appLogger(\n [\n `${prefix}`,\n `${ANSIColors.GREY_DARK}[Chunk `,\n colorizeNumber(i + 1),\n `${ANSIColors.GREY_DARK} of `,\n colorizeNumber(baseChunks.length),\n `${ANSIColors.GREY_DARK}] →${ANSIColors.RESET} `,\n `${colorizeNumber(result.tokenUsed)} tokens used`,\n ].join('')\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 const hasCMSAuth = await checkAIAccess(configuration, aiOptions);\n\n if (!hasCMSAuth) return;\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 // OAuth handled by API proxy internally\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 configuration,\n customInstructions,\n changedLines\n );\n })\n )\n );\n\n await Promise.all(tasks);\n};\n"],"mappings":"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","names":[]}
|
|
@@ -27,9 +27,8 @@ import { getChunk } from "./utils/getChunk.mjs";
|
|
|
27
27
|
import { getOutputFilePath } from "./utils/getOutputFilePath.mjs";
|
|
28
28
|
const isESModule = typeof import.meta.url === "string";
|
|
29
29
|
const dir = isESModule ? dirname(fileURLToPath(import.meta.url)) : __dirname;
|
|
30
|
-
const translateFile = async (baseFilePath, outputFilePath, locale, baseLocale, aiOptions,
|
|
30
|
+
const translateFile = async (baseFilePath, outputFilePath, locale, baseLocale, aiOptions, configuration = getConfiguration(), customInstructions) => {
|
|
31
31
|
try {
|
|
32
|
-
const configuration = getConfiguration(configOptions);
|
|
33
32
|
const appLogger = getAppLogger(configuration, {
|
|
34
33
|
config: {
|
|
35
34
|
prefix: ""
|
|
@@ -72,10 +71,18 @@ const translateFile = async (baseFilePath, outputFilePath, locale, baseLocale, a
|
|
|
72
71
|
{ role: "user", content: fileToTranslateCurrentChunk }
|
|
73
72
|
],
|
|
74
73
|
aiOptions,
|
|
75
|
-
|
|
74
|
+
configuration
|
|
76
75
|
);
|
|
77
76
|
appLogger(
|
|
78
|
-
|
|
77
|
+
[
|
|
78
|
+
`${prefix}`,
|
|
79
|
+
`${ANSIColors.GREY_DARK}[Chunk `,
|
|
80
|
+
colorizeNumber(i + 1),
|
|
81
|
+
`${ANSIColors.GREY_DARK} of `,
|
|
82
|
+
colorizeNumber(chunks.length),
|
|
83
|
+
`${ANSIColors.GREY_DARK}] \u2192${ANSIColors.RESET} `,
|
|
84
|
+
`${colorizeNumber(result.tokenUsed)} tokens used`
|
|
85
|
+
].join("")
|
|
79
86
|
);
|
|
80
87
|
const fixedTranslatedChunkResult = fixChunkStartEndChars(
|
|
81
88
|
result?.fileContent,
|
|
@@ -181,7 +188,7 @@ const translateDoc = async ({
|
|
|
181
188
|
locale,
|
|
182
189
|
baseLocale,
|
|
183
190
|
aiOptions,
|
|
184
|
-
|
|
191
|
+
configuration,
|
|
185
192
|
customInstructions
|
|
186
193
|
);
|
|
187
194
|
})
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/translateDoc.ts"],"sourcesContent":["import { AIOptions } from '@intlayer/api';\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 fg from 'fast-glob';\nimport { existsSync, 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/checkAccess';\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 translateFile = async (\n baseFilePath: string,\n outputFilePath: string,\n locale: Locales,\n baseLocale: Locales,\n aiOptions?: AIOptions,\n configOptions?: GetConfigurationOptions,\n customInstructions?: string\n) => {\n try {\n const configuration = getConfiguration(configOptions);\n const appLogger = getAppLogger(configuration, {\n config: {\n prefix: '',\n },\n });\n\n // Determine the target locale file path\n const fileContent = await readFile(baseFilePath, 'utf-8');\n let fileResultContent = fileContent;\n\n // Prepare the base prompt for ChatGPT\n const basePrompt = (\n await readFile(join(dir, './prompts/TRANSLATE_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 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 // 1. Chunk the file by number of lines instead of characters\n const chunks = chunkText(fileContent);\n appLogger(\n `${filePrefix}Base file splitted into ${colorizeNumber(chunks.length)} chunks`\n );\n\n for await (const [i, chunk] of chunks.entries()) {\n const isFirstChunk = i === 0;\n\n // Build the chunk-specific prompt\n const getPrevChunkPrompt = () =>\n `**CHUNK ${i} of ${chunks.length}** that has been translated in ${formatLocale(locale)}:\\n` +\n `///chunkStart///` +\n getChunk(fileResultContent, chunks[i - 1]) +\n `///chunkEnd///`;\n\n const getBaseChunkContextPrompt = () =>\n `**CHUNK ${i + 1} to ${Math.min(i + 3, chunks.length)} of ${chunks.length}** is the base chunk in ${formatLocale(baseLocale, false)} as reference.\\n` +\n `///chunksStart///` +\n (chunks[i - 1]?.content ?? '') +\n chunks[i].content +\n (chunks[i + 1]?.content ?? '') +\n `///chunksEnd///`;\n\n const fileToTranslateCurrentChunk = chunk.content;\n\n // Make the actual translation call\n let chunkTranslation = await retryManager(async () => {\n const result = await chunkInference(\n [\n { role: 'system', content: basePrompt },\n\n { role: 'system', content: getBaseChunkContextPrompt() },\n ...(isFirstChunk\n ? []\n : [{ role: 'system', content: getPrevChunkPrompt() } as const]),\n {\n role: 'system',\n content: `The next user message will be the **CHUNK ${colorizeNumber(i + 1)} of ${colorizeNumber(chunks.length)}** in ${formatLocale(baseLocale, false)} to translate in ${formatLocale(locale, false)}:`,\n },\n { role: 'user', content: fileToTranslateCurrentChunk },\n ],\n aiOptions,\n configOptions\n );\n\n appLogger(\n `${prefix}${colorizeNumber(result.tokenUsed)} tokens used - Chunk ${colorizeNumber(i + 1)} of ${colorizeNumber(chunks.length)}`\n );\n\n const fixedTranslatedChunkResult = fixChunkStartEndChars(\n result?.fileContent,\n fileToTranslateCurrentChunk\n );\n\n return fixedTranslatedChunkResult;\n })();\n\n // Replace the chunk in the file content\n fileResultContent = fileResultContent.replace(\n fileToTranslateCurrentChunk,\n chunkTranslation\n );\n }\n\n // 4. Write the final translation to the appropriate file path\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 TranslateDocOptions = {\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 translate function: scans all .md files in \"en/\" (unless you specified DOC_LIST),\n * then translates them to each locale in LOCALE_LIST.\n */\nexport const translateDoc = async ({\n docPattern,\n locales,\n excludedGlobPattern,\n baseLocale,\n aiOptions,\n nbSimultaneousFileProcessed,\n configOptions,\n customInstructions,\n skipIfModifiedBefore,\n skipIfModifiedAfter,\n gitOptions,\n}: TranslateDocOptions) => {\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 const hasCMSAuth = await checkAIAccess(configuration, aiOptions);\n\n if (!hasCMSAuth) return;\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 // OAuth handled by API proxy internally\n\n appLogger(`Base locale is ${formatLocale(baseLocale)}`);\n appLogger(\n `Translating ${colorizeNumber(locales.length)} locales: [ ${formatLocale(locales)} ]`\n );\n\n appLogger(`Translating ${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 `Translating 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 // check if the file exist, otherwise create it\n if (!existsSync(outputFilePath)) {\n appLogger(`File ${outputFilePath} does not exist, creating it...`);\n mkdirSync(dirname(outputFilePath), { recursive: true });\n writeFileSync(outputFilePath, '');\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 await translateFile(\n absoluteBaseFilePath,\n outputFilePath,\n locale as Locales,\n baseLocale,\n aiOptions,\n configOptions,\n customInstructions\n );\n })\n )\n );\n\n await Promise.all(tasks);\n};\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/translateDoc.ts"],"sourcesContent":["import { AIOptions } from '@intlayer/api';\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 IntlayerConfig,\n Locales,\n retryManager,\n} from '@intlayer/config';\nimport fg from 'fast-glob';\nimport { existsSync, 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/checkAccess';\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 translateFile = async (\n baseFilePath: string,\n outputFilePath: string,\n locale: Locales,\n baseLocale: Locales,\n aiOptions?: AIOptions,\n configuration: IntlayerConfig = getConfiguration(),\n customInstructions?: string\n) => {\n try {\n const appLogger = getAppLogger(configuration, {\n config: {\n prefix: '',\n },\n });\n\n // Determine the target locale file path\n const fileContent = await readFile(baseFilePath, 'utf-8');\n let fileResultContent = fileContent;\n\n // Prepare the base prompt for ChatGPT\n const basePrompt = (\n await readFile(join(dir, './prompts/TRANSLATE_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 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 // 1. Chunk the file by number of lines instead of characters\n const chunks = chunkText(fileContent);\n appLogger(\n `${filePrefix}Base file splitted into ${colorizeNumber(chunks.length)} chunks`\n );\n\n for await (const [i, chunk] of chunks.entries()) {\n const isFirstChunk = i === 0;\n\n // Build the chunk-specific prompt\n const getPrevChunkPrompt = () =>\n `**CHUNK ${i} of ${chunks.length}** that has been translated in ${formatLocale(locale)}:\\n` +\n `///chunkStart///` +\n getChunk(fileResultContent, chunks[i - 1]) +\n `///chunkEnd///`;\n\n const getBaseChunkContextPrompt = () =>\n `**CHUNK ${i + 1} to ${Math.min(i + 3, chunks.length)} of ${chunks.length}** is the base chunk in ${formatLocale(baseLocale, false)} as reference.\\n` +\n `///chunksStart///` +\n (chunks[i - 1]?.content ?? '') +\n chunks[i].content +\n (chunks[i + 1]?.content ?? '') +\n `///chunksEnd///`;\n\n const fileToTranslateCurrentChunk = chunk.content;\n\n // Make the actual translation call\n let chunkTranslation = await retryManager(async () => {\n const result = await chunkInference(\n [\n { role: 'system', content: basePrompt },\n\n { role: 'system', content: getBaseChunkContextPrompt() },\n ...(isFirstChunk\n ? []\n : [{ role: 'system', content: getPrevChunkPrompt() } as const]),\n {\n role: 'system',\n content: `The next user message will be the **CHUNK ${colorizeNumber(i + 1)} of ${colorizeNumber(chunks.length)}** in ${formatLocale(baseLocale, false)} to translate in ${formatLocale(locale, false)}:`,\n },\n { role: 'user', content: fileToTranslateCurrentChunk },\n ],\n aiOptions,\n configuration\n );\n\n appLogger(\n [\n `${prefix}`,\n `${ANSIColors.GREY_DARK}[Chunk `,\n colorizeNumber(i + 1),\n `${ANSIColors.GREY_DARK} of `,\n colorizeNumber(chunks.length),\n `${ANSIColors.GREY_DARK}] →${ANSIColors.RESET} `,\n `${colorizeNumber(result.tokenUsed)} tokens used`,\n ].join('')\n );\n\n const fixedTranslatedChunkResult = fixChunkStartEndChars(\n result?.fileContent,\n fileToTranslateCurrentChunk\n );\n\n return fixedTranslatedChunkResult;\n })();\n\n // Replace the chunk in the file content\n fileResultContent = fileResultContent.replace(\n fileToTranslateCurrentChunk,\n chunkTranslation\n );\n }\n\n // 4. Write the final translation to the appropriate file path\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 TranslateDocOptions = {\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 translate function: scans all .md files in \"en/\" (unless you specified DOC_LIST),\n * then translates them to each locale in LOCALE_LIST.\n */\nexport const translateDoc = async ({\n docPattern,\n locales,\n excludedGlobPattern,\n baseLocale,\n aiOptions,\n nbSimultaneousFileProcessed,\n configOptions,\n customInstructions,\n skipIfModifiedBefore,\n skipIfModifiedAfter,\n gitOptions,\n}: TranslateDocOptions) => {\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 const hasCMSAuth = await checkAIAccess(configuration, aiOptions);\n\n if (!hasCMSAuth) return;\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 // OAuth handled by API proxy internally\n\n appLogger(`Base locale is ${formatLocale(baseLocale)}`);\n appLogger(\n `Translating ${colorizeNumber(locales.length)} locales: [ ${formatLocale(locales)} ]`\n );\n\n appLogger(`Translating ${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 `Translating 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 // check if the file exist, otherwise create it\n if (!existsSync(outputFilePath)) {\n appLogger(`File ${outputFilePath} does not exist, creating it...`);\n mkdirSync(dirname(outputFilePath), { recursive: true });\n writeFileSync(outputFilePath, '');\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 await translateFile(\n absoluteBaseFilePath,\n outputFilePath,\n locale as Locales,\n baseLocale,\n aiOptions,\n configuration,\n customInstructions\n );\n })\n )\n );\n\n await Promise.all(tasks);\n};\n"],"mappings":"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","names":[]}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { getIntlayerAPIProxy } from "@intlayer/api";
|
|
2
|
+
import { extractErrorMessage } from "@intlayer/chokidar";
|
|
2
3
|
import { getAppLogger } from "@intlayer/config";
|
|
3
4
|
const checkCMSAuth = async (configuration) => {
|
|
4
5
|
const appLogger = getAppLogger(configuration, {
|
|
@@ -17,13 +18,7 @@ const checkCMSAuth = async (configuration) => {
|
|
|
17
18
|
try {
|
|
18
19
|
await intlayerAPI.oAuth.getOAuth2AccessToken();
|
|
19
20
|
} catch (error) {
|
|
20
|
-
|
|
21
|
-
try {
|
|
22
|
-
const jsonError = JSON.parse(error.message);
|
|
23
|
-
message = jsonError?.message ?? jsonError;
|
|
24
|
-
} catch (error2) {
|
|
25
|
-
message = `${error2.message} Error getting OAuth2 access token. Your token might be expired.`;
|
|
26
|
-
}
|
|
21
|
+
const message = extractErrorMessage(error);
|
|
27
22
|
appLogger(message, {
|
|
28
23
|
level: "error"
|
|
29
24
|
});
|
|
@@ -45,7 +40,10 @@ const checkAIAccess = async (configuration, aiOptions) => {
|
|
|
45
40
|
});
|
|
46
41
|
return false;
|
|
47
42
|
}
|
|
48
|
-
|
|
43
|
+
if (!hasHisOwnAIAPIKey) {
|
|
44
|
+
return await checkCMSAuth(configuration);
|
|
45
|
+
}
|
|
46
|
+
return true;
|
|
49
47
|
};
|
|
50
48
|
export {
|
|
51
49
|
checkAIAccess,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/utils/checkAccess.ts"],"sourcesContent":["import type { AIOptions } from '@intlayer/api';\nimport { getIntlayerAPIProxy } from '@intlayer/api';\nimport { getAppLogger, type IntlayerConfig } from '@intlayer/config';\n\nexport const checkCMSAuth = async (\n configuration: IntlayerConfig\n): Promise<boolean> => {\n const appLogger = getAppLogger(configuration, {\n config: {\n prefix: '',\n },\n });\n\n const hasCMSAuth =\n configuration.editor.clientId && configuration.editor.clientSecret;\n if (!hasCMSAuth) {\n appLogger('CMS auth not provided.', {\n level: 'error',\n });\n\n return false;\n }\n const intlayerAPI = getIntlayerAPIProxy(undefined, configuration);\n\n try {\n await intlayerAPI.oAuth.getOAuth2AccessToken();\n } catch (error) {\n
|
|
1
|
+
{"version":3,"sources":["../../../src/utils/checkAccess.ts"],"sourcesContent":["import type { AIOptions } from '@intlayer/api';\nimport { getIntlayerAPIProxy } from '@intlayer/api';\nimport { extractErrorMessage } from '@intlayer/chokidar';\nimport { getAppLogger, type IntlayerConfig } from '@intlayer/config';\n\nexport const checkCMSAuth = async (\n configuration: IntlayerConfig\n): Promise<boolean> => {\n const appLogger = getAppLogger(configuration, {\n config: {\n prefix: '',\n },\n });\n\n const hasCMSAuth =\n configuration.editor.clientId && configuration.editor.clientSecret;\n if (!hasCMSAuth) {\n appLogger('CMS auth not provided.', {\n level: 'error',\n });\n\n return false;\n }\n const intlayerAPI = getIntlayerAPIProxy(undefined, configuration);\n\n try {\n await intlayerAPI.oAuth.getOAuth2AccessToken();\n } catch (error) {\n const message = extractErrorMessage(error);\n\n appLogger(message, {\n level: 'error',\n });\n return false;\n }\n\n return true;\n};\n\nexport const checkAIAccess = async (\n configuration: IntlayerConfig,\n aiOptions?: AIOptions\n): Promise<boolean> => {\n const appLogger = getAppLogger(configuration, {\n config: {\n prefix: '',\n },\n });\n\n const hasCMSAuth =\n configuration.editor.clientId && configuration.editor.clientSecret;\n const hasHisOwnAIAPIKey = configuration.ai?.apiKey || aiOptions?.apiKey;\n\n // User need to provide either his own AI API key or the CMS auth\n if (!hasCMSAuth && !hasHisOwnAIAPIKey) {\n appLogger('AI options or API key not provided.', {\n level: 'error',\n });\n\n return false;\n }\n\n // If the user do not have his own AI API key, we need to check the CMS auth\n if (!hasHisOwnAIAPIKey) {\n return await checkCMSAuth(configuration);\n }\n\n return true;\n};\n"],"mappings":"AACA,SAAS,2BAA2B;AACpC,SAAS,2BAA2B;AACpC,SAAS,oBAAyC;AAE3C,MAAM,eAAe,OAC1B,kBACqB;AACrB,QAAM,YAAY,aAAa,eAAe;AAAA,IAC5C,QAAQ;AAAA,MACN,QAAQ;AAAA,IACV;AAAA,EACF,CAAC;AAED,QAAM,aACJ,cAAc,OAAO,YAAY,cAAc,OAAO;AACxD,MAAI,CAAC,YAAY;AACf,cAAU,0BAA0B;AAAA,MAClC,OAAO;AAAA,IACT,CAAC;AAED,WAAO;AAAA,EACT;AACA,QAAM,cAAc,oBAAoB,QAAW,aAAa;AAEhE,MAAI;AACF,UAAM,YAAY,MAAM,qBAAqB;AAAA,EAC/C,SAAS,OAAO;AACd,UAAM,UAAU,oBAAoB,KAAK;AAEzC,cAAU,SAAS;AAAA,MACjB,OAAO;AAAA,IACT,CAAC;AACD,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAEO,MAAM,gBAAgB,OAC3B,eACA,cACqB;AACrB,QAAM,YAAY,aAAa,eAAe;AAAA,IAC5C,QAAQ;AAAA,MACN,QAAQ;AAAA,IACV;AAAA,EACF,CAAC;AAED,QAAM,aACJ,cAAc,OAAO,YAAY,cAAc,OAAO;AACxD,QAAM,oBAAoB,cAAc,IAAI,UAAU,WAAW;AAGjE,MAAI,CAAC,cAAc,CAAC,mBAAmB;AACrC,cAAU,uCAAuC;AAAA,MAC/C,OAAO;AAAA,IACT,CAAC;AAED,WAAO;AAAA,EACT;AAGA,MAAI,CAAC,mBAAmB;AACtB,WAAO,MAAM,aAAa,aAAa;AAAA,EACzC;AAEA,SAAO;AACT;","names":[]}
|
|
@@ -1,14 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
getIntlayerAPIProxy
|
|
3
3
|
} from "@intlayer/api";
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
retryManager
|
|
7
|
-
} from "@intlayer/config";
|
|
8
|
-
const chunkInference = async (messages, aiOptions, configOptions) => {
|
|
4
|
+
import { retryManager } from "@intlayer/config";
|
|
5
|
+
const chunkInference = async (messages, aiOptions, configuration) => {
|
|
9
6
|
let lastResult;
|
|
10
7
|
await retryManager(async () => {
|
|
11
|
-
const configuration = getConfiguration(configOptions);
|
|
12
8
|
const api = getIntlayerAPIProxy(void 0, configuration);
|
|
13
9
|
const response = await api.ai.customQuery({
|
|
14
10
|
aiOptions,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/utils/chunkInference.ts"],"sourcesContent":["import {\n type AIOptions,\n getIntlayerAPIProxy,\n type Messages,\n} from '@intlayer/api';\nimport {
|
|
1
|
+
{"version":3,"sources":["../../../src/utils/chunkInference.ts"],"sourcesContent":["import {\n type AIOptions,\n getIntlayerAPIProxy,\n type Messages,\n} from '@intlayer/api';\nimport { type IntlayerConfig, retryManager } from '@intlayer/config';\n\ntype ChunkInferenceResult = {\n fileContent: string;\n tokenUsed: number;\n};\n\n/**\n * Translates a single chunk via the OpenAI API.\n * Includes retry logic if the call fails.\n */\nexport const chunkInference = async (\n messages: Messages,\n aiOptions?: AIOptions,\n configuration?: IntlayerConfig\n): Promise<ChunkInferenceResult> => {\n let lastResult: ChunkInferenceResult;\n\n await retryManager(async () => {\n const api = getIntlayerAPIProxy(undefined, configuration);\n\n const response = await api.ai.customQuery({\n aiOptions,\n messages,\n });\n\n if (!response.data) {\n throw new Error('No response from AI API');\n }\n\n const { fileContent, tokenUsed } = response.data;\n\n const newContent = fileContent\n .replaceAll('///chunksStart///', '')\n .replaceAll('///chunkStart///', '')\n .replaceAll('///chunksEnd///', '')\n .replaceAll('///chunkEnd///', '')\n .replaceAll('///chunksStart///', '')\n .replaceAll('chunkStart///', '')\n .replaceAll('chunksEnd///', '')\n .replaceAll('chunkEnd///', '')\n .replaceAll('///chunksStart', '')\n .replaceAll('///chunkStart', '')\n .replaceAll('///chunksEnd', '')\n .replaceAll('///chunkEnd', '')\n .replaceAll('chunksStart', '')\n .replaceAll('chunkStart', '')\n .replaceAll('chunksEnd', '')\n .replaceAll('chunkEnd', '');\n\n lastResult = {\n fileContent: newContent,\n tokenUsed,\n };\n })();\n\n return lastResult!;\n};\n"],"mappings":"AAAA;AAAA,EAEE;AAAA,OAEK;AACP,SAA8B,oBAAoB;AAW3C,MAAM,iBAAiB,OAC5B,UACA,WACA,kBACkC;AAClC,MAAI;AAEJ,QAAM,aAAa,YAAY;AAC7B,UAAM,MAAM,oBAAoB,QAAW,aAAa;AAExD,UAAM,WAAW,MAAM,IAAI,GAAG,YAAY;AAAA,MACxC;AAAA,MACA;AAAA,IACF,CAAC;AAED,QAAI,CAAC,SAAS,MAAM;AAClB,YAAM,IAAI,MAAM,yBAAyB;AAAA,IAC3C;AAEA,UAAM,EAAE,aAAa,UAAU,IAAI,SAAS;AAE5C,UAAM,aAAa,YAChB,WAAW,qBAAqB,EAAE,EAClC,WAAW,oBAAoB,EAAE,EACjC,WAAW,mBAAmB,EAAE,EAChC,WAAW,kBAAkB,EAAE,EAC/B,WAAW,qBAAqB,EAAE,EAClC,WAAW,iBAAiB,EAAE,EAC9B,WAAW,gBAAgB,EAAE,EAC7B,WAAW,eAAe,EAAE,EAC5B,WAAW,kBAAkB,EAAE,EAC/B,WAAW,iBAAiB,EAAE,EAC9B,WAAW,gBAAgB,EAAE,EAC7B,WAAW,eAAe,EAAE,EAC5B,WAAW,eAAe,EAAE,EAC5B,WAAW,cAAc,EAAE,EAC3B,WAAW,aAAa,EAAE,EAC1B,WAAW,YAAY,EAAE;AAE5B,iBAAa;AAAA,MACX,aAAa;AAAA,MACb;AAAA,IACF;AAAA,EACF,CAAC,EAAE;AAEH,SAAO;AACT;","names":[]}
|
package/dist/types/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA4BpC,eAAO,MAAM,OAAO,QAEP,CAAC;AA+Hd,KAAK,UAAU,GAAG;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,GAAG,UAAU,CAAC;AA2Cf;;;;;;;GAOG;AACH,eAAO,MAAM,MAAM,QAAO,
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA4BpC,eAAO,MAAM,OAAO,QAEP,CAAC;AA+Hd,KAAK,UAAU,GAAG;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,GAAG,UAAU,CAAC;AA2Cf;;;;;;;GAOG;AACH,eAAO,MAAM,MAAM,QAAO,OA8XzB,CAAC"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { AIOptions } from '@intlayer/api';
|
|
2
2
|
import { ListGitFilesOptions } from '@intlayer/chokidar';
|
|
3
|
-
import { GetConfigurationOptions, Locales } from '@intlayer/config';
|
|
3
|
+
import { GetConfigurationOptions, IntlayerConfig, Locales } from '@intlayer/config';
|
|
4
4
|
/**
|
|
5
5
|
* Translate a single file for a given locale
|
|
6
6
|
*/
|
|
7
|
-
export declare const reviewFile: (baseFilePath: string, outputFilePath: string, locale: Locales, baseLocale: Locales, aiOptions?: AIOptions,
|
|
7
|
+
export declare const reviewFile: (baseFilePath: string, outputFilePath: string, locale: Locales, baseLocale: Locales, aiOptions?: AIOptions, configuration?: IntlayerConfig, customInstructions?: string, changedLines?: number[]) => Promise<void>;
|
|
8
8
|
type ReviewDocOptions = {
|
|
9
9
|
docPattern: string[];
|
|
10
10
|
locales: Locales[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reviewDoc.d.ts","sourceRoot":"","sources":["../../src/reviewDoc.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAIL,mBAAmB,EACpB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAOL,uBAAuB,EACvB,OAAO,EAER,MAAM,kBAAkB,CAAC;AAoB1B;;GAEG;AACH,eAAO,MAAM,UAAU,GACrB,cAAc,MAAM,EACpB,gBAAgB,MAAM,EACtB,QAAQ,OAAO,EACf,YAAY,OAAO,EACnB,YAAY,SAAS,EACrB,
|
|
1
|
+
{"version":3,"file":"reviewDoc.d.ts","sourceRoot":"","sources":["../../src/reviewDoc.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAIL,mBAAmB,EACpB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAOL,uBAAuB,EACvB,cAAc,EACd,OAAO,EAER,MAAM,kBAAkB,CAAC;AAoB1B;;GAEG;AACH,eAAO,MAAM,UAAU,GACrB,cAAc,MAAM,EACpB,gBAAgB,MAAM,EACtB,QAAQ,OAAO,EACf,YAAY,OAAO,EACnB,YAAY,SAAS,EACrB,gBAAe,cAAmC,EAClD,qBAAqB,MAAM,EAC3B,eAAe,MAAM,EAAE,kBAgJxB,CAAC;AAEF,KAAK,gBAAgB,GAAG;IACtB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,OAAO,EAAE,OAAO,EAAE,CAAC;IACnB,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC,aAAa,CAAC,EAAE,uBAAuB,CAAC;IACxC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,oBAAoB,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAC9C,mBAAmB,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAC7C,UAAU,CAAC,EAAE,mBAAmB,CAAC;CAClC,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,SAAS,GAAU,6LAY7B,gBAAgB,kBAuGlB,CAAC"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { AIOptions } from '@intlayer/api';
|
|
2
2
|
import { ListGitFilesOptions } from '@intlayer/chokidar';
|
|
3
|
-
import { GetConfigurationOptions, Locales } from '@intlayer/config';
|
|
3
|
+
import { GetConfigurationOptions, IntlayerConfig, Locales } from '@intlayer/config';
|
|
4
4
|
/**
|
|
5
5
|
* Translate a single file for a given locale
|
|
6
6
|
*/
|
|
7
|
-
export declare const translateFile: (baseFilePath: string, outputFilePath: string, locale: Locales, baseLocale: Locales, aiOptions?: AIOptions,
|
|
7
|
+
export declare const translateFile: (baseFilePath: string, outputFilePath: string, locale: Locales, baseLocale: Locales, aiOptions?: AIOptions, configuration?: IntlayerConfig, customInstructions?: string) => Promise<void>;
|
|
8
8
|
type TranslateDocOptions = {
|
|
9
9
|
docPattern: string[];
|
|
10
10
|
locales: Locales[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"translateDoc.d.ts","sourceRoot":"","sources":["../../src/translateDoc.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAIL,mBAAmB,EACpB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAOL,uBAAuB,EACvB,OAAO,EAER,MAAM,kBAAkB,CAAC;AAmB1B;;GAEG;AACH,eAAO,MAAM,aAAa,GACxB,cAAc,MAAM,EACpB,gBAAgB,MAAM,EACtB,QAAQ,OAAO,EACf,YAAY,OAAO,EACnB,YAAY,SAAS,EACrB,
|
|
1
|
+
{"version":3,"file":"translateDoc.d.ts","sourceRoot":"","sources":["../../src/translateDoc.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAIL,mBAAmB,EACpB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAOL,uBAAuB,EACvB,cAAc,EACd,OAAO,EAER,MAAM,kBAAkB,CAAC;AAmB1B;;GAEG;AACH,eAAO,MAAM,aAAa,GACxB,cAAc,MAAM,EACpB,gBAAgB,MAAM,EACtB,QAAQ,OAAO,EACf,YAAY,OAAO,EACnB,YAAY,SAAS,EACrB,gBAAe,cAAmC,EAClD,qBAAqB,MAAM,kBA0H5B,CAAC;AAEF,KAAK,mBAAmB,GAAG;IACzB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,OAAO,EAAE,OAAO,EAAE,CAAC;IACnB,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC,aAAa,CAAC,EAAE,uBAAuB,CAAC;IACxC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,oBAAoB,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAC9C,mBAAmB,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAC7C,UAAU,CAAC,EAAE,mBAAmB,CAAC;CAClC,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,YAAY,GAAU,6LAYhC,mBAAmB,kBAgGrB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"checkAccess.d.ts","sourceRoot":"","sources":["../../../src/utils/checkAccess.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"checkAccess.d.ts","sourceRoot":"","sources":["../../../src/utils/checkAccess.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAG/C,OAAO,EAAgB,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAErE,eAAO,MAAM,YAAY,GACvB,eAAe,cAAc,KAC5B,OAAO,CAAC,OAAO,CA8BjB,CAAC;AAEF,eAAO,MAAM,aAAa,GACxB,eAAe,cAAc,EAC7B,YAAY,SAAS,KACpB,OAAO,CAAC,OAAO,CA0BjB,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type AIOptions, type Messages } from '@intlayer/api';
|
|
2
|
-
import { type
|
|
2
|
+
import { type IntlayerConfig } from '@intlayer/config';
|
|
3
3
|
type ChunkInferenceResult = {
|
|
4
4
|
fileContent: string;
|
|
5
5
|
tokenUsed: number;
|
|
@@ -8,6 +8,6 @@ type ChunkInferenceResult = {
|
|
|
8
8
|
* Translates a single chunk via the OpenAI API.
|
|
9
9
|
* Includes retry logic if the call fails.
|
|
10
10
|
*/
|
|
11
|
-
export declare const chunkInference: (messages: Messages, aiOptions?: AIOptions,
|
|
11
|
+
export declare const chunkInference: (messages: Messages, aiOptions?: AIOptions, configuration?: IntlayerConfig) => Promise<ChunkInferenceResult>;
|
|
12
12
|
export {};
|
|
13
13
|
//# sourceMappingURL=chunkInference.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chunkInference.d.ts","sourceRoot":"","sources":["../../../src/utils/chunkInference.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,SAAS,EAEd,KAAK,QAAQ,EACd,MAAM,eAAe,CAAC;AACvB,OAAO,
|
|
1
|
+
{"version":3,"file":"chunkInference.d.ts","sourceRoot":"","sources":["../../../src/utils/chunkInference.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,SAAS,EAEd,KAAK,QAAQ,EACd,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,KAAK,cAAc,EAAgB,MAAM,kBAAkB,CAAC;AAErE,KAAK,oBAAoB,GAAG;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,cAAc,GACzB,UAAU,QAAQ,EAClB,YAAY,SAAS,EACrB,gBAAgB,cAAc,KAC7B,OAAO,CAAC,oBAAoB,CA0C9B,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@intlayer/cli",
|
|
3
|
-
"version": "6.0.
|
|
3
|
+
"version": "6.0.2-canary.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Provides uniform command-line interface scripts for Intlayer, used in packages like intlayer-cli and intlayer.",
|
|
6
6
|
"keywords": [
|
|
@@ -53,12 +53,12 @@
|
|
|
53
53
|
"eventsource": "^3.0.7",
|
|
54
54
|
"fast-glob": "^3.3.3",
|
|
55
55
|
"p-limit": "^3.1.0",
|
|
56
|
-
"@intlayer/
|
|
57
|
-
"@intlayer/
|
|
58
|
-
"@intlayer/dictionaries-entry": "6.0.
|
|
59
|
-
"@intlayer/
|
|
60
|
-
"@intlayer/
|
|
61
|
-
"@intlayer/
|
|
56
|
+
"@intlayer/chokidar": "6.0.2-canary.0",
|
|
57
|
+
"@intlayer/config": "6.0.2-canary.0",
|
|
58
|
+
"@intlayer/dictionaries-entry": "6.0.2-canary.0",
|
|
59
|
+
"@intlayer/unmerged-dictionaries-entry": "6.0.2-canary.0",
|
|
60
|
+
"@intlayer/api": "6.0.2-canary.0",
|
|
61
|
+
"@intlayer/remote-dictionaries-entry": "6.0.2-canary.0"
|
|
62
62
|
},
|
|
63
63
|
"devDependencies": {
|
|
64
64
|
"@types/node": "^24.2.1",
|
|
@@ -71,19 +71,19 @@
|
|
|
71
71
|
"tsup": "^8.5.0",
|
|
72
72
|
"typescript": "^5.9.2",
|
|
73
73
|
"vitest": "^3.2.4",
|
|
74
|
-
"@intlayer/core": "6.0.
|
|
75
|
-
"@utils/eslint-config": "1.0.4",
|
|
74
|
+
"@intlayer/core": "6.0.2-canary.0",
|
|
76
75
|
"@utils/ts-config": "1.0.4",
|
|
76
|
+
"@utils/eslint-config": "1.0.4",
|
|
77
77
|
"@utils/ts-config-types": "1.0.4",
|
|
78
78
|
"@utils/tsup-config": "1.0.4"
|
|
79
79
|
},
|
|
80
80
|
"peerDependencies": {
|
|
81
|
-
"@intlayer/api": "6.0.
|
|
82
|
-
"@intlayer/config": "6.0.
|
|
83
|
-
"@intlayer/chokidar": "6.0.
|
|
84
|
-
"@intlayer/dictionaries-entry": "6.0.
|
|
85
|
-
"@intlayer/remote-dictionaries-entry": "6.0.
|
|
86
|
-
"@intlayer/unmerged-dictionaries-entry": "6.0.
|
|
81
|
+
"@intlayer/api": "6.0.2-canary.0",
|
|
82
|
+
"@intlayer/config": "6.0.2-canary.0",
|
|
83
|
+
"@intlayer/chokidar": "6.0.2-canary.0",
|
|
84
|
+
"@intlayer/dictionaries-entry": "6.0.2-canary.0",
|
|
85
|
+
"@intlayer/remote-dictionaries-entry": "6.0.2-canary.0",
|
|
86
|
+
"@intlayer/unmerged-dictionaries-entry": "6.0.2-canary.0"
|
|
87
87
|
},
|
|
88
88
|
"bug": {
|
|
89
89
|
"url": "https://github.com/aymericzip/intlayer/issues"
|