@intlayer/cli 7.5.14 → 7.6.0-canary.1
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 +4 -4
- package/dist/cjs/cli.cjs.map +1 -1
- package/dist/cjs/config.cjs +1 -1
- package/dist/cjs/config.cjs.map +1 -1
- package/dist/cjs/listContentDeclaration.cjs +1 -1
- package/dist/cjs/listContentDeclaration.cjs.map +1 -1
- package/dist/cjs/pull.cjs +11 -3
- package/dist/cjs/pull.cjs.map +1 -1
- package/dist/cjs/push/push.cjs +17 -7
- package/dist/cjs/push/push.cjs.map +1 -1
- package/dist/cjs/pushConfig.cjs +1 -1
- package/dist/cjs/pushConfig.cjs.map +1 -1
- package/dist/cjs/pushLog.cjs +6 -10
- package/dist/cjs/pushLog.cjs.map +1 -1
- package/dist/cjs/test/test.cjs +1 -1
- package/dist/cjs/test/test.cjs.map +1 -1
- package/dist/cjs/utils/checkAccess.cjs +13 -4
- package/dist/cjs/utils/checkAccess.cjs.map +1 -1
- package/dist/cjs/utils/checkConfigConsistency.cjs +8 -16
- package/dist/cjs/utils/checkConfigConsistency.cjs.map +1 -1
- package/dist/esm/cli.mjs +5 -5
- package/dist/esm/cli.mjs.map +1 -1
- package/dist/esm/config.mjs +1 -1
- package/dist/esm/config.mjs.map +1 -1
- package/dist/esm/listContentDeclaration.mjs +1 -1
- package/dist/esm/listContentDeclaration.mjs.map +1 -1
- package/dist/esm/pull.mjs +11 -3
- package/dist/esm/pull.mjs.map +1 -1
- package/dist/esm/push/push.mjs +18 -8
- package/dist/esm/push/push.mjs.map +1 -1
- package/dist/esm/pushConfig.mjs +1 -1
- package/dist/esm/pushConfig.mjs.map +1 -1
- package/dist/esm/pushLog.mjs +7 -11
- package/dist/esm/pushLog.mjs.map +1 -1
- package/dist/esm/test/test.mjs +1 -1
- package/dist/esm/test/test.mjs.map +1 -1
- package/dist/esm/utils/checkAccess.mjs +13 -4
- package/dist/esm/utils/checkAccess.mjs.map +1 -1
- package/dist/esm/utils/checkConfigConsistency.mjs +8 -16
- package/dist/esm/utils/checkConfigConsistency.mjs.map +1 -1
- package/dist/types/cli.d.ts.map +1 -1
- package/dist/types/pull.d.ts.map +1 -1
- package/dist/types/push/push.d.ts.map +1 -1
- package/dist/types/pushLog.d.ts +0 -2
- package/dist/types/pushLog.d.ts.map +1 -1
- package/dist/types/translation-alignment/computeSimilarity.d.ts.map +1 -1
- package/dist/types/translation-alignment/rebuildDocument.d.ts.map +1 -1
- package/dist/types/utils/checkAccess.d.ts.map +1 -1
- package/dist/types/utils/checkConfigConsistency.d.ts +1 -9
- package/dist/types/utils/checkConfigConsistency.d.ts.map +1 -1
- package/package.json +12 -12
package/dist/cjs/cli.cjs
CHANGED
|
@@ -115,14 +115,13 @@ const extractConfigOptions = (options) => {
|
|
|
115
115
|
if (!Object.values(filteredOptions).some(Boolean)) return;
|
|
116
116
|
const { baseDir, env, envFile, verbose, prefix, noCache } = options;
|
|
117
117
|
const addPrefix = Boolean(options.with);
|
|
118
|
+
if (typeof prefix === "string") (0, _intlayer_config.setPrefix)(prefix);
|
|
119
|
+
else if (addPrefix) (0, _intlayer_config.setPrefix)(configuration.log.prefix);
|
|
118
120
|
return removeUndefined({
|
|
119
121
|
baseDir,
|
|
120
122
|
env,
|
|
121
123
|
envFile,
|
|
122
|
-
override: { log: {
|
|
123
|
-
prefix: prefix ?? addPrefix ? configuration.log.prefix : "",
|
|
124
|
-
verbose: verbose ?? true
|
|
125
|
-
} },
|
|
124
|
+
override: { log: { verbose: verbose ?? true } },
|
|
126
125
|
cache: !noCache
|
|
127
126
|
});
|
|
128
127
|
};
|
|
@@ -135,6 +134,7 @@ const extractConfigOptions = (options) => {
|
|
|
135
134
|
* npm run intlayer push --dictionaries id1 id2 id3 --deleteLocaleDir
|
|
136
135
|
*/
|
|
137
136
|
const setAPI = () => {
|
|
137
|
+
(0, _intlayer_config.setPrefix)("");
|
|
138
138
|
const program = new commander.Command();
|
|
139
139
|
program.version(packageJson.version).description("Intlayer CLI");
|
|
140
140
|
program.command("version").description("Print the Intlayer CLI version").action(() => {
|
package/dist/cjs/cli.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.cjs","names":["getParentPackageJSON","Command","login","init","push","fill","translateDoc","reviewDoc","liveSync"],"sources":["../../src/cli.ts"],"sourcesContent":["import { dirname as pathDirname } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type { AIOptions as BaseAIOptions } from '@intlayer/api';\nimport type { DiffMode, ListGitFilesOptions } from '@intlayer/chokidar';\nimport {\n type GetConfigurationOptions,\n getConfiguration,\n} from '@intlayer/config';\nimport { Command } from 'commander';\nimport { login } from './auth/login';\nimport { build } from './build';\nimport { runCI } from './ci';\nimport { getConfig } from './config';\nimport { startEditor } from './editor';\nimport { type FillOptions, fill } from './fill/fill';\nimport { init } from './init';\nimport { listContentDeclaration } from './listContentDeclaration';\nimport { listProjectsCommand } from './listProjects';\nimport { liveSync } from './liveSync';\nimport { pull } from './pull';\nimport { push } from './push/push';\nimport { pushConfig } from './pushConfig';\nimport { reviewDoc } from './reviewDoc/reviewDoc';\nimport { testMissingTranslations } from './test';\nimport { transform } from './transform';\nimport { translateDoc } from './translateDoc/translateDoc';\nimport { getParentPackageJSON } from './utils/getParentPackageJSON';\nimport { watchContentDeclaration } from './watch';\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 (default to true using CLI)'],\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 ['--no-cache [noCache]', 'No cache'],\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]) => {\n command.option(flag, description);\n });\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 const configuration = getConfiguration();\n const { ai } = configuration;\n\n return removeUndefined({\n ...ai,\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 noCache?: boolean;\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 configuration = getConfiguration(options);\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, noCache } = options;\n\n const addPrefix: boolean = Boolean((options as any).with); // Hack to add the prefix when the command is run in parallel\n const log = {\n prefix: (prefix ?? addPrefix) ? configuration.log.prefix : '', // Should not consider the prefix set in the intlayer configuration file\n verbose: verbose ?? true,\n };\n\n const override = {\n log,\n };\n\n return removeUndefined({\n baseDir,\n env,\n envFile,\n override,\n cache: !noCache,\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 // Explicit version subcommand for convenience: `npx intlayer version`\n program\n .command('version')\n .description('Print the Intlayer CLI version')\n .action(() => {\n // Prefer the resolved package.json version; fallback to unknown\n // Keeping output minimal to align with common CLI behavior\n console.log(packageJson.version ?? 'unknown');\n });\n\n /**\n * AUTH\n */\n const loginCmd = program\n .command('login')\n .description('Login to Intlayer')\n .option('--cms-url [cmsUrl]', 'CMS URL');\n\n applyConfigOptions(loginCmd);\n\n loginCmd.action((options) => {\n const configOptions = extractConfigOptions(options) ?? {\n override: {\n log: {\n prefix: '',\n verbose: true,\n },\n },\n };\n\n return login({\n cmsUrl: options.cmsUrl,\n configOptions,\n });\n });\n\n /**\n * INIT\n */\n program\n .command('init')\n .description('Initialize Intlayer in the project')\n .option('--project-root [projectRoot]', 'Project root directory')\n .action((options) => init(options.projectRoot));\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: [\n ['-w, --watch', 'Watch for changes'],\n ['--skip-prepare', 'Skip the prepare step'],\n ['--with [with...]', 'Start command in parallel with the build'],\n ],\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 const watchOptions = {\n description: 'Watch the dictionaries changes',\n options: [['--with [with...]', 'Start command in parallel with the build']],\n };\n\n // Add build command to dictionaries program\n const dictionariesWatchCmd = dictionariesProgram\n .command('watch')\n .description(buildOptions.description);\n\n applyOptions(dictionariesWatchCmd, watchOptions.options);\n applyConfigOptions(dictionariesWatchCmd);\n dictionariesWatchCmd.action((options) => {\n watchContentDeclaration({\n ...options,\n configOptions: extractConfigOptions(options),\n });\n });\n\n // Add build command to root program as well\n const rootWatchCmd = program\n .command('watch')\n .description(buildOptions.description);\n\n applyOptions(rootWatchCmd, watchOptions.options);\n applyConfigOptions(rootWatchCmd);\n rootWatchCmd.action((options) => {\n watchContentDeclaration({\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 [\n '--dictionary [ids...]',\n 'List of dictionary IDs to pull (alias for --dictionaries)',\n ],\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 // Merge dictionary aliases\n const dictionaries = [\n ...(options.dictionaries ?? []),\n ...(options.dictionary ?? []),\n ];\n\n pull({\n ...options,\n dictionaries: dictionaries.length > 0 ? dictionaries : undefined,\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 // Merge dictionary aliases\n const dictionaries = [\n ...(options.dictionaries ?? []),\n ...(options.dictionary ?? []),\n ];\n\n pull({\n ...options,\n dictionaries: dictionaries.length > 0 ? dictionaries : undefined,\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 '--dictionary [ids...]',\n 'List of dictionary IDs to push (alias for --dictionaries)',\n ],\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 '--build [build]',\n 'Build the dictionaries before pushing to ensure the content is up to date. True will force the build, false will skip the build, undefined will allow using the cache of the build',\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 // Merge dictionary aliases\n const dictionaries = [\n ...(options.dictionaries || []),\n ...(options.dictionary || []),\n ];\n\n return push({\n ...options,\n dictionaries: dictionaries.length > 0 ? dictionaries : undefined,\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 // Merge dictionary aliases\n const dictionaries = [\n ...(options.dictionaries || []),\n ...(options.dictionary || []),\n ];\n\n return push({\n ...options,\n dictionaries: dictionaries.length > 0 ? dictionaries : undefined,\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 * PROJECTS\n */\n\n const projectsProgram = program\n .command('projects')\n .alias('project')\n .description('List Intlayer projects');\n\n const projectsListCmd = projectsProgram\n .command('list')\n .description('List all Intlayer projects in the directory')\n .option('--base-dir [baseDir]', 'Base directory to search from')\n .option(\n '--git-root',\n 'Search from the git root directory instead of the base directory'\n )\n .option('--json', 'Output the results as JSON');\n\n projectsListCmd.action((options) => {\n listProjectsCommand({\n baseDir: options.baseDir,\n gitRoot: options.gitRoot,\n json: options.json,\n });\n });\n\n // Add alias for projects list command at root level\n const rootProjectsListCmd = program\n .command('projects-list')\n .alias('pl')\n .description('List all Intlayer projects in the directory')\n .option('--base-dir [baseDir]', 'Base directory to search from')\n .option(\n '--git-root',\n 'Search from the git root directory instead of the base directory'\n )\n .option('--absolute', 'Output the results as absolute paths')\n .option('--json', 'Output the results as JSON');\n\n rootProjectsListCmd.action((options) => {\n listProjectsCommand({\n baseDir: options.baseDir,\n gitRoot: options.gitRoot,\n json: options.json,\n absolute: options.absolute,\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 .option('--json', 'Output the results as JSON')\n .option('--absolute', 'Output the results as absolute paths')\n .action((options) => {\n listContentDeclaration({\n json: options.json,\n absolute: options.absolute,\n });\n });\n\n // Add alias for content list command\n program\n .command('list')\n .description('List the content declaration files')\n .option('--json', 'Output the results as JSON')\n .option('--absolute', 'Output the results as absolute paths')\n .action((options) => {\n listContentDeclaration({\n json: options.json,\n absolute: options.absolute,\n });\n });\n\n const testProgram = contentProgram\n .command('test')\n .description('Test if there are missing translations')\n .option(\n '--build [build]',\n 'Build the dictionaries before testing to ensure the content is up to date. True will force the build, false will skip the build, undefined will allow using the cache of the build'\n );\n\n applyConfigOptions(testProgram);\n testProgram.action((options) => {\n testMissingTranslations({\n ...options,\n configOptions: extractConfigOptions(options),\n });\n });\n\n // Add alias for content test command\n const rootTestCmd = program\n .command('test')\n .description('Test if there are missing translations')\n .option(\n '--build [build]',\n 'Build the dictionaries before testing to ensure the content is up to date. True will force the build, false will skip the build, undefined will allow using the cache of the build'\n );\n\n applyConfigOptions(rootTestCmd);\n rootTestCmd.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 '--key [keys...]',\n 'Filter dictionaries based on keys (alias for --keys)'\n )\n .option(\n '--excluded-keys [excludedKeys...]',\n 'Filter out dictionaries based on keys'\n )\n .option(\n '--excluded-key [excludedKeys...]',\n 'Filter out dictionaries based on keys (alias for --excluded-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. True will force the build, false will skip the build, undefined will allow using the cache of the build'\n )\n .option(\n '--skip-metadata',\n 'Skip filling missing metadata (description, title, tags) for dictionaries'\n );\n\n applyConfigOptions(fillProgram);\n applyAIOptions(fillProgram);\n applyGitOptions(fillProgram);\n\n fillProgram.action((options) => {\n // Merge key aliases\n const keys = [...(options.keys ?? []), ...(options.key ?? [])];\n const excludedKeys = [\n ...(options.excludedKeys ?? []),\n ...(options.excludedKey ?? []),\n ];\n // Merge dictionary aliases\n const dictionaries = [\n ...(options.dictionaries ?? []),\n ...(options.dictionary ?? []),\n ];\n\n return fill({\n ...options,\n keys: keys.length > 0 ? keys : undefined,\n excludedKeys: excludedKeys.length > 0 ? excludedKeys : undefined,\n dictionaries: dictionaries.length > 0 ? dictionaries : undefined,\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 ['--skip-if-exists', 'Skip the file if it already exists'],\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 skipIfExists: options.skipIfExists,\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 skipIfExists: options.skipIfExists,\n })\n );\n\n /**\n * LIVE SYNC\n */\n\n const liveOptions = [\n ['--with [with...]', '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 applyConfigOptions(liveCmd);\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 /**\n * TRANSFORM\n */\n const transformProgram = program\n .command('transform')\n .alias('trans')\n .description('Transform components to use Intlayer');\n\n transformProgram\n .option('-f, --file [files...]', 'List of files to transform')\n .option(\n '-o, --output-content-declarations [outputContentDeclarations]',\n 'Path to output content declaration files'\n )\n .option('--code-only', 'Only transform the component code', false)\n .option('--declaration-only', 'Only generate content declaration', false)\n .action((options) => {\n transform({\n files: options.file,\n outputContentDeclarations: options.outputContentDeclarations,\n configOptions: extractConfigOptions(options),\n codeOnly: options.codeOnly,\n declarationOnly: options.declarationOnly,\n });\n });\n\n applyConfigOptions(transformProgram);\n\n program.parse(process.argv);\n\n /**\n * CI / AUTOMATION\n *\n * Used to iterate over all projects in a monorepo, and help to parse secrets\n */\n program\n .command('ci')\n .description(\n 'Run Intlayer commands with auto-injected credentials from INTLAYER_PROJECT_CREDENTIALS. Detects current project or iterates over all projects.'\n )\n .argument(\n '<command...>',\n 'The intlayer command to execute (e.g., \"fill\", \"push\")'\n )\n .allowUnknownOption() // Allows passing flags like --verbose to the subcommand\n .action((args) => {\n runCI(args);\n });\n\n return program;\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cli.cjs","names":["getParentPackageJSON","Command","login","init","push","fill","translateDoc","reviewDoc","liveSync"],"sources":["../../src/cli.ts"],"sourcesContent":["import { dirname as pathDirname } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type { AIOptions as BaseAIOptions } from '@intlayer/api';\nimport type { DiffMode, ListGitFilesOptions } from '@intlayer/chokidar';\nimport {\n type GetConfigurationOptions,\n getConfiguration,\n setPrefix,\n} from '@intlayer/config';\nimport { Command } from 'commander';\nimport { login } from './auth/login';\nimport { build } from './build';\nimport { runCI } from './ci';\nimport { getConfig } from './config';\nimport { startEditor } from './editor';\nimport { type FillOptions, fill } from './fill/fill';\nimport { init } from './init';\nimport { listContentDeclaration } from './listContentDeclaration';\nimport { listProjectsCommand } from './listProjects';\nimport { liveSync } from './liveSync';\nimport { pull } from './pull';\nimport { push } from './push/push';\nimport { pushConfig } from './pushConfig';\nimport { reviewDoc } from './reviewDoc/reviewDoc';\nimport { testMissingTranslations } from './test';\nimport { transform } from './transform';\nimport { translateDoc } from './translateDoc/translateDoc';\nimport { getParentPackageJSON } from './utils/getParentPackageJSON';\nimport { watchContentDeclaration } from './watch';\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 (default to true using CLI)'],\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 ['--no-cache [noCache]', 'No cache'],\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]) => {\n command.option(flag, description);\n });\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 const configuration = getConfiguration();\n const { ai } = configuration;\n\n return removeUndefined({\n ...ai,\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 noCache?: boolean;\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 configuration = getConfiguration(options);\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, noCache } = options;\n\n const addPrefix: boolean = Boolean((options as any).with); // Hack to add the prefix when the command is run in parallel\n\n if (typeof prefix === 'string') {\n setPrefix(prefix);\n } else if (addPrefix) {\n setPrefix(configuration.log.prefix);\n }\n\n const log = {\n verbose: verbose ?? true,\n };\n\n const override = {\n log,\n };\n\n return removeUndefined({\n baseDir,\n env,\n envFile,\n override,\n cache: !noCache,\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 setPrefix('');\n const program = new Command();\n\n program.version(packageJson.version!).description('Intlayer CLI');\n\n // Explicit version subcommand for convenience: `npx intlayer version`\n program\n .command('version')\n .description('Print the Intlayer CLI version')\n .action(() => {\n // Prefer the resolved package.json version; fallback to unknown\n // Keeping output minimal to align with common CLI behavior\n console.log(packageJson.version ?? 'unknown');\n });\n\n /**\n * AUTH\n */\n const loginCmd = program\n .command('login')\n .description('Login to Intlayer')\n .option('--cms-url [cmsUrl]', 'CMS URL');\n\n applyConfigOptions(loginCmd);\n\n loginCmd.action((options) => {\n const configOptions = extractConfigOptions(options) ?? {\n override: {\n log: {\n prefix: '',\n verbose: true,\n },\n },\n };\n\n return login({\n cmsUrl: options.cmsUrl,\n configOptions,\n });\n });\n\n /**\n * INIT\n */\n program\n .command('init')\n .description('Initialize Intlayer in the project')\n .option('--project-root [projectRoot]', 'Project root directory')\n .action((options) => init(options.projectRoot));\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: [\n ['-w, --watch', 'Watch for changes'],\n ['--skip-prepare', 'Skip the prepare step'],\n ['--with [with...]', 'Start command in parallel with the build'],\n ],\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 const watchOptions = {\n description: 'Watch the dictionaries changes',\n options: [['--with [with...]', 'Start command in parallel with the build']],\n };\n\n // Add build command to dictionaries program\n const dictionariesWatchCmd = dictionariesProgram\n .command('watch')\n .description(buildOptions.description);\n\n applyOptions(dictionariesWatchCmd, watchOptions.options);\n applyConfigOptions(dictionariesWatchCmd);\n dictionariesWatchCmd.action((options) => {\n watchContentDeclaration({\n ...options,\n configOptions: extractConfigOptions(options),\n });\n });\n\n // Add build command to root program as well\n const rootWatchCmd = program\n .command('watch')\n .description(buildOptions.description);\n\n applyOptions(rootWatchCmd, watchOptions.options);\n applyConfigOptions(rootWatchCmd);\n rootWatchCmd.action((options) => {\n watchContentDeclaration({\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 [\n '--dictionary [ids...]',\n 'List of dictionary IDs to pull (alias for --dictionaries)',\n ],\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 // Merge dictionary aliases\n const dictionaries = [\n ...(options.dictionaries ?? []),\n ...(options.dictionary ?? []),\n ];\n\n pull({\n ...options,\n dictionaries: dictionaries.length > 0 ? dictionaries : undefined,\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 // Merge dictionary aliases\n const dictionaries = [\n ...(options.dictionaries ?? []),\n ...(options.dictionary ?? []),\n ];\n\n pull({\n ...options,\n dictionaries: dictionaries.length > 0 ? dictionaries : undefined,\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 '--dictionary [ids...]',\n 'List of dictionary IDs to push (alias for --dictionaries)',\n ],\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 '--build [build]',\n 'Build the dictionaries before pushing to ensure the content is up to date. True will force the build, false will skip the build, undefined will allow using the cache of the build',\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 // Merge dictionary aliases\n const dictionaries = [\n ...(options.dictionaries || []),\n ...(options.dictionary || []),\n ];\n\n return push({\n ...options,\n dictionaries: dictionaries.length > 0 ? dictionaries : undefined,\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 // Merge dictionary aliases\n const dictionaries = [\n ...(options.dictionaries || []),\n ...(options.dictionary || []),\n ];\n\n return push({\n ...options,\n dictionaries: dictionaries.length > 0 ? dictionaries : undefined,\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 * PROJECTS\n */\n\n const projectsProgram = program\n .command('projects')\n .alias('project')\n .description('List Intlayer projects');\n\n const projectsListCmd = projectsProgram\n .command('list')\n .description('List all Intlayer projects in the directory')\n .option('--base-dir [baseDir]', 'Base directory to search from')\n .option(\n '--git-root',\n 'Search from the git root directory instead of the base directory'\n )\n .option('--json', 'Output the results as JSON');\n\n projectsListCmd.action((options) => {\n listProjectsCommand({\n baseDir: options.baseDir,\n gitRoot: options.gitRoot,\n json: options.json,\n });\n });\n\n // Add alias for projects list command at root level\n const rootProjectsListCmd = program\n .command('projects-list')\n .alias('pl')\n .description('List all Intlayer projects in the directory')\n .option('--base-dir [baseDir]', 'Base directory to search from')\n .option(\n '--git-root',\n 'Search from the git root directory instead of the base directory'\n )\n .option('--absolute', 'Output the results as absolute paths')\n .option('--json', 'Output the results as JSON');\n\n rootProjectsListCmd.action((options) => {\n listProjectsCommand({\n baseDir: options.baseDir,\n gitRoot: options.gitRoot,\n json: options.json,\n absolute: options.absolute,\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 .option('--json', 'Output the results as JSON')\n .option('--absolute', 'Output the results as absolute paths')\n .action((options) => {\n listContentDeclaration({\n json: options.json,\n absolute: options.absolute,\n });\n });\n\n // Add alias for content list command\n program\n .command('list')\n .description('List the content declaration files')\n .option('--json', 'Output the results as JSON')\n .option('--absolute', 'Output the results as absolute paths')\n .action((options) => {\n listContentDeclaration({\n json: options.json,\n absolute: options.absolute,\n });\n });\n\n const testProgram = contentProgram\n .command('test')\n .description('Test if there are missing translations')\n .option(\n '--build [build]',\n 'Build the dictionaries before testing to ensure the content is up to date. True will force the build, false will skip the build, undefined will allow using the cache of the build'\n );\n\n applyConfigOptions(testProgram);\n testProgram.action((options) => {\n testMissingTranslations({\n ...options,\n configOptions: extractConfigOptions(options),\n });\n });\n\n // Add alias for content test command\n const rootTestCmd = program\n .command('test')\n .description('Test if there are missing translations')\n .option(\n '--build [build]',\n 'Build the dictionaries before testing to ensure the content is up to date. True will force the build, false will skip the build, undefined will allow using the cache of the build'\n );\n\n applyConfigOptions(rootTestCmd);\n rootTestCmd.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 '--key [keys...]',\n 'Filter dictionaries based on keys (alias for --keys)'\n )\n .option(\n '--excluded-keys [excludedKeys...]',\n 'Filter out dictionaries based on keys'\n )\n .option(\n '--excluded-key [excludedKeys...]',\n 'Filter out dictionaries based on keys (alias for --excluded-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. True will force the build, false will skip the build, undefined will allow using the cache of the build'\n )\n .option(\n '--skip-metadata',\n 'Skip filling missing metadata (description, title, tags) for dictionaries'\n );\n\n applyConfigOptions(fillProgram);\n applyAIOptions(fillProgram);\n applyGitOptions(fillProgram);\n\n fillProgram.action((options) => {\n // Merge key aliases\n const keys = [...(options.keys ?? []), ...(options.key ?? [])];\n const excludedKeys = [\n ...(options.excludedKeys ?? []),\n ...(options.excludedKey ?? []),\n ];\n // Merge dictionary aliases\n const dictionaries = [\n ...(options.dictionaries ?? []),\n ...(options.dictionary ?? []),\n ];\n\n return fill({\n ...options,\n keys: keys.length > 0 ? keys : undefined,\n excludedKeys: excludedKeys.length > 0 ? excludedKeys : undefined,\n dictionaries: dictionaries.length > 0 ? dictionaries : undefined,\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 ['--skip-if-exists', 'Skip the file if it already exists'],\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 skipIfExists: options.skipIfExists,\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 skipIfExists: options.skipIfExists,\n })\n );\n\n /**\n * LIVE SYNC\n */\n\n const liveOptions = [\n ['--with [with...]', '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 applyConfigOptions(liveCmd);\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 /**\n * TRANSFORM\n */\n const transformProgram = program\n .command('transform')\n .alias('trans')\n .description('Transform components to use Intlayer');\n\n transformProgram\n .option('-f, --file [files...]', 'List of files to transform')\n .option(\n '-o, --output-content-declarations [outputContentDeclarations]',\n 'Path to output content declaration files'\n )\n .option('--code-only', 'Only transform the component code', false)\n .option('--declaration-only', 'Only generate content declaration', false)\n .action((options) => {\n transform({\n files: options.file,\n outputContentDeclarations: options.outputContentDeclarations,\n configOptions: extractConfigOptions(options),\n codeOnly: options.codeOnly,\n declarationOnly: options.declarationOnly,\n });\n });\n\n applyConfigOptions(transformProgram);\n\n program.parse(process.argv);\n\n /**\n * CI / AUTOMATION\n *\n * Used to iterate over all projects in a monorepo, and help to parse secrets\n */\n program\n .command('ci')\n .description(\n 'Run Intlayer commands with auto-injected credentials from INTLAYER_PROJECT_CREDENTIALS. Detects current project or iterates over all projects.'\n )\n .argument(\n '<command...>',\n 'The intlayer command to execute (e.g., \"fill\", \"push\")'\n )\n .allowUnknownOption() // Allows passing flags like --verbose to the subcommand\n .action((args) => {\n runCI(args);\n });\n\n return program;\n};\n"],"mappings":"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"}
|
package/dist/cjs/config.cjs
CHANGED
|
@@ -4,7 +4,7 @@ let _intlayer_config = require("@intlayer/config");
|
|
|
4
4
|
//#region src/config.ts
|
|
5
5
|
const getConfig = (options) => {
|
|
6
6
|
const config = (0, _intlayer_config.getConfiguration)(options?.configOptions);
|
|
7
|
-
(0, _intlayer_config.getAppLogger)(config
|
|
7
|
+
(0, _intlayer_config.getAppLogger)(config)(JSON.stringify(config, null, 2));
|
|
8
8
|
};
|
|
9
9
|
|
|
10
10
|
//#endregion
|
package/dist/cjs/config.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.cjs","names":[],"sources":["../../src/config.ts"],"sourcesContent":["import {\n type GetConfigurationOptions,\n getAppLogger,\n getConfiguration,\n} from '@intlayer/config';\n\ntype ConfigOptions = {\n configOptions?: GetConfigurationOptions;\n};\n\nexport const getConfig = (options?: ConfigOptions) => {\n const config = getConfiguration(options?.configOptions);\n const appLogger = getAppLogger(config
|
|
1
|
+
{"version":3,"file":"config.cjs","names":[],"sources":["../../src/config.ts"],"sourcesContent":["import {\n type GetConfigurationOptions,\n getAppLogger,\n getConfiguration,\n} from '@intlayer/config';\n\ntype ConfigOptions = {\n configOptions?: GetConfigurationOptions;\n};\n\nexport const getConfig = (options?: ConfigOptions) => {\n const config = getConfiguration(options?.configOptions);\n const appLogger = getAppLogger(config);\n\n appLogger(JSON.stringify(config, null, 2));\n};\n"],"mappings":";;;;AAUA,MAAa,aAAa,YAA4B;CACpD,MAAM,gDAA0B,SAAS,cAAc;AAGvD,oCAF+B,OAAO,CAE5B,KAAK,UAAU,QAAQ,MAAM,EAAE,CAAC"}
|
|
@@ -19,7 +19,7 @@ const listContentDeclaration = (options) => {
|
|
|
19
19
|
console.log(JSON.stringify(rows));
|
|
20
20
|
return;
|
|
21
21
|
}
|
|
22
|
-
const appLogger = (0, _intlayer_config.getAppLogger)((0, _intlayer_config.getConfiguration)(options?.configOptions)
|
|
22
|
+
const appLogger = (0, _intlayer_config.getAppLogger)((0, _intlayer_config.getConfiguration)(options?.configOptions));
|
|
23
23
|
const lines = rows.map((row) => [
|
|
24
24
|
(0, _intlayer_config.colon)(` - ${(0, _intlayer_config.colorizeKey)(row.key)}`, {
|
|
25
25
|
colSize: rows.map((row$1) => row$1.key.length),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"listContentDeclaration.cjs","names":["row"],"sources":["../../src/listContentDeclaration.ts"],"sourcesContent":["import { relative } from 'node:path';\nimport { formatPath } from '@intlayer/chokidar';\nimport {\n colon,\n colorizeKey,\n colorizeNumber,\n type GetConfigurationOptions,\n getAppLogger,\n getConfiguration,\n} from '@intlayer/config';\nimport { getUnmergedDictionaries } from '@intlayer/unmerged-dictionaries-entry';\n\ntype ListContentDeclarationOptions = {\n configOptions?: GetConfigurationOptions;\n json?: boolean;\n absolute?: boolean;\n};\n\nexport const listContentDeclarationRows = (\n options?: ListContentDeclarationOptions\n) => {\n const config = getConfiguration(options?.configOptions);\n\n const unmergedDictionariesRecord = getUnmergedDictionaries(config);\n\n const rows = Object.values(unmergedDictionariesRecord)\n .flat()\n .map((dictionary) => ({\n key: dictionary.key ?? '',\n path: options?.absolute\n ? (dictionary.filePath ?? 'Remote')\n : relative(config.content.baseDir, dictionary.filePath ?? 'Remote'),\n }));\n return rows;\n};\n\nexport const listContentDeclaration = (\n options?: ListContentDeclarationOptions\n) => {\n const rows = listContentDeclarationRows(options);\n\n if (options?.json) {\n console.log(JSON.stringify(rows));\n return;\n }\n\n const config = getConfiguration(options?.configOptions);\n const appLogger = getAppLogger(config
|
|
1
|
+
{"version":3,"file":"listContentDeclaration.cjs","names":["row"],"sources":["../../src/listContentDeclaration.ts"],"sourcesContent":["import { relative } from 'node:path';\nimport { formatPath } from '@intlayer/chokidar';\nimport {\n colon,\n colorizeKey,\n colorizeNumber,\n type GetConfigurationOptions,\n getAppLogger,\n getConfiguration,\n} from '@intlayer/config';\nimport { getUnmergedDictionaries } from '@intlayer/unmerged-dictionaries-entry';\n\ntype ListContentDeclarationOptions = {\n configOptions?: GetConfigurationOptions;\n json?: boolean;\n absolute?: boolean;\n};\n\nexport const listContentDeclarationRows = (\n options?: ListContentDeclarationOptions\n) => {\n const config = getConfiguration(options?.configOptions);\n\n const unmergedDictionariesRecord = getUnmergedDictionaries(config);\n\n const rows = Object.values(unmergedDictionariesRecord)\n .flat()\n .map((dictionary) => ({\n key: dictionary.key ?? '',\n path: options?.absolute\n ? (dictionary.filePath ?? 'Remote')\n : relative(config.content.baseDir, dictionary.filePath ?? 'Remote'),\n }));\n return rows;\n};\n\nexport const listContentDeclaration = (\n options?: ListContentDeclarationOptions\n) => {\n const rows = listContentDeclarationRows(options);\n\n if (options?.json) {\n console.log(JSON.stringify(rows));\n return;\n }\n\n const config = getConfiguration(options?.configOptions);\n const appLogger = getAppLogger(config);\n\n const lines = rows.map((row) =>\n [\n colon(` - ${colorizeKey(row.key)}`, {\n colSize: rows.map((row) => row.key.length),\n maxSize: 60,\n }),\n ' - ',\n formatPath(row.path),\n ].join('')\n );\n\n appLogger(`Content declaration files:`);\n\n lines.forEach((line) => {\n appLogger(line, {\n level: 'info',\n });\n });\n\n appLogger(`Total content declaration files: ${colorizeNumber(rows.length)}`);\n};\n"],"mappings":";;;;;;;AAkBA,MAAa,8BACX,YACG;CACH,MAAM,gDAA0B,SAAS,cAAc;CAEvD,MAAM,gGAAqD,OAAO;AAUlE,QARa,OAAO,OAAO,2BAA2B,CACnD,MAAM,CACN,KAAK,gBAAgB;EACpB,KAAK,WAAW,OAAO;EACvB,MAAM,SAAS,WACV,WAAW,YAAY,mCACf,OAAO,QAAQ,SAAS,WAAW,YAAY,SAAS;EACtE,EAAE;;AAIP,MAAa,0BACX,YACG;CACH,MAAM,OAAO,2BAA2B,QAAQ;AAEhD,KAAI,SAAS,MAAM;AACjB,UAAQ,IAAI,KAAK,UAAU,KAAK,CAAC;AACjC;;CAIF,MAAM,sFAD0B,SAAS,cAAc,CACjB;CAEtC,MAAM,QAAQ,KAAK,KAAK,QACtB;8BACQ,wCAAkB,IAAI,IAAI,IAAI;GAClC,SAAS,KAAK,KAAK,UAAQA,MAAI,IAAI,OAAO;GAC1C,SAAS;GACV,CAAC;EACF;qCACW,IAAI,KAAK;EACrB,CAAC,KAAK,GAAG,CACX;AAED,WAAU,6BAA6B;AAEvC,OAAM,SAAS,SAAS;AACtB,YAAU,MAAM,EACd,OAAO,QACR,CAAC;GACF;AAEF,WAAU,yEAAmD,KAAK,OAAO,GAAG"}
|
package/dist/cjs/pull.cjs
CHANGED
|
@@ -5,6 +5,7 @@ let _intlayer_api = require("@intlayer/api");
|
|
|
5
5
|
let _intlayer_chokidar = require("@intlayer/chokidar");
|
|
6
6
|
let _intlayer_config = require("@intlayer/config");
|
|
7
7
|
let node_path = require("node:path");
|
|
8
|
+
let _intlayer_unmerged_dictionaries_entry = require("@intlayer/unmerged-dictionaries-entry");
|
|
8
9
|
let node_fs = require("node:fs");
|
|
9
10
|
|
|
10
11
|
//#region src/pull.ts
|
|
@@ -18,16 +19,22 @@ const pull = async (options) => {
|
|
|
18
19
|
const config = (0, _intlayer_config.getConfiguration)(options?.configOptions);
|
|
19
20
|
if (!await require_utils_checkAccess.checkCMSAuth(config)) return;
|
|
20
21
|
const intlayerAPI = (0, _intlayer_api.getIntlayerAPIProxy)(void 0, config);
|
|
22
|
+
const unmergedDictionariesRecord = (0, _intlayer_unmerged_dictionaries_entry.getUnmergedDictionaries)(config);
|
|
21
23
|
const getDictionariesUpdateTimestampResult = await intlayerAPI.dictionary.getDictionariesUpdateTimestamp();
|
|
22
24
|
if (!getDictionariesUpdateTimestampResult.data) throw new Error("No distant dictionaries found");
|
|
23
25
|
let distantDictionariesUpdateTimeStamp = getDictionariesUpdateTimestampResult.data;
|
|
24
26
|
if (options?.dictionaries) distantDictionariesUpdateTimeStamp = Object.fromEntries(Object.entries(distantDictionariesUpdateTimeStamp).filter(([key]) => options.dictionaries?.includes(key)));
|
|
27
|
+
distantDictionariesUpdateTimeStamp = Object.fromEntries(Object.entries(distantDictionariesUpdateTimeStamp).filter(([key]) => {
|
|
28
|
+
const location = unmergedDictionariesRecord[key]?.[0]?.location ?? config.dictionary?.location ?? "remote";
|
|
29
|
+
return location === "remote" || location === "local&remote";
|
|
30
|
+
}));
|
|
25
31
|
const remoteDictionariesPath = (0, node_path.join)(config.content.mainDir, "remote_dictionaries.cjs");
|
|
26
32
|
const requireFunction = config.build?.require ?? (0, _intlayer_config.getProjectRequire)();
|
|
27
33
|
const remoteDictionariesRecord = (0, node_fs.existsSync)(remoteDictionariesPath) ? requireFunction(remoteDictionariesPath) : {};
|
|
28
34
|
const entries = Object.entries(distantDictionariesUpdateTimeStamp);
|
|
29
|
-
const keysToFetch = entries.filter(([key,
|
|
30
|
-
if (!
|
|
35
|
+
const keysToFetch = entries.filter(([key, remoteUpdatedAtValue]) => {
|
|
36
|
+
if (!remoteUpdatedAtValue) return true;
|
|
37
|
+
const remoteUpdatedAt = typeof remoteUpdatedAtValue === "object" ? remoteUpdatedAtValue.updatedAt : remoteUpdatedAtValue;
|
|
31
38
|
const local = remoteDictionariesRecord[key];
|
|
32
39
|
if (!local) return true;
|
|
33
40
|
const localUpdatedAtRaw = local?.updatedAt;
|
|
@@ -35,7 +42,8 @@ const pull = async (options) => {
|
|
|
35
42
|
if (typeof localUpdatedAt !== "number") return true;
|
|
36
43
|
return remoteUpdatedAt > localUpdatedAt;
|
|
37
44
|
}).map(([key]) => key);
|
|
38
|
-
const cachedKeys = entries.filter(([key,
|
|
45
|
+
const cachedKeys = entries.filter(([key, remoteUpdatedAtValue]) => {
|
|
46
|
+
const remoteUpdatedAt = typeof remoteUpdatedAtValue === "object" ? remoteUpdatedAtValue.updatedAt : remoteUpdatedAtValue;
|
|
39
47
|
const localUpdatedAtRaw = remoteDictionariesRecord[key]?.updatedAt;
|
|
40
48
|
const localUpdatedAt = typeof localUpdatedAtRaw === "number" ? localUpdatedAtRaw : localUpdatedAtRaw ? new Date(localUpdatedAtRaw).getTime() : void 0;
|
|
41
49
|
return typeof localUpdatedAt === "number" && typeof remoteUpdatedAt === "number" && localUpdatedAt >= remoteUpdatedAt;
|
package/dist/cjs/pull.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pull.cjs","names":["checkCMSAuth","PullLogger","ANSIColors"],"sources":["../../src/pull.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { getIntlayerAPIProxy } from '@intlayer/api';\nimport {\n type DictionaryStatus,\n parallelize,\n writeContentDeclaration,\n} from '@intlayer/chokidar';\nimport {\n ANSIColors,\n type GetConfigurationOptions,\n getAppLogger,\n getConfiguration,\n getProjectRequire,\n} from '@intlayer/config';\nimport type { Dictionary } from '@intlayer/types';\nimport { PullLogger, type PullStatus } from './push/pullLog';\nimport { checkCMSAuth } from './utils/checkAccess';\n\ntype PullOptions = {\n dictionaries?: string[];\n newDictionariesPath?: string;\n configOptions?: GetConfigurationOptions;\n};\n\ntype DictionariesStatus = {\n dictionaryKey: string;\n status: DictionaryStatus | 'pending' | 'fetching' | 'error';\n error?: Error;\n errorMessage?: string;\n};\n\n/**\n * Fetch distant dictionaries and write them locally,\n * with progress indicators and concurrency control.\n */\nexport const pull = async (options?: PullOptions): Promise<void> => {\n const appLogger = getAppLogger(options?.configOptions?.override);\n\n try {\n const config = getConfiguration(options?.configOptions);\n\n const hasCMSAuth = await checkCMSAuth(config);\n\n if (!hasCMSAuth) return;\n\n const intlayerAPI = getIntlayerAPIProxy(undefined, config);\n\n // Get remote update timestamps map\n const getDictionariesUpdateTimestampResult =\n await intlayerAPI.dictionary.getDictionariesUpdateTimestamp();\n\n if (!getDictionariesUpdateTimestampResult.data) {\n throw new Error('No distant dictionaries found');\n }\n\n let distantDictionariesUpdateTimeStamp: Record<string, number> =\n getDictionariesUpdateTimestampResult.data;\n\n // Optional filtering by requested dictionaries\n if (options?.dictionaries) {\n distantDictionariesUpdateTimeStamp = Object.fromEntries(\n Object.entries(distantDictionariesUpdateTimeStamp).filter(([key]) =>\n options.dictionaries?.includes(key)\n )\n );\n }\n\n // Load local cached remote dictionaries (if any)\n const remoteDictionariesPath = join(\n config.content.mainDir,\n 'remote_dictionaries.cjs'\n );\n const requireFunction = config.build?.require ?? getProjectRequire();\n const remoteDictionariesRecord: Record<string, any> = existsSync(\n remoteDictionariesPath\n )\n ? (requireFunction(remoteDictionariesPath) as any)\n : {};\n\n // Determine which keys need fetching by comparing updatedAt with local cache\n const entries = Object.entries(distantDictionariesUpdateTimeStamp);\n const keysToFetch = entries\n .filter(([key, remoteUpdatedAt]) => {\n if (!remoteUpdatedAt) return true;\n const local = (remoteDictionariesRecord as any)[key];\n if (!local) return true;\n const localUpdatedAtRaw = (local as any)?.updatedAt as\n | number\n | string\n | undefined;\n const localUpdatedAt =\n typeof localUpdatedAtRaw === 'number'\n ? localUpdatedAtRaw\n : localUpdatedAtRaw\n ? new Date(localUpdatedAtRaw).getTime()\n : undefined;\n if (typeof localUpdatedAt !== 'number') return true;\n return remoteUpdatedAt > localUpdatedAt;\n })\n .map(([key]) => key);\n\n const cachedKeys = entries\n .filter(([key, remoteUpdatedAt]) => {\n const local = (remoteDictionariesRecord as any)[key];\n const localUpdatedAtRaw = (local as any)?.updatedAt as\n | number\n | string\n | undefined;\n const localUpdatedAt =\n typeof localUpdatedAtRaw === 'number'\n ? localUpdatedAtRaw\n : localUpdatedAtRaw\n ? new Date(localUpdatedAtRaw).getTime()\n : undefined;\n return (\n typeof localUpdatedAt === 'number' &&\n typeof remoteUpdatedAt === 'number' &&\n localUpdatedAt >= remoteUpdatedAt\n );\n })\n .map(([key]) => key);\n\n // Check if dictionaries list is empty\n if (entries.length === 0) {\n appLogger('No dictionaries to fetch', {\n level: 'error',\n });\n return;\n }\n\n appLogger('Fetching dictionaries:');\n\n // Prepare dictionaries statuses\n const dictionariesStatuses: DictionariesStatus[] = [\n ...cachedKeys.map((dictionaryKey) => ({\n dictionaryKey,\n status: 'imported' as DictionaryStatus,\n })),\n ...keysToFetch.map((dictionaryKey) => ({\n dictionaryKey,\n status: 'pending' as const,\n })),\n ];\n\n // Initialize aggregated logger\n const logger = new PullLogger();\n logger.update(\n dictionariesStatuses.map<PullStatus>((s) => ({\n dictionaryKey: s.dictionaryKey,\n status: s.status,\n }))\n );\n\n const successfullyFetchedDictionaries: Dictionary[] = [];\n\n const processDictionary = async (\n statusObj: DictionariesStatus\n ): Promise<void> => {\n const isCached =\n statusObj.status === 'imported' || statusObj.status === 'up-to-date';\n\n if (!isCached) {\n statusObj.status = 'fetching';\n logger.update([\n { dictionaryKey: statusObj.dictionaryKey, status: 'fetching' },\n ]);\n }\n\n try {\n let sourceDictionary: Dictionary | undefined;\n\n if (isCached) {\n sourceDictionary = remoteDictionariesRecord[\n statusObj.dictionaryKey\n ] as Dictionary | undefined;\n }\n\n if (!sourceDictionary) {\n // Fetch the dictionary\n const getDictionaryResult =\n await intlayerAPI.dictionary.getDictionary(statusObj.dictionaryKey);\n\n sourceDictionary = getDictionaryResult.data as Dictionary | undefined;\n }\n\n if (!sourceDictionary) {\n throw new Error(\n `Dictionary ${statusObj.dictionaryKey} not found on remote`\n );\n }\n\n // Now, write the dictionary to local file\n const { status } = await writeContentDeclaration(\n sourceDictionary,\n config,\n options\n );\n\n statusObj.status = status;\n logger.update([{ dictionaryKey: statusObj.dictionaryKey, status }]);\n\n successfullyFetchedDictionaries.push(sourceDictionary);\n } catch (error) {\n statusObj.status = 'error';\n statusObj.error = error as Error;\n statusObj.errorMessage = `Error fetching dictionary ${statusObj.dictionaryKey}: ${error}`;\n logger.update([\n { dictionaryKey: statusObj.dictionaryKey, status: 'error' },\n ]);\n }\n };\n\n // Process dictionaries in parallel with concurrency limit\n await parallelize(dictionariesStatuses, processDictionary, 5);\n\n // Stop the logger and render final state\n logger.finish();\n\n // Per-dictionary summary\n const iconFor = (status: DictionariesStatus['status']) => {\n switch (status) {\n case 'fetched':\n case 'imported':\n case 'updated':\n case 'up-to-date':\n case 'reimported in JSON':\n case 'new content file':\n return '✔';\n case 'error':\n return '✖';\n default:\n return '⏲';\n }\n };\n\n const colorFor = (status: DictionariesStatus['status']) => {\n switch (status) {\n case 'fetched':\n case 'imported':\n case 'updated':\n case 'up-to-date':\n return ANSIColors.GREEN;\n case 'reimported in JSON':\n case 'new content file':\n return ANSIColors.YELLOW;\n case 'error':\n return ANSIColors.RED;\n default:\n return ANSIColors.BLUE;\n }\n };\n\n for (const s of dictionariesStatuses) {\n const icon = iconFor(s.status);\n const color = colorFor(s.status);\n appLogger(\n ` - ${s.dictionaryKey} ${ANSIColors.GREY}[${color}${icon} ${s.status}${ANSIColors.GREY}]${ANSIColors.RESET}`\n );\n }\n\n // Output any error messages\n for (const statusObj of dictionariesStatuses) {\n if (statusObj.errorMessage) {\n appLogger(statusObj.errorMessage, {\n level: 'error',\n });\n }\n }\n } catch (error) {\n appLogger(error, {\n level: 'error',\n });\n }\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"pull.cjs","names":["checkCMSAuth","PullLogger","ANSIColors"],"sources":["../../src/pull.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { getIntlayerAPIProxy } from '@intlayer/api';\nimport {\n type DictionaryStatus,\n parallelize,\n writeContentDeclaration,\n} from '@intlayer/chokidar';\nimport {\n ANSIColors,\n type GetConfigurationOptions,\n getAppLogger,\n getConfiguration,\n getProjectRequire,\n} from '@intlayer/config';\nimport type { Dictionary } from '@intlayer/types';\nimport { getUnmergedDictionaries } from '@intlayer/unmerged-dictionaries-entry';\nimport { PullLogger, type PullStatus } from './push/pullLog';\nimport { checkCMSAuth } from './utils/checkAccess';\n\ntype PullOptions = {\n dictionaries?: string[];\n newDictionariesPath?: string;\n configOptions?: GetConfigurationOptions;\n};\n\ntype DictionariesStatus = {\n dictionaryKey: string;\n status: DictionaryStatus | 'pending' | 'fetching' | 'error';\n error?: Error;\n errorMessage?: string;\n};\n\n/**\n * Fetch distant dictionaries and write them locally,\n * with progress indicators and concurrency control.\n */\nexport const pull = async (options?: PullOptions): Promise<void> => {\n const appLogger = getAppLogger(options?.configOptions?.override);\n\n try {\n const config = getConfiguration(options?.configOptions);\n\n const hasCMSAuth = await checkCMSAuth(config);\n\n if (!hasCMSAuth) return;\n\n const intlayerAPI = getIntlayerAPIProxy(undefined, config);\n\n const unmergedDictionariesRecord = getUnmergedDictionaries(config);\n\n // Get remote update timestamps map\n const getDictionariesUpdateTimestampResult =\n await intlayerAPI.dictionary.getDictionariesUpdateTimestamp();\n\n if (!getDictionariesUpdateTimestampResult.data) {\n throw new Error('No distant dictionaries found');\n }\n\n let distantDictionariesUpdateTimeStamp: Record<string, any> =\n getDictionariesUpdateTimestampResult.data;\n\n // Optional filtering by requested dictionaries\n if (options?.dictionaries) {\n distantDictionariesUpdateTimeStamp = Object.fromEntries(\n Object.entries(distantDictionariesUpdateTimeStamp).filter(([key]) =>\n options.dictionaries?.includes(key)\n )\n );\n }\n\n // Filter by location\n distantDictionariesUpdateTimeStamp = Object.fromEntries(\n Object.entries(distantDictionariesUpdateTimeStamp).filter(([key]) => {\n const localDictionaries = unmergedDictionariesRecord[key];\n const location =\n localDictionaries?.[0]?.location ??\n config.dictionary?.location ??\n 'remote';\n\n return location === 'remote' || location === 'local&remote';\n })\n );\n\n // Load local cached remote dictionaries (if any)\n const remoteDictionariesPath = join(\n config.content.mainDir,\n 'remote_dictionaries.cjs'\n );\n const requireFunction = config.build?.require ?? getProjectRequire();\n const remoteDictionariesRecord: Record<string, any> = existsSync(\n remoteDictionariesPath\n )\n ? (requireFunction(remoteDictionariesPath) as any)\n : {};\n\n // Determine which keys need fetching by comparing updatedAt with local cache\n const entries = Object.entries(distantDictionariesUpdateTimeStamp);\n const keysToFetch = entries\n .filter(([key, remoteUpdatedAtValue]) => {\n if (!remoteUpdatedAtValue) return true;\n\n const remoteUpdatedAt =\n typeof remoteUpdatedAtValue === 'object'\n ? (remoteUpdatedAtValue as any).updatedAt\n : remoteUpdatedAtValue;\n\n const local = (remoteDictionariesRecord as any)[key];\n if (!local) return true;\n const localUpdatedAtRaw = (local as any)?.updatedAt as\n | number\n | string\n | undefined;\n const localUpdatedAt =\n typeof localUpdatedAtRaw === 'number'\n ? localUpdatedAtRaw\n : localUpdatedAtRaw\n ? new Date(localUpdatedAtRaw).getTime()\n : undefined;\n if (typeof localUpdatedAt !== 'number') return true;\n return remoteUpdatedAt > localUpdatedAt;\n })\n .map(([key]) => key);\n\n const cachedKeys = entries\n .filter(([key, remoteUpdatedAtValue]) => {\n const remoteUpdatedAt =\n typeof remoteUpdatedAtValue === 'object'\n ? (remoteUpdatedAtValue as any).updatedAt\n : remoteUpdatedAtValue;\n\n const local = (remoteDictionariesRecord as any)[key];\n const localUpdatedAtRaw = (local as any)?.updatedAt as\n | number\n | string\n | undefined;\n const localUpdatedAt =\n typeof localUpdatedAtRaw === 'number'\n ? localUpdatedAtRaw\n : localUpdatedAtRaw\n ? new Date(localUpdatedAtRaw).getTime()\n : undefined;\n return (\n typeof localUpdatedAt === 'number' &&\n typeof remoteUpdatedAt === 'number' &&\n localUpdatedAt >= remoteUpdatedAt\n );\n })\n .map(([key]) => key);\n\n // Check if dictionaries list is empty\n if (entries.length === 0) {\n appLogger('No dictionaries to fetch', {\n level: 'error',\n });\n return;\n }\n\n appLogger('Fetching dictionaries:');\n\n // Prepare dictionaries statuses\n const dictionariesStatuses: DictionariesStatus[] = [\n ...cachedKeys.map((dictionaryKey) => ({\n dictionaryKey,\n status: 'imported' as DictionaryStatus,\n })),\n ...keysToFetch.map((dictionaryKey) => ({\n dictionaryKey,\n status: 'pending' as const,\n })),\n ];\n\n // Initialize aggregated logger\n const logger = new PullLogger();\n logger.update(\n dictionariesStatuses.map<PullStatus>((s) => ({\n dictionaryKey: s.dictionaryKey,\n status: s.status,\n }))\n );\n\n const successfullyFetchedDictionaries: Dictionary[] = [];\n\n const processDictionary = async (\n statusObj: DictionariesStatus\n ): Promise<void> => {\n const isCached =\n statusObj.status === 'imported' || statusObj.status === 'up-to-date';\n\n if (!isCached) {\n statusObj.status = 'fetching';\n logger.update([\n { dictionaryKey: statusObj.dictionaryKey, status: 'fetching' },\n ]);\n }\n\n try {\n let sourceDictionary: Dictionary | undefined;\n\n if (isCached) {\n sourceDictionary = remoteDictionariesRecord[\n statusObj.dictionaryKey\n ] as Dictionary | undefined;\n }\n\n if (!sourceDictionary) {\n // Fetch the dictionary\n const getDictionaryResult =\n await intlayerAPI.dictionary.getDictionary(statusObj.dictionaryKey);\n\n sourceDictionary = getDictionaryResult.data as Dictionary | undefined;\n }\n\n if (!sourceDictionary) {\n throw new Error(\n `Dictionary ${statusObj.dictionaryKey} not found on remote`\n );\n }\n\n // Now, write the dictionary to local file\n const { status } = await writeContentDeclaration(\n sourceDictionary,\n config,\n options\n );\n\n statusObj.status = status;\n logger.update([{ dictionaryKey: statusObj.dictionaryKey, status }]);\n\n successfullyFetchedDictionaries.push(sourceDictionary);\n } catch (error) {\n statusObj.status = 'error';\n statusObj.error = error as Error;\n statusObj.errorMessage = `Error fetching dictionary ${statusObj.dictionaryKey}: ${error}`;\n logger.update([\n { dictionaryKey: statusObj.dictionaryKey, status: 'error' },\n ]);\n }\n };\n\n // Process dictionaries in parallel with concurrency limit\n await parallelize(dictionariesStatuses, processDictionary, 5);\n\n // Stop the logger and render final state\n logger.finish();\n\n // Per-dictionary summary\n const iconFor = (status: DictionariesStatus['status']) => {\n switch (status) {\n case 'fetched':\n case 'imported':\n case 'updated':\n case 'up-to-date':\n case 'reimported in JSON':\n case 'new content file':\n return '✔';\n case 'error':\n return '✖';\n default:\n return '⏲';\n }\n };\n\n const colorFor = (status: DictionariesStatus['status']) => {\n switch (status) {\n case 'fetched':\n case 'imported':\n case 'updated':\n case 'up-to-date':\n return ANSIColors.GREEN;\n case 'reimported in JSON':\n case 'new content file':\n return ANSIColors.YELLOW;\n case 'error':\n return ANSIColors.RED;\n default:\n return ANSIColors.BLUE;\n }\n };\n\n for (const s of dictionariesStatuses) {\n const icon = iconFor(s.status);\n const color = colorFor(s.status);\n appLogger(\n ` - ${s.dictionaryKey} ${ANSIColors.GREY}[${color}${icon} ${s.status}${ANSIColors.GREY}]${ANSIColors.RESET}`\n );\n }\n\n // Output any error messages\n for (const statusObj of dictionariesStatuses) {\n if (statusObj.errorMessage) {\n appLogger(statusObj.errorMessage, {\n level: 'error',\n });\n }\n }\n } catch (error) {\n appLogger(error, {\n level: 'error',\n });\n }\n};\n"],"mappings":"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"}
|
package/dist/cjs/push/push.cjs
CHANGED
|
@@ -38,14 +38,22 @@ const getIconAndColor = (status) => {
|
|
|
38
38
|
*/
|
|
39
39
|
const push = async (options) => {
|
|
40
40
|
const config = (0, _intlayer_config.getConfiguration)(options?.configOptions);
|
|
41
|
-
const appLogger = (0, _intlayer_config.getAppLogger)(config
|
|
41
|
+
const appLogger = (0, _intlayer_config.getAppLogger)(config);
|
|
42
42
|
if (options?.build === true) await (0, _intlayer_chokidar.prepareIntlayer)(config, { forceRun: true });
|
|
43
43
|
else if (typeof options?.build === "undefined") await (0, _intlayer_chokidar.prepareIntlayer)(config);
|
|
44
44
|
try {
|
|
45
45
|
if (!await require_utils_checkAccess.checkCMSAuth(config)) return;
|
|
46
46
|
const intlayerAPI = (0, _intlayer_api.getIntlayerAPIProxy)(void 0, config);
|
|
47
47
|
const unmergedDictionariesRecord = (0, _intlayer_unmerged_dictionaries_entry.getUnmergedDictionaries)(config);
|
|
48
|
-
let dictionaries = Object.values(unmergedDictionariesRecord).flat()
|
|
48
|
+
let dictionaries = Object.values(unmergedDictionariesRecord).flat().filter((dictionary) => {
|
|
49
|
+
const location = dictionary.location ?? config.dictionary?.location ?? "local";
|
|
50
|
+
return location === "remote" || location === "local&remote";
|
|
51
|
+
});
|
|
52
|
+
if (dictionaries.length === 0) {
|
|
53
|
+
appLogger(`No dictionaries found to push. Only dictionaries with location ${(0, _intlayer_config.colorize)("remote", _intlayer_config.ANSIColors.BLUE, _intlayer_config.ANSIColors.RESET)} or ${(0, _intlayer_config.colorize)("local&remote", _intlayer_config.ANSIColors.BLUE, _intlayer_config.ANSIColors.RESET)} are pushed.`, { level: "warn" });
|
|
54
|
+
appLogger(`You can set the location in your dictionary file (e.g. ${(0, _intlayer_config.colorize)("{ key: 'my-key', location: 'local&remote', ... }", _intlayer_config.ANSIColors.BLUE, _intlayer_config.ANSIColors.RESET)} or globally in your intlayer.config.ts file (e.g. ${(0, _intlayer_config.colorize)("{ dictionary: { location: 'local&remote' } }", _intlayer_config.ANSIColors.BLUE, _intlayer_config.ANSIColors.RESET)}).`, { level: "info" });
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
49
57
|
const existingDictionariesKeys = Object.keys(unmergedDictionariesRecord);
|
|
50
58
|
if (options?.dictionaries) {
|
|
51
59
|
const noneExistingDictionariesOption = options.dictionaries.filter((dictionaryId) => !existingDictionariesKeys.includes(dictionaryId));
|
|
@@ -119,7 +127,7 @@ const push = async (options) => {
|
|
|
119
127
|
logger.finish();
|
|
120
128
|
for (const dictionaryStatus of dictionariesStatuses) {
|
|
121
129
|
const { icon, color } = getIconAndColor(dictionaryStatus.status);
|
|
122
|
-
appLogger(` - ${dictionaryStatus.dictionary.key} ${_intlayer_config.ANSIColors.GREY}[${color}${icon} ${dictionaryStatus.status}${_intlayer_config.ANSIColors.GREY}]${_intlayer_config.ANSIColors.RESET}`);
|
|
130
|
+
appLogger(` - ${(0, _intlayer_config.colorizeKey)(dictionaryStatus.dictionary.key)} ${_intlayer_config.ANSIColors.GREY}[${color}${icon} ${dictionaryStatus.status}${_intlayer_config.ANSIColors.GREY}]${_intlayer_config.ANSIColors.RESET}`);
|
|
123
131
|
}
|
|
124
132
|
for (const statusObj of dictionariesStatuses) if (statusObj.errorMessage) appLogger(statusObj.errorMessage, { level: "error" });
|
|
125
133
|
const deleteOption = options?.deleteLocaleDictionary;
|
|
@@ -127,8 +135,10 @@ const push = async (options) => {
|
|
|
127
135
|
if (deleteOption && keepOption) throw new Error("Cannot specify both --deleteLocaleDictionary and --keepLocaleDictionary options.");
|
|
128
136
|
if (deleteOption) await deleteLocalDictionaries(successfullyPushedDictionaries, options);
|
|
129
137
|
else if (keepOption) {} else {
|
|
130
|
-
const
|
|
131
|
-
|
|
138
|
+
const remoteDictionaries = successfullyPushedDictionaries.filter((dictionary) => dictionary.location === "remote");
|
|
139
|
+
const remoteDictionariesKeys = remoteDictionaries.map((dictionary) => dictionary.key);
|
|
140
|
+
const answer = await askUser(`Do you want to delete the local dictionaries that were successfully pushed? ${(0, _intlayer_config.colorize)("(Dictionaries:", _intlayer_config.ANSIColors.GREY, _intlayer_config.ANSIColors.RESET)} ${(0, _intlayer_config.colorizeKey)(remoteDictionariesKeys)}${(0, _intlayer_config.colorize)(")", _intlayer_config.ANSIColors.GREY, _intlayer_config.ANSIColors.RESET)} ${(0, _intlayer_config.colorize)("(yes/no)", _intlayer_config.ANSIColors.GREY_DARK, _intlayer_config.ANSIColors.RESET)}: `);
|
|
141
|
+
if (answer.toLowerCase() === "yes" || answer.toLowerCase() === "y") await deleteLocalDictionaries(remoteDictionaries, options);
|
|
132
142
|
}
|
|
133
143
|
} catch (error) {
|
|
134
144
|
appLogger(error, { level: "error" });
|
|
@@ -147,12 +157,12 @@ const askUser = (question) => {
|
|
|
147
157
|
});
|
|
148
158
|
};
|
|
149
159
|
const deleteLocalDictionaries = async (dictionariesToDelete, options) => {
|
|
150
|
-
const appLogger = (0, _intlayer_config.getAppLogger)((0, _intlayer_config.getConfiguration)(options?.configOptions)
|
|
160
|
+
const appLogger = (0, _intlayer_config.getAppLogger)((0, _intlayer_config.getConfiguration)(options?.configOptions));
|
|
151
161
|
const filePathsSet = /* @__PURE__ */ new Set();
|
|
152
162
|
for (const dictionary of dictionariesToDelete) {
|
|
153
163
|
const { filePath } = dictionary;
|
|
154
164
|
if (!filePath) {
|
|
155
|
-
appLogger(`Dictionary ${dictionary.key} does not have a file path`, { level: "error" });
|
|
165
|
+
appLogger(`Dictionary ${(0, _intlayer_config.colorizeKey)(dictionary.key)} does not have a file path`, { level: "error" });
|
|
156
166
|
continue;
|
|
157
167
|
}
|
|
158
168
|
filePathsSet.add(filePath);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"push.cjs","names":["ANSIColors","checkCMSAuth","PushLogger","readline","fsPromises"],"sources":["../../../src/push/push.ts"],"sourcesContent":["import * as fsPromises from 'node:fs/promises';\nimport { join } from 'node:path';\nimport * as readline from 'node:readline';\nimport { getIntlayerAPIProxy } from '@intlayer/api';\nimport {\n formatPath,\n type ListGitFilesOptions,\n listGitFiles,\n parallelize,\n prepareIntlayer,\n writeContentDeclaration,\n} from '@intlayer/chokidar';\nimport {\n ANSIColors,\n type GetConfigurationOptions,\n getAppLogger,\n getConfiguration,\n} from '@intlayer/config';\nimport type { Dictionary } from '@intlayer/types';\nimport { getUnmergedDictionaries } from '@intlayer/unmerged-dictionaries-entry';\nimport { PushLogger, type PushStatus } from '../pushLog';\nimport { checkCMSAuth } from '../utils/checkAccess';\n\ntype PushOptions = {\n deleteLocaleDictionary?: boolean;\n keepLocaleDictionary?: boolean;\n dictionaries?: string[];\n gitOptions?: ListGitFilesOptions;\n configOptions?: GetConfigurationOptions;\n build?: boolean;\n};\n\ntype DictionariesStatus = {\n dictionary: Dictionary;\n status: 'pending' | 'pushing' | 'modified' | 'pushed' | 'unknown' | 'error';\n error?: Error;\n errorMessage?: string;\n};\n\n// Print per-dictionary summary similar to loadDictionaries\nconst statusIconsAndColors = {\n pushed: { icon: '✔', color: ANSIColors.GREEN },\n modified: { icon: '✔', color: ANSIColors.GREEN },\n error: { icon: '✖', color: ANSIColors.RED },\n default: { icon: '⏲', color: ANSIColors.BLUE },\n};\n\nconst getIconAndColor = (status: DictionariesStatus['status']) => {\n return (\n statusIconsAndColors[status as keyof typeof statusIconsAndColors] ??\n statusIconsAndColors.default\n );\n};\n\n/**\n * Get all local dictionaries and push them simultaneously.\n */\nexport const push = async (options?: PushOptions): Promise<void> => {\n const config = getConfiguration(options?.configOptions);\n const appLogger = getAppLogger(config, {\n config: {\n prefix: '',\n },\n });\n\n if (options?.build === true) {\n await prepareIntlayer(config, { forceRun: true });\n } else if (typeof options?.build === 'undefined') {\n await prepareIntlayer(config);\n }\n\n try {\n const hasCMSAuth = await checkCMSAuth(config);\n\n if (!hasCMSAuth) return;\n\n const intlayerAPI = getIntlayerAPIProxy(undefined, config);\n\n const unmergedDictionariesRecord = getUnmergedDictionaries(config);\n let dictionaries: Dictionary[] = Object.values(\n unmergedDictionariesRecord\n ).flat();\n const existingDictionariesKeys: string[] = Object.keys(\n unmergedDictionariesRecord\n );\n\n if (options?.dictionaries) {\n // Check if the provided dictionaries exist\n const noneExistingDictionariesOption = options.dictionaries.filter(\n (dictionaryId) => !existingDictionariesKeys.includes(dictionaryId)\n );\n\n if (noneExistingDictionariesOption.length > 0) {\n appLogger(\n `The following dictionaries do not exist: ${noneExistingDictionariesOption.join(\n ', '\n )} and have been ignored.`,\n {\n level: 'error',\n }\n );\n }\n\n // Filter the dictionaries from the provided list of IDs\n dictionaries = dictionaries.filter((dictionary) =>\n options.dictionaries?.includes(dictionary.key)\n );\n }\n\n if (options?.gitOptions) {\n const gitFiles = await listGitFiles(options.gitOptions);\n\n dictionaries = dictionaries.filter((dictionary) =>\n gitFiles.includes(\n join(config.content.baseDir, dictionary.filePath ?? '')\n )\n );\n }\n\n // Check if the dictionaries list is empty\n if (dictionaries.length === 0) {\n appLogger('No local dictionaries found', {\n level: 'error',\n });\n return;\n }\n\n appLogger('Pushing dictionaries:');\n\n // Prepare dictionaries statuses\n const dictionariesStatuses: DictionariesStatus[] = dictionaries.map(\n (dictionary) => ({\n dictionary,\n status: 'pending',\n })\n );\n\n // Initialize aggregated logger similar to loadDictionaries\n const logger = new PushLogger();\n logger.update(\n dictionariesStatuses.map<PushStatus>((s) => ({\n dictionaryKey: s.dictionary.key,\n status: 'pending',\n }))\n );\n\n const successfullyPushedDictionaries: Dictionary[] = [];\n\n const processDictionary = async (\n statusObj: DictionariesStatus\n ): Promise<void> => {\n statusObj.status = 'pushing';\n logger.update([\n { dictionaryKey: statusObj.dictionary.key, status: 'pushing' },\n ]);\n\n try {\n const pushResult = await intlayerAPI.dictionary.pushDictionaries([\n statusObj.dictionary,\n ]);\n\n const updatedDictionaries = pushResult.data?.updatedDictionaries ?? [];\n const newDictionaries = pushResult.data?.newDictionaries ?? [];\n\n const allDictionaries = [...updatedDictionaries, ...newDictionaries];\n\n for (const remoteDictionaryData of allDictionaries) {\n const localDictionary = unmergedDictionariesRecord[\n remoteDictionaryData.key\n ]?.find(\n (dictionary) => dictionary.localId === remoteDictionaryData.localId\n );\n\n if (!localDictionary) continue;\n\n await writeContentDeclaration(\n { ...localDictionary, id: remoteDictionaryData.id },\n config\n );\n }\n\n if (\n updatedDictionaries.some(\n (dictionary) => dictionary.key === statusObj.dictionary.key\n )\n ) {\n statusObj.status = 'modified';\n successfullyPushedDictionaries.push(statusObj.dictionary);\n logger.update([\n { dictionaryKey: statusObj.dictionary.key, status: 'modified' },\n ]);\n } else if (\n newDictionaries.some(\n (dictionary) => dictionary.key === statusObj.dictionary.key\n )\n ) {\n statusObj.status = 'pushed';\n successfullyPushedDictionaries.push(statusObj.dictionary);\n logger.update([\n { dictionaryKey: statusObj.dictionary.key, status: 'pushed' },\n ]);\n } else {\n statusObj.status = 'unknown';\n }\n } catch (error) {\n statusObj.status = 'error';\n statusObj.error = error as Error;\n statusObj.errorMessage = `Error pushing dictionary ${statusObj.dictionary.key}: ${error}`;\n logger.update([\n { dictionaryKey: statusObj.dictionary.key, status: 'error' },\n ]);\n }\n };\n\n // Process dictionaries in parallel with a concurrency limit (reuse parallelize)\n await parallelize(dictionariesStatuses, processDictionary, 5);\n\n // Stop the logger and render final state\n logger.finish();\n\n for (const dictionaryStatus of dictionariesStatuses) {\n const { icon, color } = getIconAndColor(dictionaryStatus.status);\n appLogger(\n ` - ${dictionaryStatus.dictionary.key} ${ANSIColors.GREY}[${color}${icon} ${dictionaryStatus.status}${ANSIColors.GREY}]${ANSIColors.RESET}`\n );\n }\n\n // Output any error messages\n for (const statusObj of dictionariesStatuses) {\n if (statusObj.errorMessage) {\n appLogger(statusObj.errorMessage, {\n level: 'error',\n });\n }\n }\n\n // Handle delete or keep options\n const deleteOption = options?.deleteLocaleDictionary;\n const keepOption = options?.keepLocaleDictionary;\n\n if (deleteOption && keepOption) {\n throw new Error(\n 'Cannot specify both --deleteLocaleDictionary and --keepLocaleDictionary options.'\n );\n }\n\n if (deleteOption) {\n // Delete only the successfully pushed dictionaries\n await deleteLocalDictionaries(successfullyPushedDictionaries, options);\n } else if (keepOption) {\n // Do nothing, keep the local dictionaries\n } else {\n // Ask the user\n const answer = await askUser(\n 'Do you want to delete the local dictionaries that were successfully pushed? (yes/no): '\n );\n if (answer.toLowerCase() === 'yes' || answer.toLowerCase() === 'y') {\n await deleteLocalDictionaries(successfullyPushedDictionaries, options);\n }\n }\n } catch (error) {\n appLogger(error, {\n level: 'error',\n });\n }\n};\n\nconst askUser = (question: string): Promise<string> => {\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n return new Promise((resolve) => {\n rl.question(question, (answer: string) => {\n rl.close();\n resolve(answer);\n });\n });\n};\n\nconst deleteLocalDictionaries = async (\n dictionariesToDelete: Dictionary[],\n options?: PushOptions\n): Promise<void> => {\n const config = getConfiguration(options?.configOptions);\n const appLogger = getAppLogger(config, {\n config: {\n prefix: '',\n },\n });\n\n // Use a Set to collect all unique file paths\n const filePathsSet: Set<string> = new Set();\n\n for (const dictionary of dictionariesToDelete) {\n const { filePath } = dictionary;\n\n if (!filePath) {\n appLogger(`Dictionary ${dictionary.key} does not have a file path`, {\n level: 'error',\n });\n continue;\n }\n\n filePathsSet.add(filePath);\n }\n\n for (const filePath of filePathsSet) {\n try {\n const stats = await fsPromises.lstat(filePath);\n\n if (stats.isFile()) {\n await fsPromises.unlink(filePath);\n appLogger(`Deleted file ${formatPath(filePath)}`, {});\n } else if (stats.isDirectory()) {\n appLogger(`Path is a directory ${formatPath(filePath)}, skipping.`, {});\n } else {\n appLogger(\n `Unknown file type for ${formatPath(filePath)}, skipping.`,\n {}\n );\n }\n } catch (err) {\n appLogger(`Error deleting ${formatPath(filePath)}: ${err}`, {\n level: 'error',\n });\n }\n }\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"push.cjs","names":["ANSIColors","checkCMSAuth","PushLogger","readline","fsPromises"],"sources":["../../../src/push/push.ts"],"sourcesContent":["import * as fsPromises from 'node:fs/promises';\nimport { join } from 'node:path';\nimport * as readline from 'node:readline';\nimport { getIntlayerAPIProxy } from '@intlayer/api';\nimport {\n formatPath,\n type ListGitFilesOptions,\n listGitFiles,\n parallelize,\n prepareIntlayer,\n writeContentDeclaration,\n} from '@intlayer/chokidar';\nimport {\n ANSIColors,\n colorize,\n colorizeKey,\n type GetConfigurationOptions,\n getAppLogger,\n getConfiguration,\n} from '@intlayer/config';\nimport type { Dictionary } from '@intlayer/types';\nimport { getUnmergedDictionaries } from '@intlayer/unmerged-dictionaries-entry';\nimport { PushLogger, type PushStatus } from '../pushLog';\nimport { checkCMSAuth } from '../utils/checkAccess';\n\ntype PushOptions = {\n deleteLocaleDictionary?: boolean;\n keepLocaleDictionary?: boolean;\n dictionaries?: string[];\n gitOptions?: ListGitFilesOptions;\n configOptions?: GetConfigurationOptions;\n build?: boolean;\n};\n\ntype DictionariesStatus = {\n dictionary: Dictionary;\n status: 'pending' | 'pushing' | 'modified' | 'pushed' | 'unknown' | 'error';\n error?: Error;\n errorMessage?: string;\n};\n\n// Print per-dictionary summary similar to loadDictionaries\nconst statusIconsAndColors = {\n pushed: { icon: '✔', color: ANSIColors.GREEN },\n modified: { icon: '✔', color: ANSIColors.GREEN },\n error: { icon: '✖', color: ANSIColors.RED },\n default: { icon: '⏲', color: ANSIColors.BLUE },\n};\n\nconst getIconAndColor = (status: DictionariesStatus['status']) => {\n return (\n statusIconsAndColors[status as keyof typeof statusIconsAndColors] ??\n statusIconsAndColors.default\n );\n};\n\n/**\n * Get all local dictionaries and push them simultaneously.\n */\nexport const push = async (options?: PushOptions): Promise<void> => {\n const config = getConfiguration(options?.configOptions);\n const appLogger = getAppLogger(config);\n\n if (options?.build === true) {\n await prepareIntlayer(config, { forceRun: true });\n } else if (typeof options?.build === 'undefined') {\n await prepareIntlayer(config);\n }\n\n try {\n const hasCMSAuth = await checkCMSAuth(config);\n\n if (!hasCMSAuth) return;\n\n const intlayerAPI = getIntlayerAPIProxy(undefined, config);\n\n const unmergedDictionariesRecord = getUnmergedDictionaries(config);\n let dictionaries: Dictionary[] = Object.values(unmergedDictionariesRecord)\n .flat()\n .filter((dictionary) => {\n const location =\n dictionary.location ?? config.dictionary?.location ?? 'local';\n\n return location === 'remote' || location === 'local&remote';\n });\n\n // Check if the dictionaries list is empty after filtering by location\n if (dictionaries.length === 0) {\n appLogger(\n `No dictionaries found to push. Only dictionaries with location ${colorize('remote', ANSIColors.BLUE, ANSIColors.RESET)} or ${colorize('local&remote', ANSIColors.BLUE, ANSIColors.RESET)} are pushed.`,\n { level: 'warn' }\n );\n appLogger(\n `You can set the location in your dictionary file (e.g. ${colorize(\"{ key: 'my-key', location: 'local&remote', ... }\", ANSIColors.BLUE, ANSIColors.RESET)} or globally in your intlayer.config.ts file (e.g. ${colorize(\"{ dictionary: { location: 'local&remote' } }\", ANSIColors.BLUE, ANSIColors.RESET)}).`,\n { level: 'info' }\n );\n return;\n }\n\n const existingDictionariesKeys: string[] = Object.keys(\n unmergedDictionariesRecord\n );\n\n if (options?.dictionaries) {\n // Check if the provided dictionaries exist\n const noneExistingDictionariesOption = options.dictionaries.filter(\n (dictionaryId) => !existingDictionariesKeys.includes(dictionaryId)\n );\n\n if (noneExistingDictionariesOption.length > 0) {\n appLogger(\n `The following dictionaries do not exist: ${noneExistingDictionariesOption.join(\n ', '\n )} and have been ignored.`,\n {\n level: 'error',\n }\n );\n }\n\n // Filter the dictionaries from the provided list of IDs\n dictionaries = dictionaries.filter((dictionary) =>\n options.dictionaries?.includes(dictionary.key)\n );\n }\n\n if (options?.gitOptions) {\n const gitFiles = await listGitFiles(options.gitOptions);\n\n dictionaries = dictionaries.filter((dictionary) =>\n gitFiles.includes(\n join(config.content.baseDir, dictionary.filePath ?? '')\n )\n );\n }\n\n // Check if the dictionaries list is empty\n if (dictionaries.length === 0) {\n appLogger('No local dictionaries found', {\n level: 'error',\n });\n return;\n }\n\n appLogger('Pushing dictionaries:');\n\n // Prepare dictionaries statuses\n const dictionariesStatuses: DictionariesStatus[] = dictionaries.map(\n (dictionary) => ({\n dictionary,\n status: 'pending',\n })\n );\n\n // Initialize aggregated logger similar to loadDictionaries\n const logger = new PushLogger();\n logger.update(\n dictionariesStatuses.map<PushStatus>((s) => ({\n dictionaryKey: s.dictionary.key,\n status: 'pending',\n }))\n );\n\n const successfullyPushedDictionaries: Dictionary[] = [];\n\n const processDictionary = async (\n statusObj: DictionariesStatus\n ): Promise<void> => {\n statusObj.status = 'pushing';\n logger.update([\n { dictionaryKey: statusObj.dictionary.key, status: 'pushing' },\n ]);\n\n try {\n const pushResult = await intlayerAPI.dictionary.pushDictionaries([\n statusObj.dictionary,\n ]);\n\n const updatedDictionaries = pushResult.data?.updatedDictionaries ?? [];\n const newDictionaries = pushResult.data?.newDictionaries ?? [];\n\n const allDictionaries = [...updatedDictionaries, ...newDictionaries];\n\n for (const remoteDictionaryData of allDictionaries) {\n const localDictionary = unmergedDictionariesRecord[\n remoteDictionaryData.key\n ]?.find(\n (dictionary) => dictionary.localId === remoteDictionaryData.localId\n );\n\n if (!localDictionary) continue;\n\n await writeContentDeclaration(\n { ...localDictionary, id: remoteDictionaryData.id },\n config\n );\n }\n\n if (\n updatedDictionaries.some(\n (dictionary) => dictionary.key === statusObj.dictionary.key\n )\n ) {\n statusObj.status = 'modified';\n successfullyPushedDictionaries.push(statusObj.dictionary);\n logger.update([\n { dictionaryKey: statusObj.dictionary.key, status: 'modified' },\n ]);\n } else if (\n newDictionaries.some(\n (dictionary) => dictionary.key === statusObj.dictionary.key\n )\n ) {\n statusObj.status = 'pushed';\n successfullyPushedDictionaries.push(statusObj.dictionary);\n logger.update([\n { dictionaryKey: statusObj.dictionary.key, status: 'pushed' },\n ]);\n } else {\n statusObj.status = 'unknown';\n }\n } catch (error) {\n statusObj.status = 'error';\n statusObj.error = error as Error;\n statusObj.errorMessage = `Error pushing dictionary ${statusObj.dictionary.key}: ${error}`;\n logger.update([\n { dictionaryKey: statusObj.dictionary.key, status: 'error' },\n ]);\n }\n };\n\n // Process dictionaries in parallel with a concurrency limit (reuse parallelize)\n await parallelize(dictionariesStatuses, processDictionary, 5);\n\n // Stop the logger and render final state\n logger.finish();\n\n for (const dictionaryStatus of dictionariesStatuses) {\n const { icon, color } = getIconAndColor(dictionaryStatus.status);\n appLogger(\n ` - ${colorizeKey(dictionaryStatus.dictionary.key)} ${ANSIColors.GREY}[${color}${icon} ${dictionaryStatus.status}${ANSIColors.GREY}]${ANSIColors.RESET}`\n );\n }\n\n // Output any error messages\n for (const statusObj of dictionariesStatuses) {\n if (statusObj.errorMessage) {\n appLogger(statusObj.errorMessage, {\n level: 'error',\n });\n }\n }\n\n // Handle delete or keep options\n const deleteOption = options?.deleteLocaleDictionary;\n const keepOption = options?.keepLocaleDictionary;\n\n if (deleteOption && keepOption) {\n throw new Error(\n 'Cannot specify both --deleteLocaleDictionary and --keepLocaleDictionary options.'\n );\n }\n\n if (deleteOption) {\n // Delete only the successfully pushed dictionaries\n await deleteLocalDictionaries(successfullyPushedDictionaries, options);\n } else if (keepOption) {\n // Do nothing, keep the local dictionaries\n } else {\n // Ask the user\n const remoteDictionaries = successfullyPushedDictionaries.filter(\n (dictionary) => dictionary.location === 'remote'\n );\n const remoteDictionariesKeys = remoteDictionaries.map(\n (dictionary) => dictionary.key\n );\n const answer = await askUser(\n `Do you want to delete the local dictionaries that were successfully pushed? ${colorize('(Dictionaries:', ANSIColors.GREY, ANSIColors.RESET)} ${colorizeKey(remoteDictionariesKeys)}${colorize(')', ANSIColors.GREY, ANSIColors.RESET)} ${colorize('(yes/no)', ANSIColors.GREY_DARK, ANSIColors.RESET)}: `\n );\n if (answer.toLowerCase() === 'yes' || answer.toLowerCase() === 'y') {\n await deleteLocalDictionaries(remoteDictionaries, options);\n }\n }\n } catch (error) {\n appLogger(error, {\n level: 'error',\n });\n }\n};\n\nconst askUser = (question: string): Promise<string> => {\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n return new Promise((resolve) => {\n rl.question(question, (answer: string) => {\n rl.close();\n resolve(answer);\n });\n });\n};\n\nconst deleteLocalDictionaries = async (\n dictionariesToDelete: Dictionary[],\n options?: PushOptions\n): Promise<void> => {\n const config = getConfiguration(options?.configOptions);\n const appLogger = getAppLogger(config);\n\n // Use a Set to collect all unique file paths\n const filePathsSet: Set<string> = new Set();\n\n for (const dictionary of dictionariesToDelete) {\n const { filePath } = dictionary;\n\n if (!filePath) {\n appLogger(\n `Dictionary ${colorizeKey(dictionary.key)} does not have a file path`,\n {\n level: 'error',\n }\n );\n continue;\n }\n\n filePathsSet.add(filePath);\n }\n\n for (const filePath of filePathsSet) {\n try {\n const stats = await fsPromises.lstat(filePath);\n\n if (stats.isFile()) {\n await fsPromises.unlink(filePath);\n appLogger(`Deleted file ${formatPath(filePath)}`, {});\n } else if (stats.isDirectory()) {\n appLogger(`Path is a directory ${formatPath(filePath)}, skipping.`, {});\n } else {\n appLogger(\n `Unknown file type for ${formatPath(filePath)}, skipping.`,\n {}\n );\n }\n } catch (err) {\n appLogger(`Error deleting ${formatPath(filePath)}: ${err}`, {\n level: 'error',\n });\n }\n }\n};\n"],"mappings":";;;;;;;;;;;;;;AA0CA,MAAM,uBAAuB;CAC3B,QAAQ;EAAE,MAAM;EAAK,OAAOA,4BAAW;EAAO;CAC9C,UAAU;EAAE,MAAM;EAAK,OAAOA,4BAAW;EAAO;CAChD,OAAO;EAAE,MAAM;EAAK,OAAOA,4BAAW;EAAK;CAC3C,SAAS;EAAE,MAAM;EAAK,OAAOA,4BAAW;EAAM;CAC/C;AAED,MAAM,mBAAmB,WAAyC;AAChE,QACE,qBAAqB,WACrB,qBAAqB;;;;;AAOzB,MAAa,OAAO,OAAO,YAAyC;CAClE,MAAM,gDAA0B,SAAS,cAAc;CACvD,MAAM,+CAAyB,OAAO;AAEtC,KAAI,SAAS,UAAU,KACrB,+CAAsB,QAAQ,EAAE,UAAU,MAAM,CAAC;UACxC,OAAO,SAAS,UAAU,YACnC,+CAAsB,OAAO;AAG/B,KAAI;AAGF,MAAI,CAFe,MAAMC,uCAAa,OAAO,CAE5B;EAEjB,MAAM,qDAAkC,QAAW,OAAO;EAE1D,MAAM,gGAAqD,OAAO;EAClE,IAAI,eAA6B,OAAO,OAAO,2BAA2B,CACvE,MAAM,CACN,QAAQ,eAAe;GACtB,MAAM,WACJ,WAAW,YAAY,OAAO,YAAY,YAAY;AAExD,UAAO,aAAa,YAAY,aAAa;IAC7C;AAGJ,MAAI,aAAa,WAAW,GAAG;AAC7B,aACE,iGAA2E,UAAUD,4BAAW,MAAMA,4BAAW,MAAM,CAAC,qCAAe,gBAAgBA,4BAAW,MAAMA,4BAAW,MAAM,CAAC,eAC1L,EAAE,OAAO,QAAQ,CAClB;AACD,aACE,yFAAmE,oDAAoDA,4BAAW,MAAMA,4BAAW,MAAM,CAAC,oFAA8D,gDAAgDA,4BAAW,MAAMA,4BAAW,MAAM,CAAC,KAC3S,EAAE,OAAO,QAAQ,CAClB;AACD;;EAGF,MAAM,2BAAqC,OAAO,KAChD,2BACD;AAED,MAAI,SAAS,cAAc;GAEzB,MAAM,iCAAiC,QAAQ,aAAa,QACzD,iBAAiB,CAAC,yBAAyB,SAAS,aAAa,CACnE;AAED,OAAI,+BAA+B,SAAS,EAC1C,WACE,4CAA4C,+BAA+B,KACzE,KACD,CAAC,0BACF,EACE,OAAO,SACR,CACF;AAIH,kBAAe,aAAa,QAAQ,eAClC,QAAQ,cAAc,SAAS,WAAW,IAAI,CAC/C;;AAGH,MAAI,SAAS,YAAY;GACvB,MAAM,WAAW,2CAAmB,QAAQ,WAAW;AAEvD,kBAAe,aAAa,QAAQ,eAClC,SAAS,6BACF,OAAO,QAAQ,SAAS,WAAW,YAAY,GAAG,CACxD,CACF;;AAIH,MAAI,aAAa,WAAW,GAAG;AAC7B,aAAU,+BAA+B,EACvC,OAAO,SACR,CAAC;AACF;;AAGF,YAAU,wBAAwB;EAGlC,MAAM,uBAA6C,aAAa,KAC7D,gBAAgB;GACf;GACA,QAAQ;GACT,EACF;EAGD,MAAM,SAAS,IAAIE,4BAAY;AAC/B,SAAO,OACL,qBAAqB,KAAiB,OAAO;GAC3C,eAAe,EAAE,WAAW;GAC5B,QAAQ;GACT,EAAE,CACJ;EAED,MAAM,iCAA+C,EAAE;EAEvD,MAAM,oBAAoB,OACxB,cACkB;AAClB,aAAU,SAAS;AACnB,UAAO,OAAO,CACZ;IAAE,eAAe,UAAU,WAAW;IAAK,QAAQ;IAAW,CAC/D,CAAC;AAEF,OAAI;IACF,MAAM,aAAa,MAAM,YAAY,WAAW,iBAAiB,CAC/D,UAAU,WACX,CAAC;IAEF,MAAM,sBAAsB,WAAW,MAAM,uBAAuB,EAAE;IACtE,MAAM,kBAAkB,WAAW,MAAM,mBAAmB,EAAE;IAE9D,MAAM,kBAAkB,CAAC,GAAG,qBAAqB,GAAG,gBAAgB;AAEpE,SAAK,MAAM,wBAAwB,iBAAiB;KAClD,MAAM,kBAAkB,2BACtB,qBAAqB,MACpB,MACA,eAAe,WAAW,YAAY,qBAAqB,QAC7D;AAED,SAAI,CAAC,gBAAiB;AAEtB,2DACE;MAAE,GAAG;MAAiB,IAAI,qBAAqB;MAAI,EACnD,OACD;;AAGH,QACE,oBAAoB,MACjB,eAAe,WAAW,QAAQ,UAAU,WAAW,IACzD,EACD;AACA,eAAU,SAAS;AACnB,oCAA+B,KAAK,UAAU,WAAW;AACzD,YAAO,OAAO,CACZ;MAAE,eAAe,UAAU,WAAW;MAAK,QAAQ;MAAY,CAChE,CAAC;eAEF,gBAAgB,MACb,eAAe,WAAW,QAAQ,UAAU,WAAW,IACzD,EACD;AACA,eAAU,SAAS;AACnB,oCAA+B,KAAK,UAAU,WAAW;AACzD,YAAO,OAAO,CACZ;MAAE,eAAe,UAAU,WAAW;MAAK,QAAQ;MAAU,CAC9D,CAAC;UAEF,WAAU,SAAS;YAEd,OAAO;AACd,cAAU,SAAS;AACnB,cAAU,QAAQ;AAClB,cAAU,eAAe,4BAA4B,UAAU,WAAW,IAAI,IAAI;AAClF,WAAO,OAAO,CACZ;KAAE,eAAe,UAAU,WAAW;KAAK,QAAQ;KAAS,CAC7D,CAAC;;;AAKN,4CAAkB,sBAAsB,mBAAmB,EAAE;AAG7D,SAAO,QAAQ;AAEf,OAAK,MAAM,oBAAoB,sBAAsB;GACnD,MAAM,EAAE,MAAM,UAAU,gBAAgB,iBAAiB,OAAO;AAChE,aACE,wCAAkB,iBAAiB,WAAW,IAAI,CAAC,GAAGF,4BAAW,KAAK,GAAG,QAAQ,KAAK,GAAG,iBAAiB,SAASA,4BAAW,KAAK,GAAGA,4BAAW,QAClJ;;AAIH,OAAK,MAAM,aAAa,qBACtB,KAAI,UAAU,aACZ,WAAU,UAAU,cAAc,EAChC,OAAO,SACR,CAAC;EAKN,MAAM,eAAe,SAAS;EAC9B,MAAM,aAAa,SAAS;AAE5B,MAAI,gBAAgB,WAClB,OAAM,IAAI,MACR,mFACD;AAGH,MAAI,aAEF,OAAM,wBAAwB,gCAAgC,QAAQ;WAC7D,YAAY,QAEhB;GAEL,MAAM,qBAAqB,+BAA+B,QACvD,eAAe,WAAW,aAAa,SACzC;GACD,MAAM,yBAAyB,mBAAmB,KAC/C,eAAe,WAAW,IAC5B;GACD,MAAM,SAAS,MAAM,QACnB,8GAAwF,kBAAkBA,4BAAW,MAAMA,4BAAW,MAAM,CAAC,qCAAe,uBAAuB,kCAAY,KAAKA,4BAAW,MAAMA,4BAAW,MAAM,CAAC,kCAAY,YAAYA,4BAAW,WAAWA,4BAAW,MAAM,CAAC,IACxS;AACD,OAAI,OAAO,aAAa,KAAK,SAAS,OAAO,aAAa,KAAK,IAC7D,OAAM,wBAAwB,oBAAoB,QAAQ;;UAGvD,OAAO;AACd,YAAU,OAAO,EACf,OAAO,SACR,CAAC;;;AAIN,MAAM,WAAW,aAAsC;CACrD,MAAM,KAAKG,cAAS,gBAAgB;EAClC,OAAO,QAAQ;EACf,QAAQ,QAAQ;EACjB,CAAC;AACF,QAAO,IAAI,SAAS,YAAY;AAC9B,KAAG,SAAS,WAAW,WAAmB;AACxC,MAAG,OAAO;AACV,WAAQ,OAAO;IACf;GACF;;AAGJ,MAAM,0BAA0B,OAC9B,sBACA,YACkB;CAElB,MAAM,sFAD0B,SAAS,cAAc,CACjB;CAGtC,MAAM,+BAA4B,IAAI,KAAK;AAE3C,MAAK,MAAM,cAAc,sBAAsB;EAC7C,MAAM,EAAE,aAAa;AAErB,MAAI,CAAC,UAAU;AACb,aACE,gDAA0B,WAAW,IAAI,CAAC,6BAC1C,EACE,OAAO,SACR,CACF;AACD;;AAGF,eAAa,IAAI,SAAS;;AAG5B,MAAK,MAAM,YAAY,aACrB,KAAI;EACF,MAAM,QAAQ,MAAMC,iBAAW,MAAM,SAAS;AAE9C,MAAI,MAAM,QAAQ,EAAE;AAClB,SAAMA,iBAAW,OAAO,SAAS;AACjC,aAAU,mDAA2B,SAAS,IAAI,EAAE,CAAC;aAC5C,MAAM,aAAa,CAC5B,WAAU,0DAAkC,SAAS,CAAC,cAAc,EAAE,CAAC;MAEvE,WACE,4DAAoC,SAAS,CAAC,cAC9C,EAAE,CACH;UAEI,KAAK;AACZ,YAAU,qDAA6B,SAAS,CAAC,IAAI,OAAO,EAC1D,OAAO,SACR,CAAC"}
|
package/dist/cjs/pushConfig.cjs
CHANGED
|
@@ -6,7 +6,7 @@ let _intlayer_config = require("@intlayer/config");
|
|
|
6
6
|
//#region src/pushConfig.ts
|
|
7
7
|
const pushConfig = async (options) => {
|
|
8
8
|
const config = (0, _intlayer_config.getConfiguration)(options?.configOptions);
|
|
9
|
-
const appLogger = (0, _intlayer_config.getAppLogger)(config
|
|
9
|
+
const appLogger = (0, _intlayer_config.getAppLogger)(config);
|
|
10
10
|
if (!await require_utils_checkAccess.checkCMSAuth(config, false)) return;
|
|
11
11
|
const getDictionariesKeysResult = await (0, _intlayer_api.getIntlayerAPIProxy)(void 0, config).project.pushProjectConfiguration(config);
|
|
12
12
|
if (!getDictionariesKeysResult.data) throw new Error("Error pushing project configuration");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pushConfig.cjs","names":["checkCMSAuth"],"sources":["../../src/pushConfig.ts"],"sourcesContent":["import { getIntlayerAPIProxy } from '@intlayer/api';\nimport {\n type GetConfigurationOptions,\n getAppLogger,\n getConfiguration,\n} from '@intlayer/config';\nimport { checkCMSAuth } from './utils/checkAccess';\n\ntype PushOptions = {\n configOptions?: GetConfigurationOptions;\n};\n\nexport const pushConfig = async (options?: PushOptions) => {\n const config = getConfiguration(options?.configOptions);\n const appLogger = getAppLogger(config
|
|
1
|
+
{"version":3,"file":"pushConfig.cjs","names":["checkCMSAuth"],"sources":["../../src/pushConfig.ts"],"sourcesContent":["import { getIntlayerAPIProxy } from '@intlayer/api';\nimport {\n type GetConfigurationOptions,\n getAppLogger,\n getConfiguration,\n} from '@intlayer/config';\nimport { checkCMSAuth } from './utils/checkAccess';\n\ntype PushOptions = {\n configOptions?: GetConfigurationOptions;\n};\n\nexport const pushConfig = async (options?: PushOptions) => {\n const config = getConfiguration(options?.configOptions);\n const appLogger = getAppLogger(config);\n\n const hasCMSAuth = await checkCMSAuth(config, false);\n\n if (!hasCMSAuth) return;\n\n const intlayerAPI = getIntlayerAPIProxy(undefined, config);\n\n // Push the project configuration\n const getDictionariesKeysResult =\n await intlayerAPI.project.pushProjectConfiguration(config);\n\n if (!getDictionariesKeysResult.data) {\n throw new Error('Error pushing project configuration');\n }\n\n appLogger('Project configuration pushed successfully');\n\n appLogger(JSON.stringify(getDictionariesKeysResult.data, null, 2));\n};\n"],"mappings":";;;;;;AAYA,MAAa,aAAa,OAAO,YAA0B;CACzD,MAAM,gDAA0B,SAAS,cAAc;CACvD,MAAM,+CAAyB,OAAO;AAItC,KAAI,CAFe,MAAMA,uCAAa,QAAQ,MAAM,CAEnC;CAKjB,MAAM,4BACJ,6CAJsC,QAAW,OAAO,CAItC,QAAQ,yBAAyB,OAAO;AAE5D,KAAI,CAAC,0BAA0B,KAC7B,OAAM,IAAI,MAAM,sCAAsC;AAGxD,WAAU,4CAA4C;AAEtD,WAAU,KAAK,UAAU,0BAA0B,MAAM,MAAM,EAAE,CAAC"}
|
package/dist/cjs/pushLog.cjs
CHANGED
|
@@ -9,11 +9,7 @@ var PushLogger = class {
|
|
|
9
9
|
renderedLines = 0;
|
|
10
10
|
spinnerFrames = _intlayer_config.spinnerFrames;
|
|
11
11
|
isFinished = false;
|
|
12
|
-
prefix;
|
|
13
12
|
lastRenderedState = "";
|
|
14
|
-
constructor() {
|
|
15
|
-
this.prefix = (0, _intlayer_config.getConfiguration)().log.prefix;
|
|
16
|
-
}
|
|
17
13
|
update(newStatuses) {
|
|
18
14
|
if (this.isFinished) return;
|
|
19
15
|
for (const status of newStatuses) {
|
|
@@ -46,14 +42,14 @@ var PushLogger = class {
|
|
|
46
42
|
const frame = this.spinnerFrames[this.spinnerIndex];
|
|
47
43
|
const lines = [];
|
|
48
44
|
const isDone = done === total;
|
|
49
|
-
const progressLabel = `dictionaries: ${done}/${total}`;
|
|
45
|
+
const progressLabel = `dictionaries: ${(0, _intlayer_config.colorizeNumber)(done)}/${(0, _intlayer_config.colorizeNumber)(total)}`;
|
|
50
46
|
const details = [];
|
|
51
|
-
if (pushed > 0) details.push(`new: ${pushed}`);
|
|
52
|
-
if (modified > 0) details.push(`modified: ${modified}`);
|
|
53
|
-
if (errors > 0) details.push((0, _intlayer_config.colorize)(`errors: ${errors}`, _intlayer_config.ANSIColors.RED));
|
|
47
|
+
if (pushed > 0) details.push(`new: ${(0, _intlayer_config.colorizeNumber)(pushed)}`);
|
|
48
|
+
if (modified > 0) details.push(`modified: ${(0, _intlayer_config.colorizeNumber)(modified)}`);
|
|
49
|
+
if (errors > 0) details.push((0, _intlayer_config.colorize)(`errors: ${(0, _intlayer_config.colorizeNumber)(errors)}`, _intlayer_config.ANSIColors.RED));
|
|
54
50
|
const suffix = details.length > 0 ? ` (${details.join(", ")})` : "";
|
|
55
|
-
if (isDone) lines.push(`${
|
|
56
|
-
else lines.push(`${
|
|
51
|
+
if (isDone) lines.push(`${(0, _intlayer_config.colorize)("✔", _intlayer_config.ANSIColors.GREEN)} pushed ${progressLabel}${suffix}`);
|
|
52
|
+
else lines.push(`${(0, _intlayer_config.colorize)(frame, _intlayer_config.ANSIColors.BLUE)} pushing ${progressLabel}${suffix}`);
|
|
57
53
|
const currentState = lines.join("\n");
|
|
58
54
|
if (currentState === this.lastRenderedState) return;
|
|
59
55
|
this.lastRenderedState = currentState;
|
package/dist/cjs/pushLog.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pushLog.cjs","names":["spinnerFrames","ANSIColors"],"sources":["../../src/pushLog.ts"],"sourcesContent":["import {\n ANSIColors,\n colorize,\n
|
|
1
|
+
{"version":3,"file":"pushLog.cjs","names":["spinnerFrames","ANSIColors"],"sources":["../../src/pushLog.ts"],"sourcesContent":["import {\n ANSIColors,\n colorize,\n colorizeNumber,\n spinnerFrames,\n} from '@intlayer/config';\n\nexport type PushStatus = {\n dictionaryKey: string;\n status: 'pending' | 'pushing' | 'pushed' | 'modified' | 'error';\n errorMessage?: string;\n};\n\nexport class PushLogger {\n private statuses: PushStatus[] = [];\n private spinnerTimer: NodeJS.Timeout | null = null;\n private spinnerIndex = 0;\n private renderedLines = 0;\n private readonly spinnerFrames = spinnerFrames;\n private isFinished = false;\n private lastRenderedState: string = '';\n\n update(newStatuses: PushStatus[]) {\n if (this.isFinished) return;\n for (const status of newStatuses) {\n const index = this.statuses.findIndex(\n (s) => s.dictionaryKey === status.dictionaryKey\n );\n if (index >= 0) {\n this.statuses[index] = status;\n } else {\n this.statuses.push(status);\n }\n }\n\n this.startSpinner();\n this.render();\n }\n\n finish() {\n this.isFinished = true;\n this.stopSpinner();\n this.render();\n }\n\n private startSpinner() {\n if (this.spinnerTimer || this.isFinished) return;\n this.spinnerTimer = setInterval(() => {\n this.spinnerIndex = (this.spinnerIndex + 1) % this.spinnerFrames.length;\n this.render();\n }, 100);\n }\n\n private stopSpinner() {\n if (!this.spinnerTimer) return;\n clearInterval(this.spinnerTimer);\n this.spinnerTimer = null;\n }\n\n private render() {\n const { total, done, pushed, modified, errors } = this.computeProgress();\n\n const frame = this.spinnerFrames[this.spinnerIndex];\n const lines: string[] = [];\n\n const isDone = done === total;\n\n const progressLabel = `dictionaries: ${colorizeNumber(done)}/${colorizeNumber(total)}`;\n const details: string[] = [];\n if (pushed > 0) details.push(`new: ${colorizeNumber(pushed)}`);\n if (modified > 0) details.push(`modified: ${colorizeNumber(modified)}`);\n if (errors > 0)\n details.push(\n colorize(`errors: ${colorizeNumber(errors)}`, ANSIColors.RED)\n );\n\n const suffix = details.length > 0 ? ` (${details.join(', ')})` : '';\n\n if (isDone) {\n lines.push(\n `${colorize('✔', ANSIColors.GREEN)} pushed ${progressLabel}${suffix}`\n );\n } else {\n lines.push(\n `${colorize(frame, ANSIColors.BLUE)} pushing ${progressLabel}${suffix}`\n );\n }\n\n const currentState = lines.join('\\n');\n if (currentState === this.lastRenderedState) {\n return;\n }\n this.lastRenderedState = currentState;\n\n if (this.renderedLines > 0) {\n process.stdout.write(`\\x1b[${this.renderedLines}F`);\n }\n\n const totalLinesToClear = Math.max(this.renderedLines, lines.length);\n for (let i = 0; i < totalLinesToClear; i++) {\n process.stdout.write('\\x1b[2K');\n const line = lines[i];\n if (line !== undefined) {\n process.stdout.write(line);\n }\n process.stdout.write('\\n');\n }\n\n this.renderedLines = lines.length;\n }\n\n private computeProgress() {\n const keys = new Set(this.statuses.map((s) => s.dictionaryKey));\n\n const pushed = this.statuses.filter((s) => s.status === 'pushed').length;\n const modified = this.statuses.filter(\n (s) => s.status === 'modified'\n ).length;\n const errors = this.statuses.filter((s) => s.status === 'error').length;\n const done = pushed + modified + errors;\n\n return {\n total: keys.size,\n done,\n pushed,\n modified,\n errors,\n } as const;\n }\n}\n"],"mappings":";;;;AAaA,IAAa,aAAb,MAAwB;CACtB,AAAQ,WAAyB,EAAE;CACnC,AAAQ,eAAsC;CAC9C,AAAQ,eAAe;CACvB,AAAQ,gBAAgB;CACxB,AAAiB,gBAAgBA;CACjC,AAAQ,aAAa;CACrB,AAAQ,oBAA4B;CAEpC,OAAO,aAA2B;AAChC,MAAI,KAAK,WAAY;AACrB,OAAK,MAAM,UAAU,aAAa;GAChC,MAAM,QAAQ,KAAK,SAAS,WACzB,MAAM,EAAE,kBAAkB,OAAO,cACnC;AACD,OAAI,SAAS,EACX,MAAK,SAAS,SAAS;OAEvB,MAAK,SAAS,KAAK,OAAO;;AAI9B,OAAK,cAAc;AACnB,OAAK,QAAQ;;CAGf,SAAS;AACP,OAAK,aAAa;AAClB,OAAK,aAAa;AAClB,OAAK,QAAQ;;CAGf,AAAQ,eAAe;AACrB,MAAI,KAAK,gBAAgB,KAAK,WAAY;AAC1C,OAAK,eAAe,kBAAkB;AACpC,QAAK,gBAAgB,KAAK,eAAe,KAAK,KAAK,cAAc;AACjE,QAAK,QAAQ;KACZ,IAAI;;CAGT,AAAQ,cAAc;AACpB,MAAI,CAAC,KAAK,aAAc;AACxB,gBAAc,KAAK,aAAa;AAChC,OAAK,eAAe;;CAGtB,AAAQ,SAAS;EACf,MAAM,EAAE,OAAO,MAAM,QAAQ,UAAU,WAAW,KAAK,iBAAiB;EAExE,MAAM,QAAQ,KAAK,cAAc,KAAK;EACtC,MAAM,QAAkB,EAAE;EAE1B,MAAM,SAAS,SAAS;EAExB,MAAM,gBAAgB,sDAAgC,KAAK,CAAC,wCAAkB,MAAM;EACpF,MAAM,UAAoB,EAAE;AAC5B,MAAI,SAAS,EAAG,SAAQ,KAAK,6CAAuB,OAAO,GAAG;AAC9D,MAAI,WAAW,EAAG,SAAQ,KAAK,kDAA4B,SAAS,GAAG;AACvE,MAAI,SAAS,EACX,SAAQ,oCACG,gDAA0B,OAAO,IAAIC,4BAAW,IAAI,CAC9D;EAEH,MAAM,SAAS,QAAQ,SAAS,IAAI,KAAK,QAAQ,KAAK,KAAK,CAAC,KAAK;AAEjE,MAAI,OACF,OAAM,KACJ,kCAAY,KAAKA,4BAAW,MAAM,CAAC,UAAU,gBAAgB,SAC9D;MAED,OAAM,KACJ,kCAAY,OAAOA,4BAAW,KAAK,CAAC,WAAW,gBAAgB,SAChE;EAGH,MAAM,eAAe,MAAM,KAAK,KAAK;AACrC,MAAI,iBAAiB,KAAK,kBACxB;AAEF,OAAK,oBAAoB;AAEzB,MAAI,KAAK,gBAAgB,EACvB,SAAQ,OAAO,MAAM,QAAQ,KAAK,cAAc,GAAG;EAGrD,MAAM,oBAAoB,KAAK,IAAI,KAAK,eAAe,MAAM,OAAO;AACpE,OAAK,IAAI,IAAI,GAAG,IAAI,mBAAmB,KAAK;AAC1C,WAAQ,OAAO,MAAM,UAAU;GAC/B,MAAM,OAAO,MAAM;AACnB,OAAI,SAAS,OACX,SAAQ,OAAO,MAAM,KAAK;AAE5B,WAAQ,OAAO,MAAM,KAAK;;AAG5B,OAAK,gBAAgB,MAAM;;CAG7B,AAAQ,kBAAkB;EACxB,MAAM,OAAO,IAAI,IAAI,KAAK,SAAS,KAAK,MAAM,EAAE,cAAc,CAAC;EAE/D,MAAM,SAAS,KAAK,SAAS,QAAQ,MAAM,EAAE,WAAW,SAAS,CAAC;EAClE,MAAM,WAAW,KAAK,SAAS,QAC5B,MAAM,EAAE,WAAW,WACrB,CAAC;EACF,MAAM,SAAS,KAAK,SAAS,QAAQ,MAAM,EAAE,WAAW,QAAQ,CAAC;EACjE,MAAM,OAAO,SAAS,WAAW;AAEjC,SAAO;GACL,OAAO,KAAK;GACZ;GACA;GACA;GACA;GACD"}
|